PHP项目Laravel邮件队列发送配置

wen PHP项目 3

本文目录导读:

PHP项目Laravel邮件队列发送配置

  1. 基础配置
  2. 数据库驱动配置(最简单)
  3. 实现示例
  4. 发送邮件的三种方式
  5. 启动队列工作者
  6. Supervisor 配置(生产环境)
  7. 失败任务处理
  8. 高级配置
  9. 测试邮件
  10. 注意事项

在Laravel中配置邮件队列发送是一个常见的需求,我来详细说明完整的配置步骤:

基础配置

环境配置 (.env文件)

# 邮件配置
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-app-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=from@example.com
MAIL_FROM_NAME="${APP_NAME}"
# 队列配置(推荐使用 Redis 或数据库)
QUEUE_CONNECTION=database
# 或
QUEUE_CONNECTION=redis

数据库驱动配置(最简单)

生成迁移文件

php artisan queue:table
php artisan migrate

创建邮件类

php artisan make:mail OrderShipped

实现示例

创建邮件类(app/Mail/TestQueueMail.php)

<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class TestQueueMail extends Mailable
{
    use Queueable, SerializesModels;
    public $data;
    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($data)
    {
        $this->data = $data;
    }
    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this
            ->from(config('mail.from.address'), config('mail.from.name'))
            ->subject('测试队列邮件')
            ->view('emails.test')
            ->with(['data' => $this->data]);
    }
}

创建邮件视图(resources/views/emails/test.blade.php)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">测试邮件</title>
</head>
<body>
    <h1>这是一封队列测试邮件</h1>
    <p>发送时间:{{ now() }}</p>
    <p>数据内容:{{ $data['message'] ?? '默认内容' }}</p>
</body>
</html>

发送邮件的三种方式

延迟发送(推入队列)

use App\Mail\TestQueueMail;
public function sendMail(Request $request)
{
    $data = ['message' => '这是测试邮件内容'];
    $recipient = 'recipient@example.com';
    // 推入队列发送
    Mail::to($recipient)->queue(new TestQueueMail($data));
    // 延迟5分钟发送
    Mail::to($recipient)->later(now()->addMinutes(5), new TestQueueMail($data));
    // 也可以使用 Job 方式
    dispatch(new SendMailJob($recipient, $data));
    return response()->json(['status' => 'success', 'message' => '邮件已在队列中']);
}

创建专用Job

php artisan make:job SendMailJob
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
use App\Mail\TestQueueMail;
class SendMailJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    protected $recipient;
    protected $data;
    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($recipient, $data)
    {
        $this->recipient = $recipient;
        $this->data = $data;
    }
    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        try {
            Mail::to($this->recipient)->send(new TestQueueMail($this->data));
            \Log::info('邮件发送成功', [
                'recipient' => $this->recipient,
                'time' => now()
            ]);
        } catch (\Exception $e) {
            \Log::error('邮件发送失败', [
                'recipient' => $this->recipient,
                'error' => $e->getMessage()
            ]);
            // 如果失败,重新尝试3次
            if ($this->attempts() < 3) {
                $this->release(10); // 10秒后重试
            }
        }
    }
    /**
     * 定义失败回调
     */
    public function failed(\Throwable $exception)
    {
        \Log::error('邮件发送最终失败', [
            'recipient' => $this->recipient,
            'error' => $exception->getMessage()
        ]);
    }
}

实现 ShouldQueue 接口

<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class TestQueueMail extends Mailable implements ShouldQueue
{
    use Queueable, SerializesModels;
    // 其他代码...
    // 设置队列连接
    public $connection = 'database';
    // 设置队列名称
    public $queue = 'emails';
    // 设置延迟时间
    public $delay = 0;
    // 设置重试次数
    public $tries = 3;
    // 设置超时时间(秒)
    public $timeout = 60;
}

启动队列工作者

# 基本启动
php artisan queue:work
# 指定队列
php artisan queue:work --queue=emails
# 指定连接
php artisan queue:work database --queue=emails
# 后台守护进程运行
php artisan queue:work --daemon
# 只处理一次任务
php artisan queue:work --once
# 配合 Supervisor 使用(生产环境推荐)

Supervisor 配置(生产环境)

创建文件 /etc/supervisor/conf.d/laravel-worker.conf

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=8
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/worker.log
stopwaitsecs=3600

失败任务处理

# 查看失败任务
php artisan queue:failed
# 重试失败任务
php artisan queue:retry all
# 删除失败任务
php artisan queue:forget all
# 清空失败任务
php artisan queue:flush

高级配置

多个邮件配置

// config/mail.php
return [
    'mailers' => [
        'smtp' => [...],
        'sendmail' => [...],
        'mailgun' => [...],
        'ses' => [...],
        'postmark' => [...],
        'log' => [...],
        'array' => [...],
        'failover' => [
            'transport' => 'failover',
            'mailers' => ['smtp', 'mailgun'],
        ],
    ],
];

邮件队列监控

// 使用 Laravel Horizon(推荐用于 Redis)
composer require laravel/horizon
php artisan horizon:install
php artisan migrate

测试邮件

// 在测试环境使用 array 驱动,不会真正发送邮件
MAIL_MAILER=array
// 记录到日志
MAIL_MAILER=log

注意事项

  1. 生产环境一定要使用 Supervisor 或进程管理工具监控队列进程
  2. 及时处理失败任务,避免邮件积压
  3. 设置合适的重试次数超时时间
  4. 使用日志记录邮件发送的状态
  5. 考虑使用邮件服务商的 API 接口(如 Mailgun、SES)提高发送效率
  6. 批量邮件建议使用单独专用队列

这样就完成了 Laravel 邮件队列发送的完整配置,根据实际需求选择最简单的配置方式即可。

抱歉,评论功能暂时关闭!