对 Laravel 5 发送邮件队列感到困惑 (Laravel 5.4)

Confused about Laravel 5 Queue for Sending Mail (Laravel 5.4)

我从Laravel4.1升级到5.4。队列迁移困难

首先,我从 routes:

中注释掉了 iron route
Route::post('queue/receive', function()
{
    return Queue::marshal();
});

然后,我配置了数据库驱动并迁移了jobs table:

php artisan queue:table
php artisan migrate

我将 Mail::queue 代码更改为 Mailables,如下所示:

Mail::to('person@gmail.com')->send(new ForgotPassword($user->first_name));

同步发送邮件成功(无队列)。然后,我切换到队列:

Mail::to('person@gmail.com')->queue(new ForgotPassword($user->first_name));

最后,我 运行 来自控制台的命令:

php artisan queue:listen

当执行 Mail::to 行时,会在 Jobs table 中插入一行,但不会发送邮件。我该如何解决这个问题?

注:ForgotPassword是一个Mailableclass(应该是Jobclass?)。

您可能需要编辑计算机上项目文件夹中现有的 .env 文件。 找到.env文件,通过sublime text打开并编辑。

使用您要发送邮件的电子邮件 ID 和密码进行编辑。

您可以使用 laravel 队列发送邮件,请参阅示例,

定义作业

public function handle()
{
        $mail_meta_data = $this->send_data;
        $require_data = $this->require_data;
        Mail::queue($mail_meta_data['view_name'], ['data'=>$require_data], function($message) use ($mail_meta_data, $require_data) {
            //$message->from($mail_meta_data['to'], $mail_meta_data['name']);

            $message->to($mail_meta_data['to'])->subject($mail_meta_data['subject']);
        });
 }

调用作业

dispatch(new SendEmailNotification($mail_meta_data, $require_data));

.env

 MAIL_DRIVER=smtp
 MAIL_HOST=smtp.sendgrid.net
 MAIL_PORT=587
 MAIL_USERNAME=smtp_username
 MAIL_PASSWORD=smptp_password
 MAIL_ENCRYPTION=tls

 APP_EMAIL=email sent from
 APP_NAME=Name of Email sender

备注

  1. 确保您已在 .env 文件或 config/mail.php
  2. 中设置上述邮件配置
  3. 也是phpartisanqueue:listen是运行

就您的 ForgotPassword 对象而言,同步 send() 和异步 queue() 之间的主要区别在于,当您将对象排队等待发送时,它必须被序列化以发送到队列,并在队列工作者处理它时反序列化。

由于 send() 工作正常,但 queue() 发生错误,我们可以看到排队的作业被触发并试图被处理,很可能是错误serialization/unserialization.

您的 ForgotPassword class 可能正在使用 SerializesModels 特征,因为这就是 artisan 命令生成新的可邮寄对象的方式。此特征定义了 __sleep() and __wakeup() 方法,这些方法修改了序列化和反序列化的工作方式。

__sleep方法实现时,PHP只会序列化__sleep方法返回的变量。在这种情况下,SerializesModels trait 提供的实现使用反射来遍历 class 上定义的属性,以提供一种特殊的方式来序列化 Eloquent 模型和集合。

正因为如此,这意味着 ForgotPassword class 上任何未明确定义为 class 上的 属性 的变量都不会被序列化,当排队的作业被处理并且 class 被反序列化时,它将不可用。这是您遇到问题的最可能原因。当您的工作正在尝试时,您的未序列化的可邮寄实例没有它需要的数据,并且正在失败。

有两种方法可以解决这个问题。首先,如果您的 ForgotPassword 实际上不需要序列化任何模型,您可以删除 SerializedModels 特性。这将从 class 中删除 __sleep() 定义,然后在 class 上分配的所有变量,而不仅仅是那些实际定义的变量,将被序列化,并且在 class 未序列化。

第二个选项更合适也更明确,是在 ForgotPassword class.

上实际定义您需要的属性

如果您在 class 上定义属性,则可以在 class 上保留 SerializesModels 特征。但是,如果您实际上没有序列化模型,我会继续删除它。如果不需要,则无需额外的序列化开销。