MAIL_DRIVER和MAIL_ENCRYPTION必须匹配端口:PORT=465对应ENCRYPTION=ssl,PORT=587对应ENCRYPTION=tls;MAIL_PASSWORD必须为授权码而非登录密码;发件人配置优先级为Mailable::from() > .env > config/mail.php;推荐使用queue()配合队列驱动避免阻塞请求。

MAIL_DRIVER 和 MAIL_ENCRYPTION 必须匹配端口
很多人配完 MAIL_PORT=465 却漏掉 MAIL_ENCRYPTION=ssl,结果报错 Swift_TransportException: Expected response code 250 but got code "501"。反过来,如果用 MAIL_PORT=587,就必须设 MAIL_ENCRYPTION=tls;设成 ssl 或留空都会连不上。
常见组合只有两种:
-
MAIL_PORT=465+MAIL_ENCRYPTION=ssl -
MAIL_PORT=587+MAIL_ENCRYPTION=tls
别硬套教程里的“默认25端口”,现在主流邮箱(163、Gmail、腾讯企业邮)基本都禁用了25,留空或填25大概率超时。
MAIL_PASSWORD 必须是授权码,不是登录密码
网易163、QQ邮箱、Gmail 都不接受账户原始密码。必须去邮箱后台开启 SMTP 服务,并生成「客户端授权码」或「应用专用密码」——这个字符串才是 MAIL_PASSWORD 的值。
典型错误现象:
- 报错
Authentication failed或535 Login Fail - 发件人地址能通过验证,但收件方看到发件人显示为
xxx@163.com via smtp.163.com
注意:腾讯企业邮例外,它允许直接用邮箱密码;但普通 QQ 邮箱和 163 一律不行。
发件人配置有两处,优先级不同
config/mail.php 里的 'from' 是全局默认,但会被 .env 中的 MAIL_FROM_ADDRESS 和 MAIL_FROM_NAME 覆盖。如果只改了 mail.php 没动 .env,实际发信人还是 .env 里定义的。
更关键的是:用 Mailable 类发送时,build() 方法里调用 ->from(...) 会覆盖所有全局配置。比如:
return $this->from('noreply@myapp.com', 'MyApp')->view('emails.welcome');
这种写法就完全绕过了 .env 和 mail.php 的设置。调试时建议先统一用环境变量配好,再局部覆盖。
发送方式选 Mail::to()->send() 还是 queue()?
开发阶段用 Mail::to($to)->send(new WelcomeEmail()) 最直观,但上线后别这么干。HTTP 请求等待邮件发完才返回,用户可能卡在 loading 状态十几秒。
正确做法是加队列:
- 确保
QUEUE_CONNECTION在.env中设为database或redis - 改用
Mail::to($to)->queue(new WelcomeEmail()) - 别忘了跑
php artisan queue:work启动监听
如果没配队列还强行用 queue(),邮件会静默失败,日志里只有一行 Failed to process job,根本看不出哪错了。


















