在 Laravel 7.x 中如何识别邮件是否是使用 Mail::send() 或 Mail::queue() 触发的

问题描述 投票:0回答:1

我在 Laravel7.x 中有如下代码

Mail::queue(new ReportMail($user));
Mail::send(new ReportMail($user));

在 ReportMail 类中,有没有办法知道邮件是否被调用 Mail::send() 或 Mail::queue() ?

我的所有邮件 MailClass 在发送邮件之前都会经过 MailTrait 函数。

在那里我使用了如下的节流功能:

// somewhere in the file - app/Traits/MailTrait.php
Redis::throttle('emails')
    ->allow(300)    // Maximum number of allowed operations
    ->every(60)     // Time period in seconds for the rate limit
    ->block(60)     // Blocking time (seconds) if rate limit is exceeded
    ->then(
    function () use ($mailTemplateObj) {
        $this->sendFinalizedMail($mailTemplateObj);
    },
    function () {
        Log::info('Throttling, Too many email requests received!');
    }
);

这对于排队的邮件效果很好...但是当队列仍在处理中时触发发送邮件时。不知何故,这会破坏队列并需要重新启动。

所以我需要在我们的MailClass中弄清楚:在ReportMail中,如果邮件是send()或queue(),并避免使用redis::throttle()来处理mail::send()

我可以通过向 ReportMail 类添加一个标志来解决这个问题,但问题是我有关于 300 个这样的邮件类,我需要在每个类中实现,这感觉不是解决这个问题的好方法......

非常感谢你们的任何好主意...... 谢谢。

php laravel redis
1个回答
0
投票

为了在不单独修改每个 MailClass 的情况下实现此目的,您可以利用 Laravel 事件系统在邮件通过队列发送时设置一个标志。 创建自定义事件类

    // app/Events/MailSentEvent.php

namespace App\Events;

use Illuminate\Queue\SerializesModels;

class MailSentEvent
{
    use SerializesModels;

    public $isQueued;

    public function __construct($isQueued)
    {
        $this->isQueued = $isQueued;
    }
}

修改您的 MailTrait 以在发送邮件时调度事件

// app/Traits/MailTrait.php

use App\Events\MailSentEvent;
use Illuminate\Support\Facades\Event;

// ...

public function sendFinalizedMail($mailTemplateObj, $isQueued = false)
{
    Redis::throttle('emails')
        ->allow(300)
        ->every(60)
        ->block(60)
        ->then(
            function () use ($mailTemplateObj, $isQueued) {
                $this->sendFinalizedMail($mailTemplateObj);
                Event::dispatch(new MailSentEvent($isQueued));
            },
            function () {
                Log::info('Throttling, Too many email requests received!');
            }
        );
}

在 ReportMail 类中,在应用限制之前检查标志

// app/Mail/ReportMail.php

use App\Events\MailSentEvent;
use Illuminate\Support\Facades\Event;
use Illuminate\Mail\Mailable;

class ReportMail extends Mailable
{
    public function build()
    {
        // ...

        $isQueued = Event::hasListeners(MailSentEvent::class);

        // Use $isQueued to determine if the mail is sent through queue or not
        if (!$isQueued) {
            Redis::throttle('emails')
                ->allow(300)
                ->every(60)
                ->block(60)
                ->then(
                    function () {
                        $this->sendFinalizedMail($mailTemplateObj);
                    },
                    function () {
                        Log::info('Throttling, Too many email requests received!');
                    }
                );
        } else {
            $this->sendFinalizedMail($mailTemplateObj, true);
        }
    }
}

这样,您可以将逻辑集中在 MailTrait 中,并使用事件系统动态设置标志。这减少了单独修改每个 MailClass 的需要。

© www.soinside.com 2019 - 2024. All rights reserved.