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 显式传数据,此时属性可设为 protected 或 private:
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));
延时发送:
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 驱动把邮件内容写入日志,是最简单的确认方式。
| 想做的事 | 方法 |
|---|
| 创建 Mailable | php artisan make:mail ClassName |
| 设置发件人 | envelope() 的 from |
| 使用 Blade 模板 | content() 的 view |
| 使用 Markdown 模板 | content() 的 markdown |
| 发送邮件 | Mail::to()->send() |
| 排队发送 | Mail::to()->queue() |
| 延时发送 | Mail::to()->later() |