Laravel邮件配置需在config/mail.php定义并由.env注入敏感项,MAIL_MAILER必须明确设置;验证用php artisan tinker执行config('mail');发送前必须调用to();弃用Mail::send()改用Mailable类;附件路径须绝对且中文名用attachData()指定filename。

邮件配置写在哪、怎么验证是否生效
Laravel 的邮件配置不在 .env 里写全就能用,关键得让框架读到并走对驱动。默认配置在 config/mail.php,但所有敏感项(如 SMTP 密码、端口)必须从 .env 注入,否则本地测试可能通、线上直接静默失败。
-
MAIL_MAILER必须明确设为smtp、log或array;设成sendmail但没装 sendmail 会卡住不报错 - 用
php artisan tinker执行config('mail')看实际加载值,别只信.env里的注释行 - 开发时优先设
MAIL_MAILER=log,发邮件会写进storage/logs/laravel.log,比配错 SMTP 还死等超时更省时间
发送前必须调用 to() 吗
必须。Laravel 的 Mailable 类不是“构造即发送”,而是构建消息对象,to()、cc()、bcc() 是链式调用的起点,漏掉 to() 会导致 Symfony\Component\Mailer\Exception\TransportException:No recipients specified。
- 收件人地址必须是字符串或数组,不能传
User模型实例——哪怕模型有email属性也不行 - 批量发送别用循环反复 new Mailable,改用
Mail::to($users)->send(new OrderShipped()),Laravel 会自动拆解数组 - 如果要用队列异步发,
to()必须在dispatch()前完成,队列任务里再调to()会找不到上下文
为什么 Mail::send() 被弃用了
因为 Mail::send() 是 Laravel 5.x 时代的旧接口,底层直接拼 View 字符串,不支持 Mailable 类的生命周期钩子、主题模板继承、附件流式处理等能力。6.x 起强制走 Mailable 类 + Mail::to()->send() 流程。
- 还在用
Mail::send('emails.welcome', ['name' => 'John'], function ($message) { ... })?立刻改掉,否则升级到 10.x 会报Call to undefined method Illuminate\Support\Facades\Mail::send() - 迁移很简单:把视图路径转成
resources/views/emails/welcome.blade.php,新建app/Mail/WelcomeEmail.php继承Mailable,在build()里调$this->view('emails.welcome') - 旧写法无法用
assertSentMail()在测试里断言,新写法可以
附件路径不对、中文名乱码的硬伤怎么破
附件用 attach() 时,路径必须是绝对路径(storage_path('app/files/report.pdf')),相对路径会找错位置;中文文件名默认被编码成 filename*=UTF-8''xxx.pdf,部分老旧邮箱客户端(如 Outlook 2010)会显示成乱码。
- 解决乱码:用
attachData()替代attach(),手动指定filename参数,例如$message->attachData($content, '订单报表.pdf', ['mime' => 'application/pdf']) - 不要用
public_path()直接挂 web 可访问路径,附件内容应从 storage 读取,避免权限暴露 - 大附件(>5MB)建议改用下载链接代替附件,否则 SMTP 服务器可能拒绝中止连接,错误信息通常是
Expected response code 250 but got code "452"
邮件内容里混用 Blade 指令和原始 HTML 标签容易出意外交互,比如 @if 块里写了未闭合的 <table>,渲染后整个布局崩掉——这种问题只能靠预览 HTML 源码排查,没法靠日志定位。</table>











