Laravel覆盖邮件自动添加纯文本版本

Laravel override mail to automatically add plain text version

我正在对我的 Laravel 应用程序进行一些更改,以自动将纯文本版本添加到我的电子邮件中。我正在通过使用库来做到这一点

https://packagist.org/packages/html2text/html2text

我会通过 运行

获得文本版本
\Html2Text\Html2Text::convert($content)

现在我想覆盖 laravels Mailable.php buildView() 函数来自动生成文本。我的问题是:如何正确覆盖它?我可以在哪里重新申报?

Mailer 是由 Mailer Service Provider 定义的,您可以在 'providers' 下的 config/app.php 中看到它的注册,在那里您会看到:

\Illuminate\Mail\MailServiceProvider::class,

因此,您需要做的就是删除 MailServiceProvider 注册并根据您的更改创建您自己的提供程序并注册您的。

确保执行 Illuminate\Contracts\Mail\Mailer 合同。

但你不需要!

Laravel 附带的邮件程序已经支持发送电子邮件的 HTML 和普通版本。

Mailer::send() 方法的第一个参数是 @param string|array $view,您通常会在其中发送电子邮件的 HTML 版本的视图名称,但是,您也可以发送这样的数组...

Mailer::send([
    'html' => 'my-mails.notification-in-html',
    'text' => 'my-mails.notification-in-text',
  ], $data, $callback);

您甚至可以定义不同的文本并删除您不会放入纯文本版本的内容,或者调整在纯文本中看起来不错的不同签名,还可以设置不同的格式。

有关详细信息,您可以查看 Illuminate\Mail\Mailer class 中的 parseView()

所以,你有它,2 个选项:

  • 创建您自己的 Mailer 并注册它而不是默认的
  • 或者只调用带有视图数组的邮件程序。

当我需要为纯文本版本使用相同的 HTML 模板时,我按以下方式覆盖了 Mailable:

<?php

namespace App\Mail;

// [...] some other imports

use Illuminate\Mail\Mailable;

class BaseMailable extends Mailable
{
    // [...] some other code

    /**
     * Method to add plain text version by converting it from HTML version
     * Separate plain text view could be used if exists
     */
    public function viewHtmlWithPlainText($view, array $data = [])
    {
        // NOTE: we render HTML separately because HTML and Plain versions have the same data
        // and we need to pass `plain` parameter to the HTML template to render it differently
        $this->html( view($view, $this->buildViewData())->render() );

        $plainTextView = str_replace('emails.', 'emails.txt.', $view);
        $plainTextAttrs = [
            'plain' => true,
            'senderName' => config('app.name')
        ];
        if (view()->exists($plainTextView)) {
            $this->text( $plainTextView, array_merge($plainTextAttrs, $data) );
        } else {
            $this->text( $view, array_merge($plainTextAttrs, $data) );
        }

        return $this;
    }
}

然后在子 Mailable 中,您可以像之前的 view() 方法一样使用它:

<?php

namespace App\Mail;

use App\Mail\BaseMailable;

class UserResetPasswordLink extends BaseMailable
{
    public function build()
    {
        return $this
            ->subject(trans('ui.reset_password'))
            ->viewHtmlWithPlainText('emails.client.user-reset-password-link', [
                'token' => $this->token,
            ]);
    }
}

并且在模板中,您将拥有用于纯文本电子邮件的 $plain=true 变量,因此您可以 re-use HTML 纯文本模板文件

@if (empty($plain))
<div>Some HTML content</div>
@else
Some plain text content
@endif