Laravel - 发送邮件
Laravel - 发送邮件
Section titled “Laravel - 发送邮件”Laravel 在流行的 Symfony Mailer 组件(以前是 SwiftMailer)之上提供了简洁、简单的 API,让你能够快速通过本地或基于云的服务开始发送邮件。
Laravel 的邮件服务通过应用程序的 .env 文件和 config/mail.php 配置文件进行配置。.env 文件允许你在不修改代码的情况下快速更改邮件驱动和凭证。
常见的 .env 邮件变量:
MAIL_MAILER=smtpMAIL_HOST=mailpitMAIL_PORT=1025MAIL_USERNAME=nullMAIL_PASSWORD=nullMAIL_ENCRYPTION=nullMAIL_FROM_ADDRESS="hello@example.com"MAIL_FROM_NAME="${APP_NAME}"常见选项说明:
MAIL_MAILER:要使用的驱动(例如,smtp、ses、mailgun、postmark、sendmail、log)。对于本地开发,强烈推荐使用log(将邮件写入日志文件)或像 Mailpit/MailHog 这样的工具(smtp配置到其主机/端口)。MAIL_HOST、MAIL_PORT、MAIL_USERNAME、MAIL_PASSWORD、MAIL_ENCRYPTION:用于 SMTP 的凭证。MAIL_FROM_ADDRESS、MAIL_FROM_NAME:邮件的默认发件人地址和名称。
对于像 Gmail 这样的服务,如果启用了两步验证,你可能需要生成一个“应用专用密码”(App Password)。以下是 Gmail SMTP 的配置示例:
MAIL_MAILER=smtpMAIL_HOST=smtp.gmail.comMAIL_PORT=587MAIL_USERNAME=your-gmail-username@gmail.comMAIL_PASSWORD=your-gmail-app-passwordMAIL_ENCRYPTION=tlsMAIL_FROM_ADDRESS="your-gmail-username@gmail.com"MAIL_FROM_NAME="Your Application Name"修改 .env 文件后,清除配置缓存:php artisan config:clear。
生成 Mailable 类
Section titled “生成 Mailable 类”在 Laravel 中,应用程序发送的每种类型的电子邮件都表示为一个 “mailable” 类。这些类存储在 app/Mail 目录中。你可以使用 Artisan 命令生成一个新的 mailable 类:
php artisan make:mail OrderShipped该命令将创建 app/Mail/OrderShipped.php 文件。一个 mailable 类包含用于构建电子邮件的方法,例如定义其发件人、收件人、主题和要使用的视图。
配置 Mailable 类:
Section titled “配置 Mailable 类:”在一个 mailable 类中,你通常在构造函数中配置其属性(要传递给视图的数据),并在 build 方法(旧版本)或 envelope 和 content 方法(新版本)中构建电子邮件消息。
Mailable 示例(OrderShipped.php - 使用 Envelope 和 Content 的现代语法):
<?php
namespace App\Mail;
use App\Models\Order; // 假设你有一个 Order 模型use Illuminate\Bus\Queueable;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Mail\Mailable;use Illuminate\Mail\Mailables\Content;use Illuminate\Mail\Mailables\Envelope;use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable implements ShouldQueue // 可选:用于加入队列{ use Queueable, SerializesModels;
public Order $order;
/** * Create a new message instance. */ public function __construct(Order $order) { $this->order = $order; }
/** * Get the message envelope. */ public function envelope(): Envelope { return new Envelope( from: new \Illuminate\Mail\Mailables\Address('noreply@example.com', 'Example App'), subject: 'Your Order Has Shipped!', ); }
/** * Get the message content definition. */ public function content(): Content { return new Content( view: 'emails.orders.shipped', // 邮件的 Blade 视图 // with: ['orderName' => $this->order->name], // 公共属性的替代方案 ); }
/** * Get the attachments for the message. * * @return array<int, \Illuminate\Mail\Mailables\Attachment> */ public function attachments(): array { return [ // Attachment::fromPath(public_path('/path/to/file.pdf')), ]; }}创建邮件视图(resources/views/emails/orders/shipped.blade.php):
Section titled “创建邮件视图(resources/views/emails/orders/shipped.blade.php):”<!DOCTYPE html><html><head> <title>Order Shipped</title></head><body> <h1>Hi, {{ $order->customer_name }}!</h1> {{-- 访问 Mailable 类中的公共属性 --}} <p>Your order #{{ $order->id }} has been shipped.</p> <p>Thank you for your purchase!</p></body></html>要发送 mailable,请使用 Mail Facade 上的 to 方法。to 方法接受电子邮件地址、用户实例或用户集合。然后,使用 mailable 类的实例调用 send 方法。
在控制器中的示例:
<?php
namespace App\Http\Controllers;
use App\Mail\OrderShipped;use App\Models\Order; // 假设 Order 模型存在use Illuminate\Http\Request;use Illuminate\Support\Facades\Mail;
class OrderController extends Controller{ public function ship(Request $request, string $orderId) { $order = Order::findOrFail($orderId); // 获取订单
// 发送邮件 Mail::to($order->customer_email) // 如果发送给已登录用户,也可以用 $request->user() // ->cc($moreUsers) // ->bcc($evenMoreUsers) ->send(new OrderShipped($order));
return redirect()->route('orders.show', $orderId)->with('status', 'Order shipped email sent!'); }}通常你会从路由定义中调用这个 ship 方法。
发送纯文本邮件(使用 Mail::raw 或 Mailable 中的文本视图)
Section titled “发送纯文本邮件(使用 Mail::raw 或 Mailable 中的文本视图)”如果你需要发送一个没有 Blade 模板的简单纯文本邮件,可以使用 Mail::raw():
Mail::raw('This is a plain text email body.', function ($message) { $message->to('recipient@example.com') ->subject('Simple Text Email');});对于 Mailable 类,你可以在 Content 对象中指定一个文本视图:
public function content(): Content{ return new Content( view: 'emails.orders.shipped', // HTML 视图 text: 'emails.orders.shipped_plain' // 纯文本视图 );}Mailable 中的附件
Section titled “Mailable 中的附件”要添加附件,请在 Mailable 类的 attachments 方法中或直接在 Envelope 对象(或旧版本中的 build 方法)上使用 attach 方法。
// 在 Mailable 类的 attachments() 方法中(较新的 Laravel):use Illuminate\Mail\Mailables\Attachment;
public function attachments(): array{ return [ Attachment::fromPath(public_path('documents/invoice.pdf')) ->as('customer-invoice.pdf') ->withMime('application/pdf'), Attachment::fromStorageDisk('s3', 'avatars/profile.jpg'), // 从存储盘附加 ];}将邮件加入队列
Section titled “将邮件加入队列”发送电子邮件可能会显著降低应用程序的响应时间。Laravel 允许你轻松地将邮件加入队列进行后台发送。在你的 mailable 类上实现 ShouldQueue 接口。
class OrderShipped extends Mailable implements ShouldQueue{ ... }然后,当你调用 Mail::send() 时,Laravel 会自动将该任务推送到你的队列。你需要运行一个队列工作进程:php artisan queue:work。
使用 Mailpit/MailHog 进行本地开发
Section titled “使用 Mailpit/MailHog 进行本地开发”在本地开发期间,你通常不希望发送真实的电子邮件。像 Mailpit 或 MailHog 这样的工具充当本地 SMTP 服务器,它们会捕获所有外发邮件并将其显示在 Web 界面中。这对于测试来说非常宝贵。
配置你的 .env 文件以指向 Mailpit(通常运行在 localhost:1025 上):
MAIL_MAILER=smtpMAIL_HOST=localhost # or 127.0.0.1MAIL_PORT=1025MAIL_USERNAME=nullMAIL_PASSWORD=nullMAIL_ENCRYPTION=null # or 'tls' if Mailpit is configured for it常见的学习障碍:电子邮件配置问题
许多初学者在发送电子邮件时会遇到困难,原因可能是不正确的 .env 配置或邮件服务器本身的问题(例如,Gmail 阻止安全性较低的应用,ISP 阻止 SMTP 端口)。在开发过程中使用 MAIL_MAILER=log 或 Mailpit 可以帮助隔离问题是出在 Laravel 的代码还是邮件服务器设置上。
有关详细信息,请查阅 Laravel 关于邮件的官方文档:https://laravel.com/docs/mail