允许用户在Laravel 9中发送其自己的SMTP设置的电子邮件
#网络开发人员 #重构 #php #laravel

在Laravel中存在各种指南,但是我发现的所有(thisthis)的所有指南只能完成Laravel 8的工作。原因是,在V9中,不再支持Swift Mailer支持Symfony Mailer。 Laravel文档显示了如何编写自己的自定义运输,但这不是我们在这里需要的。阅读此帖子时,可能会有一个软件包发送带有自定义SMTP参数的电子邮件,因此您可能需要先看一下。

Laravel在幕后做什么

我们要处理的第一件事与称为MailManager的类有关。它负责配置和解决各种运输驱动程序。我们已经知道我们要使用SMTP传输,我们只需要知道如何覆盖来自.env文件的默认配置即可。该MailManager有一种方法:

protected function getConfig(string $name)
{
    return $this->app['config']['mail.driver']
        ? $this->app['config']['mail']
        : $this->app['config']["mail.mailers.{$name}"];
}

这是我们要覆盖的方法。在这样做之前,我们需要知道框架如何解决和使用MailManager。在框架的MailServiceProvider中,我们找到了这件代码:

protected function registerIlluminateMailer()
{
    $this->app->singleton('mail.manager', function ($app) {
        return new MailManager($app);
    });
    $this->app->bind('mailer', function ($app) {
        return $app->make('mail.manager')->mailer();
    });
}

这告诉我们,要使用另一个邮件而不是默认邮件,我们必须使用MailManager的另一个实例并从中获取邮件。

实施自定义邮件

因此,我们将这个名为App\Extensions\UserMailManager的新类称为“ App\Extensions\UserMailManager”,将其放置或称其为您想要的任何东西,在创建并覆盖我们之前看到的getConfig()方法时接受配置。

namespace App\Extensions;

use Illuminate\Mail\MailManager;

class UserMailManager extends MailManager
{
    public function __construct($app, private readonly array $customConfig)
    {
        parent::__construct($app);
    }

    protected function getConfig(string $name)
    {
        return $this->customConfig;
    }
}

在您的AppServiceProvider或任何其他提供商中,我们将此新的MailManager的实例绑定到容器,这将使我们在需要时传递自定义SMTP参数。可能是一个单身人士,不确定。

class AppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind('user.mailer', function ($app, $parameters) {
            return (new UserMailManager($app, $parameters))->mailer();
        });
    }
    ...
}

到目前为止,您将使用我们的设置:

/** @var Mailer $mailer */
$mailer = app('user.mailer', $smtpParams);
$mailer->send($mailable);

这看起来并不那么方便。通常,您在users表中的列中有SMTP参数(或其他表,都没关系)。我们将通过在User模型中创建助手方法来利用它。

public function sendMail(Mailable $mailable)
{
    if ($this->smtp_enabled) {
        $smtpParams = [
            'transport' => 'smtp',
            'host' => $this->smtp_params['smtp_host'] ?? null,
            'port' => $this->smtp_params['smtp_port'] ?? null,
            'username' => $this->smtp_params['smtp_user'] ?? null,
            'password' => $this->smtp_params['smtp_password'] ?? null,
            'timeout' => null,
            'verify_peer' => false,
        ];

        /** @var Mailer $mailer */
        $mailer = app('creator.mailer', $smtpParams);
        $mailer->send($mailable);
    } else {
        Mail::send($mailable);
    }
}

将邮件与自定义SMTP参数一起使用

现在,在要使用自定义参数的代码的其他部分中,您可以将Mail::send(new TestMail($testVariable))$user->sendMail(new TestMail($testVariable))交换。方便,对吗?

如果您想排队邮件,我建议您添加一种名为queueMail($mailable, ...)的新方法,并根据您的需求进行调整。唯一的区别可能是在方法内使用$mailer->queue($mailable);

就是这样。如果这对您有所帮助,请留下大拇指,并感谢您这么远。