laravel邮件发不出的主因是mail_mailer未设为smtp且凭证错误;收件人须为字符串或模型,非数组;队列需确保queue_connection匹配并运行queue:work。

邮件发不出去但没报错?检查 .env 里的驱动和凭证
Laravel 的 Mail 默认走 log 驱动,只写日志不真发——这是最常被忽略的“假成功”。确认你改了 MAIL_MAILER 而不只是 MAIL_DRIVER(Laravel 8+ 已废弃后者)。
-
MAIL_MAILER=smtp(不是MAIL_DRIVER=smtp) -
MAIL_HOST填对,比如smtp.gmail.com或企业邮箱的 SMTP 地址 - Gmail 必须开「应用专用密码」,不能用账号密码;国内邮箱如腾讯企业邮要开 SMTP 并记下端口(
MAIL_PORT=465或587) -
MAIL_ENCRYPTION=tls或ssl要和端口匹配:465 通常配ssl,587 配tls
本地开发用 log 或 smtp?别在 .env 里硬切
开发时想看邮件内容又不想真发,log 驱动最安全;但日志里是原始 MIME 内容,难读。更实用的是用 smtp 驱动配本地调试服务(如 MailHog 或 Mailpit)。
- 装 MailHog:
docker run -d -p 1025:1025 -p 8025:8025 mailhog/mailhog -
.env改成:MAIL_MAILER=smtp、MAIL_HOST=localhost、MAIL_PORT=1025、MAIL_USERNAME=、MAIL_PASSWORD= - 访问
http://localhost:8025就能实时查收所有测试邮件 - 上线前务必切回真实 SMTP,否则生产环境会连不上本地 MailHog
Mail::to() 收件人失效?注意对象类型和数组结构
Mail::to() 接收 String、User 模型或带 email 属性的对象,但传普通数组会静默失败(尤其从请求里直接取 $request->input('emails'))。
- 错误写法:
Mail::to(['user@example.com'])->send(new WelcomeMail());→ 不报错但不发 - 正确写法:
Mail::to('user@example.com')->send(new WelcomeMail());或Mail::to($user)->send(...) - 批量发多个?用
cc()/bcc(),或者循环调用Mail::to()(别用数组塞进to()) - 模型必须有
email字段或实现routeNotificationForMail()方法
队列发邮件卡住?QUEUE_CONNECTION 和 php artisan queue:work 必须对齐
用了 ->delay() 或配置了 QUEUE_CONNECTION=database,但邮件一直不发,大概率是队列没跑起来,或连接配置没同步。
- 先确认
.env中QUEUE_CONNECTION和数据库/redis 配置一致(比如用了 Redis,REDIS_CLIENT得是predis或phpredis) - 运行
php artisan queue:work --stop-when-empty测试单次执行;别只靠supervisor启着就以为没问题 - 邮件类里不要在
__construct()中加载大量数据(如User::find()),构造函数在入队时执行,容易因模型不存在或权限问题失败 - 队列任务失败后默认进
failed_jobs表,记得用php artisan queue:failed查原因
真正麻烦的不是配通,而是发信逻辑混在业务里没隔离——比如注册后立刻发欢迎信,但用户数据还没 commit 完,队列里查不到刚创建的记录。这种时序问题,比 SMTP 配置更难 debug。