如何处理已执行的邮件队列任务并记录详情至log_mail表
解决思路及实现方案
方案一:监听邮件发送成功事件(推荐)
Laravel 内置了邮件发送成功的MessageSent事件,直接监听该事件即可在邮件发送完成后自动记录日志,无需修改原有的队列发送逻辑。
- 生成事件监听器
执行Artisan命令创建监听器:
php artisan make:listener LogSentMail
- 编写监听器逻辑
在生成的app/Listeners/LogSentMail.php中,提取邮件信息并存入log_mail表:
<?php namespace App\Listeners; use Illuminate\Mail\Events\MessageSent; use Illuminate\Support\Facades\DB; class LogSentMail { public function handle(MessageSent $event) { $swiftMessage = $event->message; // 提取收件人/抄送人(SwiftMailer返回键为邮箱、值为名称的数组,取邮箱部分) $to = collect($swiftMessage->getTo())->keys()->implode(','); $cc = collect($swiftMessage->getCc())->keys()->implode(','); // 提取邮件标题和正文 $subject = $swiftMessage->getSubject(); $body = $swiftMessage->getBody(); // HTML邮件返回HTML内容,纯文本邮件返回文本内容 // 写入日志表 DB::table('log_mail')->insert([ 'to' => $to, 'cc' => $cc, 'subject' => $subject, 'body' => $body, 'sent_at' => now(), 'created_at' => now(), 'updated_at' => now(), ]); } }
- 注册事件与监听器
打开app/Providers/EventServiceProvider.php,在$listen数组中添加事件关联:
protected $listen = [ // 其他事件... \Illuminate\Mail\Events\MessageSent::class => [ \App\Listeners\LogSentMail::class, ], ];
方案二:在自定义Job中手动记录(适用于需额外业务逻辑的场景)
如果邮件发送在自定义Job中执行,可在邮件发送完成后直接添加日志逻辑,同时处理队列执行失败的情况:
public function handle() { // job logic... // 发送邮件并捕获结果 try { Mail::to($email)->queue(new TasksFinished($msg)); // 若需确保邮件发送成功后再记录,优先用方案一;此处为Job执行成功后的记录 $this->logMail($email, $msg); } catch (\Exception $e) { // 记录发送失败日志 DB::table('log_mail')->insert([ 'to' => $email, 'subject' => '任务完成通知', // 可从Mailable类中直接获取 'body' => $msg, 'sent_at' => null, 'status' => 'failed', 'error_msg' => $e->getMessage(), 'created_at' => now(), 'updated_at' => now(), ]); throw $e; // 抛出异常让队列触发重试 } } private function logMail($email, $msg) { $mailable = new TasksFinished($msg); $mailable->build(); // 构建邮件以获取标题等信息 DB::table('log_mail')->insert([ 'to' => $email, 'subject' => $mailable->subject, 'body' => $mailable->render(), // 获取渲染后的HTML正文 'sent_at' => now(), 'created_at' => now(), 'updated_at' => now(), ]); }
注意事项
- 方案一可覆盖同步、队列等所有邮件发送场景,只要邮件发送成功就会自动记录日志,适用性更广。
- 处理收件人/抄送人时,需注意SwiftMailer返回的数组格式,可根据需求调整拼接方式。
- 若需记录附件、发送状态等额外信息,可从
$swiftMessage对象中进一步提取字段存入日志表。
内容的提问来源于stack exchange,提问作者Paos
相关产品推荐
相关产品推荐

