Skip to content

邮件

介绍

发送电子邮件不必复杂。Laravel 提供了一个由流行的 SwiftMailer 库支持的简洁、简单的电子邮件 API。Laravel 和 SwiftMailer 提供了通过 SMTP、Mailgun、Postmark、Amazon SES 和 sendmail 发送电子邮件的驱动程序,使您可以快速开始通过本地或基于云的服务发送邮件。

配置

Laravel 的电子邮件服务可以通过应用程序的 config/mail.php 配置文件进行配置。此文件中配置的每个邮件程序都可以有其独特的配置,甚至可以有其独特的“传输”,允许您的应用程序使用不同的电子邮件服务发送某些电子邮件消息。例如,您的应用程序可能使用 Postmark 发送事务性电子邮件,而使用 Amazon SES 发送批量电子邮件。

在您的 mail 配置文件中,您会发现一个 mailers 配置数组。此数组包含 Laravel 支持的主要邮件驱动程序/传输的示例配置条目,而 default 配置值决定了当您的应用程序需要发送电子邮件消息时将使用哪个邮件程序。

驱动程序/传输先决条件

基于 API 的驱动程序(如 Mailgun 和 Postmark)通常比通过 SMTP 服务器发送邮件更简单、更快。我们建议您尽可能使用这些驱动程序。所有基于 API 的驱动程序都需要 Guzzle HTTP 库,可以通过 Composer 包管理器安装:

php
composer require guzzlehttp/guzzle

Mailgun 驱动程序

要使用 Mailgun 驱动程序,首先安装 Guzzle HTTP 库。然后,将 config/mail.php 配置文件中的 default 选项设置为 mailgun。接下来,验证您的 config/services.php 配置文件包含以下选项:

php
'mailgun' => [
    'domain' => env('MAILGUN_DOMAIN'),
    'secret' => env('MAILGUN_SECRET'),
],

如果您不使用美国 Mailgun 区域,可以在 services 配置文件中定义您所在区域的端点:

php
'mailgun' => [
    'domain' => env('MAILGUN_DOMAIN'),
    'secret' => env('MAILGUN_SECRET'),
    'endpoint' => env('MAILGUN_ENDPOINT', 'api.eu.mailgun.net'),
],

Postmark 驱动程序

要使用 Postmark 驱动程序,请通过 Composer 安装 Postmark 的 SwiftMailer 传输:

php
composer require wildbit/swiftmailer-postmark

接下来,安装 Guzzle HTTP 库,并将 config/mail.php 配置文件中的 default 选项设置为 postmark。最后,验证您的 config/services.php 配置文件包含以下选项:

php
'postmark' => [
    'token' => env('POSTMARK_TOKEN'),
],

如果您想指定给定邮件程序应使用的 Postmark 消息流,可以将 message_stream_id 配置选项添加到邮件程序的配置数组中。此配置数组可以在应用程序的 config/mail.php 配置文件中找到:

php
'postmark' => [
    'transport' => 'postmark',
    'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
],

这样,您还可以设置多个具有不同消息流的 Postmark 邮件程序。

SES 驱动程序

要使用 Amazon SES 驱动程序,您必须首先安装 Amazon AWS SDK for PHP。您可以通过 Composer 包管理器安装此库:

bash
composer require aws/aws-sdk-php

接下来,将 config/mail.php 配置文件中的 default 选项设置为 ses,并验证您的 config/services.php 配置文件包含以下选项:

php
'ses' => [
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],

要通过会话令牌利用 AWS 临时凭证,可以将 token 键添加到应用程序的 SES 配置中:

php
'ses' => [
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    'token' => env('AWS_SESSION_TOKEN'),
],

如果您想定义 Laravel 应在发送电子邮件时传递给 AWS SDK 的 SendRawEmail 方法的其他选项,可以在 ses 配置中定义一个 options 数组:

php
'ses' => [
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    'options' => [
        'ConfigurationSetName' => 'MyConfigurationSet',
        'Tags' => [
            ['Name' => 'foo', 'Value' => 'bar'],
        ],
    ],
],

故障转移配置

有时,您配置为发送应用程序邮件的外部服务可能会宕机。在这些情况下,定义一个或多个备用邮件传递配置是有用的,以便在您的主要传递驱动程序宕机时使用。

为此,您应该在应用程序的 mail 配置文件中定义一个使用 failover 传输的邮件程序。应用程序的 failover 邮件程序的配置数组应包含一个 mailers 数组,该数组引用邮件驱动程序应按顺序选择进行传递的顺序:

php
'mailers' => [
    'failover' => [
        'transport' => 'failover',
        'mailers' => [
            'postmark',
            'mailgun',
            'sendmail',
        ],
    ],

    // ...
],

一旦定义了故障转移邮件程序,您应该通过在应用程序的 mail 配置文件中将其名称指定为 default 配置键的值来将其设置为应用程序使用的默认邮件程序:

php
'default' => env('MAIL_MAILER', 'failover'),

生成邮件类

在构建 Laravel 应用程序时,应用程序发送的每种类型的电子邮件都表示为一个“邮件类”。这些类存储在 app/Mail 目录中。如果您在应用程序中没有看到此目录,请不要担心,因为当您使用 make:mail Artisan 命令创建第一个邮件类时,它将为您生成:

php
php artisan make:mail OrderShipped

编写邮件类

生成邮件类后,打开它以便我们可以探索其内容。首先,请注意,邮件类的所有配置都在 build 方法中完成。在此方法中,您可以调用各种方法,如 fromsubjectviewattach 来配置电子邮件的呈现和传递。

lightbulb

您可以在邮件类的 build 方法中类型提示依赖项。Laravel 服务容器会自动注入这些依赖项。

配置发件人

使用 from 方法

首先,让我们探索配置电子邮件的发件人。换句话说,电子邮件将从谁那里发送。有两种方法可以配置发件人。首先,您可以在邮件类的 build 方法中使用 from 方法:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
    return $this->from('example@example.com', 'Example')
                ->view('emails.orders.shipped');
}

使用全局 from 地址

然而,如果您的应用程序对其所有电子邮件使用相同的“发件人”地址,那么在您生成的每个邮件类中调用 from 方法可能会变得繁琐。相反,您可以在 config/mail.php 配置文件中指定一个全局“发件人”地址。如果在邮件类中未指定其他“发件人”地址,则将使用此地址:

php
'from' => ['address' => 'example@example.com', 'name' => 'App Name'],

此外,您可以在 config/mail.php 配置文件中定义一个全局“reply_to”地址:

php
'reply_to' => ['address' => 'example@example.com', 'name' => 'App Name'],

配置视图

在邮件类的 build 方法中,您可以使用 view 方法指定在渲染电子邮件内容时应使用哪个模板。由于每封电子邮件通常使用 Blade 模板 来渲染其内容,因此在构建电子邮件的 HTML 时,您可以充分利用 Blade 模板引擎的强大功能和便利性:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped');
}
lightbulb

您可能希望创建一个 resources/views/emails 目录来存放所有电子邮件模板;但是,您可以自由地将它们放置在 resources/views 目录中的任何位置。

纯文本电子邮件

如果您想定义电子邮件的纯文本版本,可以使用 text 方法。与 view 方法一样,text 方法接受一个模板名称,该模板将用于渲染电子邮件的内容。您可以自由地定义消息的 HTML 和纯文本版本:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->text('emails.orders.shipped_plain');
}

视图数据

通过公共属性

通常,您会希望将一些数据传递给视图,以便在渲染电子邮件的 HTML 时使用。有两种方法可以使数据在视图中可用。首先,定义在邮件类上的任何公共属性将自动在视图中可用。因此,例如,您可以将数据传递到邮件类的构造函数中,并将该数据设置为类上定义的公共属性:

php
<?php

namespace App\Mail;

use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class OrderShipped extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * 订单实例。
     *
     * @var \App\Models\Order
     */
    public $order;

    /**
     * 创建一个新的消息实例。
     *
     * @param  \App\Models\Order  $order
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * 构建消息。
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped');
    }
}

一旦数据被设置为公共属性,它将自动在视图中可用,因此您可以像访问 Blade 模板中的任何其他数据一样访问它:

php
<div>
    价格: {{ $order->price }}
</div>

通过 with 方法

如果您想在将数据发送到模板之前自定义电子邮件数据的格式,可以通过 with 方法手动将数据传递给视图。通常,您仍然会通过邮件类的构造函数传递数据;但是,您应该将此数据设置为 protectedprivate 属性,以便数据不会自动在模板中可用。然后,在调用 with 方法时,传递一个您希望在模板中可用的数据数组:

php
<?php

namespace App\Mail;

use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class OrderShipped extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * 订单实例。
     *
     * @var \App\Models\Order
     */
    protected $order;

    /**
     * 创建一个新的消息实例。
     *
     * @param  \App\Models\Order  $order
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * 构建消息。
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped')
                    ->with([
                        'orderName' => $this->order->name,
                        'orderPrice' => $this->order->price,
                    ]);
    }
}

一旦数据被传递给 with 方法,它将自动在视图中可用,因此您可以像访问 Blade 模板中的任何其他数据一样访问它:

php
<div>
    价格: {{ $orderPrice }}
</div>

附件

要向电子邮件添加附件,请在邮件类的 build 方法中使用 attach 方法。attach 方法接受文件的完整路径作为其第一个参数:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->attach('/path/to/file');
}

在将文件附加到消息时,您还可以通过将 array 作为第二个参数传递给 attach 方法来指定显示名称和/或 MIME 类型:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->attach('/path/to/file', [
                    'as' => 'name.pdf',
                    'mime' => 'application/pdf',
                ]);
}

从磁盘附加文件

如果您在某个 文件系统磁盘 上存储了一个文件,可以使用 attachFromStorage 方法将其附加到电子邮件中:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
   return $this->view('emails.orders.shipped')
               ->attachFromStorage('/path/to/file');
}

如果需要,您可以使用 attachFromStorage 方法的第二个和第三个参数指定文件的附件名称和其他选项:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
   return $this->view('emails.orders.shipped')
               ->attachFromStorage('/path/to/file', 'name.pdf', [
                   'mime' => 'application/pdf'
               ]);
}

如果您需要指定默认磁盘以外的存储磁盘,可以使用 attachFromStorageDisk 方法:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
   return $this->view('emails.orders.shipped')
               ->attachFromStorageDisk('s3', '/path/to/file');
}

原始数据附件

attachData 方法可用于将原始字节字符串作为附件附加。例如,如果您在内存中生成了一个 PDF 并希望将其附加到电子邮件中而不将其写入磁盘,可以使用此方法。attachData 方法接受原始数据字节作为其第一个参数,文件名作为其第二个参数,以及选项数组作为其第三个参数:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->attachData($this->pdf, 'name.pdf', [
                    'mime' => 'application/pdf',
                ]);
}

内联附件

将内联图像嵌入到电子邮件中通常很麻烦;然而,Laravel 提供了一种方便的方法来将图像附加到电子邮件中。要嵌入内联图像,请在电子邮件模板中使用 $message 变量上的 embed 方法。Laravel 会自动将 $message 变量提供给所有电子邮件模板,因此您无需手动传递它:

php
<body>
    这里是一张图片:

    <img src="{{ $message->embed($pathToImage) }}">
</body>
exclamation

$message 变量在纯文本消息模板中不可用,因为纯文本消息不使用内联附件。

嵌入原始数据附件

如果您已经有一个要嵌入到电子邮件模板中的原始图像数据字符串,可以在 $message 变量上调用 embedData 方法。在调用 embedData 方法时,您需要提供一个应分配给嵌入图像的文件名:

php
<body>
    这里是一张来自原始数据的图片:

    <img src="{{ $message->embedData($data, 'example-image.jpg') }}">
</body>

自定义 SwiftMailer 消息

Mailable 基类的 withSwiftMessage 方法允许您注册一个闭包,该闭包将在发送消息之前使用 SwiftMailer 消息实例调用。这使您有机会在消息传递之前对其进行深度自定义:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
    $this->view('emails.orders.shipped');

    $this->withSwiftMessage(function ($message) {
        $message->getHeaders()->addTextHeader(
            'Custom-Header', 'Header Value'
        );
    });

    return $this;
}

Markdown 邮件类

Markdown 邮件消息允许您在邮件类中利用 邮件通知 的预构建模板和组件。由于消息是用 Markdown 编写的,Laravel 能够为消息渲染美观、响应式的 HTML 模板,同时还自动生成纯文本副本。

生成 Markdown 邮件类

要生成带有相应 Markdown 模板的邮件类,可以使用 make:mail Artisan 命令的 --markdown 选项:

php
php artisan make:mail OrderShipped --markdown=emails.orders.shipped

然后,在邮件类的 build 方法中配置邮件时,调用 markdown 方法而不是 view 方法。markdown 方法接受 Markdown 模板的名称和一个可选的数据数组,以便在模板中使用:

php
/**
 * 构建消息。
 *
 * @return $this
 */
public function build()
{
    return $this->from('example@example.com')
                ->markdown('emails.orders.shipped', [
                    'url' => $this->orderUrl,
                ]);
}

编写 Markdown 消息

Markdown 邮件类使用 Blade 组件和 Markdown 语法的组合,使您能够轻松构建邮件消息,同时利用 Laravel 的预构建电子邮件 UI 组件:

php
@component('mail::message')
# 订单已发货

您的订单已发货!

@component('mail::button', ['url' => $url])
查看订单
@endcomponent

谢谢,<br>
{{ config('app.name') }}
@endcomponent
lightbulb

编写 Markdown 电子邮件时不要使用过多缩进。根据 Markdown 标准,Markdown 解析器会将缩进内容渲染为代码块。

按钮组件

按钮组件渲染一个居中的按钮链接。该组件接受两个参数,一个 url 和一个可选的 color。支持的颜色有 primarysuccesserror。您可以在消息中添加任意数量的按钮组件:

php
@component('mail::button', ['url' => $url, 'color' => 'success'])
查看订单
@endcomponent

面板组件

面板组件将给定的文本块渲染在一个面板中,该面板的背景颜色与消息的其余部分略有不同。这使您可以引起对给定文本块的注意:

php
@component('mail::panel')
这是面板内容。
@endcomponent

表格组件

表格组件允许您将 Markdown 表格转换为 HTML 表格。该组件接受 Markdown 表格作为其内容。表格列对齐支持使用默认的 Markdown 表格对齐语法:

php
@component('mail::table')
| Laravel       | 表格         | 示例  |
| ------------- |:-------------:| --------:|
| 2      | 居中      | $10      |
| 3      | 右对齐 | $20      |
@endcomponent

自定义组件

您可以将所有 Markdown 邮件组件导出到您自己的应用程序中进行自定义。要导出组件,请使用 vendor:publish Artisan 命令发布 laravel-mail 资产标签:

php
php artisan vendor:publish --tag=laravel-mail

此命令会将 Markdown 邮件组件发布到 resources/views/vendor/mail 目录。mail 目录将包含一个 html 和一个 text 目录,每个目录都包含其各自的可用组件表示。您可以随意自定义这些组件。

自定义 CSS

导出组件后,resources/views/vendor/mail/html/themes 目录将包含一个 default.css 文件。您可以自定义此文件中的 CSS,您的样式将自动转换为 Markdown 邮件消息的 HTML 表示中的内联 CSS 样式。

如果您想为 Laravel 的 Markdown 组件构建一个全新的主题,可以在 html/themes 目录中放置一个 CSS 文件。命名并保存您的 CSS 文件后,更新应用程序的 config/mail.php 配置文件中的 theme 选项以匹配新主题的名称。

要为单个邮件类自定义主题,可以将邮件类的 $theme 属性设置为发送该邮件类时应使用的主题名称。

发送邮件

要发送消息,请在 Mail facade 上使用 to 方法。to 方法接受电子邮件地址、用户实例或用户集合。如果您传递一个对象或对象集合,邮件程序将自动使用它们的 emailname 属性来确定电子邮件的收件人,因此请确保这些属性在您的对象上可用。一旦指定了收件人,您可以将邮件类实例传递给 send 方法:

php
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Mail\OrderShipped;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;

class OrderShipmentController extends Controller
{
    /**
     * 发货给定订单。
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $order = Order::findOrFail($request->order_id);

        // 发货订单...

        Mail::to($request->user())->send(new OrderShipped($order));
    }
}

您不仅限于在发送消息时指定“to”收件人。您可以通过将各自的方法链接在一起自由设置“to”、“cc”和“bcc”收件人:

php
Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->send(new OrderShipped($order));

循环遍历收件人

有时,您可能需要通过遍历收件人/电子邮件地址数组来向收件人列表发送邮件类。然而,由于 to 方法将电子邮件地址附加到邮件类的收件人列表中,因此循环中的每次迭代都会向每个先前的收件人发送另一封电子邮件。因此,您应该为每个收件人重新创建邮件类实例:

php
foreach (['taylor@example.com', 'dries@example.com'] as $recipient) {
    Mail::to($recipient)->send(new OrderShipped($order));
}

通过特定邮件程序发送邮件

默认情况下,Laravel 将使用在应用程序的 mail 配置文件中配置为 default 邮件程序的邮件程序发送电子邮件。然而,您可以使用 mailer 方法通过特定邮件程序配置发送消息:

php
Mail::mailer('postmark')
        ->to($request->user())
        ->send(new OrderShipped($order));

队列邮件

队列邮件消息

由于发送电子邮件消息可能会对应用程序的响应时间产生负面影响,许多开发人员选择将电子邮件消息排队以进行后台发送。Laravel 使用其内置的 统一队列 API 使这变得简单。要将邮件消息排队,请在指定消息的收件人后使用 Mail facade 上的 queue 方法:

php
Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->queue(new OrderShipped($order));

此方法将自动处理将作业推送到队列中,以便消息在后台发送。您需要在使用此功能之前配置您的队列

延迟消息队列

如果您希望延迟队列电子邮件消息的传递,可以使用 later 方法。作为其第一个参数,later 方法接受一个 DateTime 实例,指示消息应何时发送:

php
Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->later(now()->addMinutes(10), new OrderShipped($order));

推送到特定队列

由于使用 make:mail 命令生成的所有邮件类都使用 Illuminate\Bus\Queueable trait,您可以在任何邮件类实例上调用 onQueueonConnection 方法,允许您为消息指定连接和队列名称:

php
$message = (new OrderShipped($order))
                ->onConnection('sqs')
                ->onQueue('emails');

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->queue($message);

默认队列

如果您有希望始终排队的邮件类,可以在类上实现 ShouldQueue 合约。现在,即使在发送邮件时调用 send 方法,由于实现了合约,邮件类仍将排队:

php
use Illuminate\Contracts\Queue\ShouldQueue;

class OrderShipped extends Mailable implements ShouldQueue
{
    //
}

队列邮件类和数据库事务

当队列邮件类在数据库事务中调度时,它们可能会在数据库事务提交之前由队列处理。当这种情况发生时,您在数据库事务期间对模型或数据库记录所做的任何更新可能尚未反映在数据库中。此外,在事务中创建的任何模型或数据库记录可能不存在于数据库中。如果您的邮件类依赖于这些模型,当处理发送队列邮件类的作业时,可能会发生意外错误。

如果您的队列连接的 after_commit 配置选项设置为 false,您仍然可以通过在发送邮件消息时调用 afterCommit 方法来指示特定队列邮件类应在所有打开的数据库事务提交后调度:

php
Mail::to($request->user())->send(
    (new OrderShipped($order))->afterCommit()
);

或者,您可以从邮件类的构造函数中调用 afterCommit 方法:

php
<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class OrderShipped extends Mailable implements ShouldQueue
{
    use Queueable, SerializesModels;

    /**
     * 创建一个新的消息实例。
     *
     * @return void
     */
    public function __construct()
    {
        $this->afterCommit();
    }
}
lightbulb

要了解有关解决这些问题的更多信息,请查看有关 队列作业和数据库事务 的文档。

渲染邮件类

有时您可能希望捕获邮件类的 HTML 内容而不发送它。为此,您可以调用邮件类的 render 方法。此方法将返回邮件类的评估 HTML 内容作为字符串:

php
use App\Mail\InvoicePaid;
use App\Models\Invoice;

$invoice = Invoice::find(1);

return (new InvoicePaid($invoice))->render();

在浏览器中预览邮件类

在设计邮件类的模板时,可以方便地在浏览器中快速预览渲染的邮件类,就像典型的 Blade 模板一样。为此,Laravel 允许您直接从路由闭包或控制器返回任何邮件类。当返回邮件类时,它将在浏览器中渲染并显示,使您能够快速预览其设计,而无需将其发送到实际的电子邮件地址:

php
Route::get('/mailable', function () {
    $invoice = App\Models\Invoice::find(1);

    return new App\Mail\InvoicePaid($invoice);
});
exclamation

内联附件 在浏览器中预览邮件类时不会渲染。要预览这些邮件类,您应该将它们发送到电子邮件测试应用程序,如 MailHogHELO

本地化邮件类

Laravel 允许您以请求的当前语言环境以外的语言环境发送邮件类,并且即使邮件被排队,也会记住此语言环境。

为此,Mail facade 提供了一个 locale 方法来设置所需的语言。应用程序将在评估邮件类的模板时切换到此语言环境,然后在评估完成后恢复到先前的语言环境:

php
Mail::to($request->user())->locale('es')->send(
    new OrderShipped($order)
);

用户首选语言环境

有时,应用程序会存储每个用户的首选语言环境。通过在一个或多个模型上实现 HasLocalePreference 合约,您可以指示 Laravel 在发送邮件时使用此存储的语言环境:

php
use Illuminate\Contracts\Translation\HasLocalePreference;

class User extends Model implements HasLocalePreference
{
    /**
     * 获取用户的首选语言环境。
     *
     * @return string
     */
    public function preferredLocale()
    {
        return $this->locale;
    }
}

一旦实现了接口,Laravel 将在向模型发送邮件类和通知时自动使用首选语言环境。因此,在使用此接口时无需调用 locale 方法:

php
Mail::to($request->user())->send(new OrderShipped($order));

测试邮件类

Laravel 提供了几种方便的方法来测试您的邮件类是否包含您期望的内容。这些方法是:assertSeeInHtmlassertDontSeeInHtmlassertSeeInTextassertDontSeeInText

正如您所期望的,“HTML” 断言断言邮件类的 HTML 版本包含给定字符串,而“文本” 断言断言邮件类的纯文本版本包含给定字符串:

php
use App\Mail\InvoicePaid;
use App\Models\User;

public function test_mailable_content()
{
    $user = User::factory()->create();

    $mailable = new InvoicePaid($user);

    $mailable->assertSeeInHtml($user->email);
    $mailable->assertSeeInHtml('Invoice Paid');

    $mailable->assertSeeInText($user->email);
    $mailable->assertSeeInText('Invoice Paid');
}

测试邮件类发送

我们建议将邮件类的内容测试与断言给定邮件类已“发送”给特定用户的测试分开。要了解如何测试邮件类是否已发送,请查看我们的 Mail fake 文档。

邮件与本地开发

在开发发送电子邮件的应用程序时,您可能不希望实际将电子邮件发送到真实的电子邮件地址。Laravel 提供了几种方法来在本地开发期间“禁用”电子邮件的实际发送。

日志驱动程序

日志邮件驱动程序不会发送您的电子邮件,而是将所有电子邮件消息写入日志文件以供检查。通常,此驱动程序仅在本地开发期间使用。有关按环境配置应用程序的更多信息,请查看 配置文档

HELO / Mailtrap / MailHog

或者,您可以使用 HELOMailtrap 等服务和 smtp 驱动程序将电子邮件消息发送到“虚拟”邮箱,您可以在真实的电子邮件客户端中查看它们。这种方法的好处是可以在 Mailtrap 的消息查看器中实际检查最终的电子邮件。

如果您使用 Laravel Sail,可以使用 MailHog 预览您的消息。当 Sail 正在运行时,您可以在 http://localhost:8025 访问 MailHog 界面。

使用全局 to 地址

最后,您可以通过调用 Mail facade 提供的 alwaysTo 方法来指定全局“to”地址。通常,此方法应在应用程序的服务提供者之一的 boot 方法中调用:

php
use Illuminate\Support\Facades\Mail;

/**
 * 启动任何应用程序服务。
 *
 * @return void
 */
public function boot()
{
    if ($this->app->environment('local')) {
        Mail::alwaysTo('taylor@example.com');
    }
}

事件

在发送邮件消息的过程中,Laravel 会触发两个事件。MessageSending 事件在消息发送之前触发,而 MessageSent 事件在消息发送后触发。请记住,这些事件是在邮件被发送时触发的,而不是在邮件被排队时触发的。您可以在 App\Providers\EventServiceProvider 服务提供者中为此事件注册事件监听器:

php
/**
 * 应用程序的事件监听器映射。
 *
 * @var array
 */
protected $listen = [
    'Illuminate\Mail\Events\MessageSending' => [
        'App\Listeners\LogSendingMessage',
    ],
    'Illuminate\Mail\Events\MessageSent' => [
        'App\Listeners\LogSentMessage',
    ],
];