跳转到主要内容

Laravel 邮件功能概览

Laravel 邮件基于 Symfony Mailer,支持 SMTP、Mailgun、Postmark、Resend、Amazon SES、sendmail 等驱动。
以前使用的 SwiftMailer 已被废弃。Laravel 9 起使用 Symfony Mailer。
邮件配置写在 config/mail.php。可通过 .env 切换驱动:
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=your-username
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"

创建 Mailable 类

Laravel 把每种邮件表达为「Mailable」类。使用 make:mail 命令生成:
php artisan make:mail OrderShipped
生成到 app/Mail/

Mailable 设置

生成的 Mailable 类有 envelope()content()attachments() 三个方法。
<?php

namespace App\Mail;

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

class OrderShipped extends Mailable
{
    use Queueable, SerializesModels;

    public function __construct(
        public Order $order,
    ) {}

    public function envelope(): Envelope
    {
        return new Envelope(
            subject: '订单已发货',
        );
    }

    public function content(): Content
    {
        return new Content(
            view: 'mail.orders.shipped',
        );
    }

    public function attachments(): array
    {
        return [];
    }
}

设置发件人

envelope() 中指定发件人:
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Envelope;

public function envelope(): Envelope
{
    return new Envelope(
        from: new Address('[email protected]', 'Shop Support'),
        subject: '订单已发货',
    );
}
config/mail.php 中设置全局默认发件人可省略单独指定:
'from' => [
    'address' => env('MAIL_FROM_ADDRESS', '[email protected]'),
    'name' => env('MAIL_FROM_NAME', 'Example'),
],

设置邮件正文

content() 中指定 Blade 模板。构造器中赋值给 public 属性的数据会自动传给模板。
public function content(): Content
{
    return new Content(
        view: 'mail.orders.shipped',
    );
}
对应 Blade 模板 resources/views/mail/orders/shipped.blade.php
<!DOCTYPE html>
<html>
<body>
    <h1>您的订单已发货</h1>
    <p>订单号:{{ $order->id }}</p>
    <p>金额合计:¥{{ number_format($order->total) }}</p>
    <p>感谢您的购买。</p>
</body>
</html>
也可以通过 with 显式传数据,此时属性可设为 protectedprivate
public function __construct(
    protected Order $order,
) {}

public function content(): Content
{
    return new Content(
        view: 'mail.orders.shipped',
        with: [
            'orderId' => $this->order->id,
            'total' => $this->order->total,
        ],
    );
}

发送邮件

使用 Mail 门面的 to() 指定收件人,然后 send()
<?php

namespace App\Http\Controllers;

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

class OrderShipmentController extends Controller
{
    public function store(Request $request): RedirectResponse
    {
        $order = Order::findOrFail($request->order_id);

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

        return redirect('/orders');
    }
}
也可指定抄送/密送:
Mail::to($request->user())
    ->cc($ccUsers)
    ->bcc($bccUsers)
    ->send(new OrderShipped($order));
使用特定 mailer:
Mail::mailer('postmark')
    ->to($request->user())
    ->send(new OrderShipped($order));

使用队列发送邮件

邮件发送会影响响应时间,建议通过队列在后台发送。
Mail::to($request->user())->queue(new OrderShipped($order));
使用队列前需先配置好队列并启动 worker。
延时发送:
Mail::to($request->user())
    ->later(now()->plus(minutes: 10), new OrderShipped($order));
在 Mailable 类上实现 ShouldQueue 后,调用 send() 也会自动进入队列:
use Illuminate\Contracts\Queue\ShouldQueue;

class OrderShipped extends Mailable implements ShouldQueue
{
    // ...
}

用 PHP 属性指定队列连接与名称

用 PHP 属性可以在类级别声明式指定,无需 on()->queue() 链式调用:
use Illuminate\Queue\Attributes\Connection;
use Illuminate\Queue\Attributes\Queue;

#[Connection('sqs')]
#[Queue('emails')]
class OrderShipped extends Mailable implements ShouldQueue
{
    // ...
}

创建 Markdown 邮件

Markdown 邮件可以使用 Laravel 提供的美观响应式 HTML 模板。

生成 Markdown Mailable

--markdown 选项生成:
php artisan make:mail OrderShipped --markdown=mail.orders.shipped
content() 中使用 markdown 参数:
use Illuminate\Mail\Mailables\Content;

public function content(): Content
{
    return new Content(
        markdown: 'mail.orders.shipped',
        with: [
            'url' => route('orders.show', $this->order),
        ],
    );
}

编写 Markdown 模板

使用 Laravel 提供的 Blade 组件:
<x-mail::message>
# 您的订单已发货

订单已发货,特此通知。

<x-mail::button :url="$url">
查看订单
</x-mail::button>

感谢您的支持。<br>
{{ config('app.name') }}
</x-mail::message>
可用组件:
组件说明
<x-mail::button>按钮链接(可用 color 指定 primary/success/error
<x-mail::panel>突出的面板
<x-mail::table>Markdown 表格
Markdown 邮件会同时生成纯文本版本,兼容不支持 HTML 的客户端。

邮件预览

在路由中返回 Mailable 实例即可在浏览器预览,便于开发调试:
// routes/web.php
Route::get('/mailable', function () {
    $order = App\Models\Order::first();
    return new App\Mail\OrderShipped($order);
});

本地开发的邮件

为避免误发邮件到生产环境,可在本地使用 Mailpit 等工具:
# .env (Mailpit)
MAIL_MAILER=smtp
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
Laragon、Laravel Herd 默认已包含 Mailpit。
也可用 log 驱动把邮件内容写入日志,是最简单的确认方式。
MAIL_MAILER=log

小结

想做的事方法
创建 Mailablephp artisan make:mail ClassName
设置发件人envelope()from
使用 Blade 模板content()view
使用 Markdown 模板content()markdown
发送邮件Mail::to()->send()
排队发送Mail::to()->queue()
延时发送Mail::to()->later()
最后修改于 2026年7月13日