smtp 配置后发不出邮件,首要检查 mail_mailer=smtp 是否设置,laravel 9+ 默认为 log 驱动,未设此值则其他 smtp 参数无效;mailgun 需设 mail_mailer=mailgun 并正确配置 mailgun_domain 和 mailgun_secret;ssl/tls 与端口须匹配(如 gmail 用 tls+587);database 队列驱动不可靠,生产环境应使用 redis 或 supervisor 管理队列。

SMTP 配置后发不出邮件,先检查 MAIL_MAILER 环境变量
很多人改了 .env 里的 MAIL_HOST、MAIL_PORT 等一堆参数,但邮件就是不发——根本原因是 Laravel 9+ 默认用 log 驱动,不是 smtp。必须显式设为 smtp 才走 SMTP 发送逻辑。
-
MAIL_MAILER=smtp是硬性前提,漏掉这行,其他全白配 - Laravel 8 及更早版本用
MAIL_DRIVER,升级后别混用,MAIL_DRIVER已废弃,只认MAIL_MAILER - 本地开发时容易误设成
MAIL_MAILER=log(方便调试),上线前务必核对
Mailgun API Key 配置错位导致 Connection could not be established with host api.mailgun.net
Mailgun 不走 SMTP,而是 http API 调用;但很多人照着 SMTP 模板填,把 MAIL_PASSWORD 当作 API Key 塞进去,结果连不上。
- Mailgun 必须设
MAIL_MAILER=mailgun,且删掉所有 SMTP 相关配置(MAIL_HOST、MAIL_PORT等) -
MAILGUN_DOMAIN填你 Mailgun 控制台里「Sending」→「Domains」页显示的域名(如mg.example.com),不是邮箱后缀 -
MAILGUN_SECRET填的是「Domain Settings」→「API Security」里的private API Key,不是 Webhook Key 或 public Key - Mailgun 免费版默认只允许向已验证邮箱发信,测试时务必用控制台里「Verified Emails」列表里的地址收件
SSL/TLS 和端口不匹配引发 stream_socket_enable_crypto(): SSL operation failed
SMTP 连接失败一大半卡在加密层,不是账号密码错,而是协议和端口没对上。
- Gmail 使用
MAIL_ENCRYPTION=tls+MAIL_PORT=587;若强行设ssl加密,会握手失败 - 某些企业邮箱或自建 Postfix 要求
MAIL_ENCRYPTION=ssl+MAIL_PORT=465,二者必须严格配套 -
MAIL_ENCRYPTION=NULL并非“不加密”,而是禁用加密层,仅用于本地smtp测试(如 MailHog),生产环境禁用 - PHP 版本影响:PHP 8.1+ 对 TLS 1.3 支持更严,老 SMTP 服务若只支持 TLS 1.0/1.1,可能需降级或换服务商
队列发送邮件时 QUEUE_CONNECTION=database 导致邮件延迟或丢失
用 php artisan queue:work 发邮件没问题,但切到 database 驱动后,邮件迟迟不发甚至静默失败——这不是邮件配置问题,是队列本身不可靠。
-
database队列驱动没有守护进程机制,queue:work停了就停摆,适合开发调试,不适合生产 - 真正可用的生产队列至少要用
redis或supervisor管理的database进程,否则任务积压在jobs表里没人捞 - 邮件任务默认不重试,失败后直接进
failed_jobs表,记得跑php artisan queue:failed查原因 - 如果只是想异步发邮件又不想搭 Redis,改用
sync驱动 + 前台响应后后台dispatch(new SendEmailJob())更可控
邮件配置本身不复杂,真正卡住人的永远是环境链路:DNS 解析是否通、防火墙是否放行端口、服务商是否限制 IP、队列是否真在跑——这些比选 SMTP 还 Mailgun 更容易被跳过检查。