You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何处理已执行的邮件队列任务并记录详情至log_mail表

解决思路及实现方案

方案一:监听邮件发送成功事件(推荐)

Laravel 内置了邮件发送成功的MessageSent事件,直接监听该事件即可在邮件发送完成后自动记录日志,无需修改原有的队列发送逻辑。

  1. 生成事件监听器
    执行Artisan命令创建监听器:
php artisan make:listener LogSentMail
  1. 编写监听器逻辑
    在生成的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(),
        ]);
    }
}
  1. 注册事件与监听器
    打开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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 14:23:21