Laravel生产环境邮件发送失败的首要原因是MAIL_MAILER未设为smtp或配置缓存未清除,必须执行php artisan config:clear;Gmail需启用两步验证并使用应用专用密码,端口587配tls、465配ssl,且MAIL_FROM_ADDRESS域名须与服务器主域名一致以避免被标记为垃圾邮件。

在Laravel生产环境部署后,用户注册验证、密码重置、订单通知等关键功能依赖邮件送达,但配置稍有偏差就会导致收件人收不到任何消息,且无明确报错提示,问题常被误判为业务逻辑故障。
确认驱动与环境变量生效
打开终端,进入项目根目录,执行php artisan tinker,输入config('mail.default')回车——若返回null或"log",说明MAIL_MAILER未生效或仍为开发默认值。
立即检查.env文件首行是否含MAIL_MAILER=smtp(不是MAIL_DRIVER,该键名自Laravel 8起已废弃);若存在注释符号#或空格,必须删除。
【必须运行】修改.env后,强制清空配置缓存:php artisan config:clear && php artisan cache:clear。Laravel生产环境默认启用配置缓存,不执行此步,.env变更永不生效。
配置SMTP连接参数
方法一:Gmail/Google Workspace(需两步验证)
登录Google账户 → “安全性” → 开启“两步验证” → 进入“应用专用密码” → 应用选“邮件”,设备填“Laravel Prod” → 生成16位密码,粘贴至.env的MAIL_PASSWORD字段。
方法二:腾讯企业邮箱(国内常用)
在腾讯企业邮箱管理后台开启SMTP服务 → 获取服务器地址smtp.exmail.qq.com → 端口填465 → MAIL_ENCRYPTION=ssl → 用户名填完整邮箱地址,密码填邮箱登录密码(无需专用密码)。
方法三:SendGrid(推荐SaaS方案)
登录SendGrid控制台 → “Settings” → “API Keys” → 创建新Key → 将Key值填入.env的MAIL_PASSWORD → MAIL_HOST=smtp.sendgrid.net → MAIL_PORT=587 → MAIL_ENCRYPTION=tls → MAIL_USERNAME=apikey(固定值,非邮箱)。
注意:所有服务商端口与加密方式必须严格匹配——587只认tls,465只认ssl,配错直接Connection could not be established。
验证发信通路
第一步:禁用队列,直连测试
临时将.env中QUEUE_CONNECTION=sync,避免队列层干扰。
第二步:用tinker触发裸邮件
执行php artisan tinker → 输入以下三行(替换为你的真实邮箱):
use Illuminate\Support\Facades\Mail;
Mail::raw('Production SMTP test OK', function ($m) { $m->to('admin@yourdomain.com')->subject('Laravel Prod Mail Test'); });
第三步:观察响应
若返回空结果(无Exception),说明发送成功;若报Expected response code 250 but got code "535",认证失败,重点核对MAIL_USERNAME和MAIL_PASSWORD;若卡住超时,检查服务器是否屏蔽25/465/587端口(阿里云/腾讯云默认封禁25端口,必须改用465或587)。
第四步:检查日志定位静默失败
查看storage/logs/laravel.log,搜索mail或Swift_TransportException,真实错误细节全在此处,比控制台报错更精准。
设置发件人与内容安全
在.env中补全发件人信息:
MAIL_FROM_ADDRESS=no-reply@yourdomain.com
MAIL_FROM_NAME="YourApp 官方通知"
确保MAIL_FROM_ADDRESS域名与你服务器绑定的主域名一致,否则Gmail等客户端可能标记为垃圾邮件。
邮件视图中禁止使用<script>、javascript:链接或内联样式含!important——多数邮件客户端会剥离这些内容,导致排版崩坏或内容截断。
纯文本备选方案:在Mailable类中同时定义->text('emails.welcome_plain')和->html('emails.welcome'),提升兼容性。
启用队列异步发送
1. 确认队列驱动已切换为可靠后端
生产环境禁用database驱动,改用redis或supervisor管理的redis连接池。检查.env:QUEUE_CONNECTION=redis。
2. 修改邮件调用方式
将原本的Mail::to($user)->send(new WelcomeEmail())改为Mail::to($user)->queue(new WelcomeEmail())。
3. 启动队列监听器
在后台运行php artisan queue:work --sleep=3 --max-jobs=1000 --tries=3,并用supervisor守护进程,避免终端关闭后中断。
4. 验证队列任务是否入列
执行php artisan queue:failed确认无堆积失败任务;检查Redis中queues:default列表长度是否随发送请求增长。


















