先查 storage/logs/laravel.log 和 /var/log/maillog,再清配置缓存、确认 MAIL_FROM_ADDRESS 与 config/mail.php 一致,检查端口加密匹配(如QQ邮箱用465+ssl)、防火墙/SELinux/PHP扩展(openssl、mbstring)是否就绪。

先看 storage/logs/laravel.log 里有没有明确报错,没日志就等于瞎猜——90% 的问题靠它直接定位。
查 Laravel 日志和系统邮件日志
错误不会自己说话,但日志会。Laravel 默认把邮件失败堆栈写进 storage/logs/laravel.log,比如 Swift_TransportException、Connection could not be established 或 535 Authentication failed 这类信息,基本能锁定是认证、DNS、SSL 还是网络层的问题。
同时别漏掉系统级日志:/var/log/maillog(CentOS/RHEL)或 /var/log/mail.log(Debian/Ubuntu)。如果 Laravel 日志只说“连接超时”,而 maillog 里压根没记录出站连接尝试,说明请求根本没发出去——大概率是防火墙、SELinux 或 PHP 扩展缺失挡在了最外层。
- 用
tail -f storage/logs/laravel.log和tail -f /var/log/maillog同时观察,发一次邮件看两边谁先有动静 - 如果
maillog里出现connect to smtp.qq.com[163.177.72.143]:25: Connection refused,说明端口被屏蔽或服务拒绝(阿里云/腾讯云默认封 25 端口) - 如果
laravel.log报stream_socket_client(): php_network_getaddresses: getaddrinfo failed,就是 DNS 解析失败,得查nslookup smtp.qq.com或手动加/etc/hosts
确认 MAIL_* 配置没被缓存或覆盖
Laravel 会缓存配置,改完 .env 不清缓存 = 白改。尤其注意 MAIL_FROM_ADDRESS 和 config/mail.php 里的 from.address 必须一致,否则 QQ/163 邮箱会直接拒信,报错类似 Expected response code 250 but got code “501”。
- 执行
php artisan config:clear(不是cache:clear),再试一次 - 用
php artisan tinker输入config('mail'),确认输出的host、port、encryption、username全部是你预期的值 - QQ 邮箱必须用
MAIL_PORT=465+MAIL_ENCRYPTION=ssl;163 邮箱同理;Mailtrap 则是2525+tls——端口和加密方式不匹配,连接必然失败
检查 CentOS 系统层限制:防火墙、SELinux、PHP 扩展
CentOS 上邮件发不出去,八成卡在这三层。Apache/Nginx 进程默认没有发信权限,SELinux 会拦截,防火墙可能拦 SMTP 出站,PHP 缺扩展则连 socket 都建不起来。
- 运行
php -m | grep -E 'openssl|mbstring|xml',缺openssl就没法握手,缺mbstring可能导致编码异常(尤其中文发件人名) - 执行
sudo firewall-cmd --list-ports,确认465/tcp或587/tcp已开放(25基本不用指望) - 临时关 SELinux 测试:
sudo setenforce 0;如果此时邮件通了,说明需要调整策略,而不是永久关闭 - 别信“已装 sendmail”——Laravel 默认走 SMTP,不是本地 MTA;装了 sendmail 却没配
MAIL_MAILER=sendmail,它根本不会用
绕过 SSL 证书验证失败(常见于自建环境或旧 OpenSSL)
报错含 certificate verify failed 或 unable to connect to ssl://smtp.qq.com:465,通常是 PHP 的 OpenSSL 没加载 CA 证书,或者系统时间严重偏差(±5 分钟以上也会触发证书校验失败)。
- 运行
php -r "print_r(openssl_get_cert_locations());",看default_cert_file路径是否存在;若为空或文件不存在,需手动下载 CA 包并配置openssl.cafile(通常在php.ini) - 检查系统时间:
date,若不准,运行sudo ntpdate -s time.nist.gov同步 - 开发环境可临时禁用证书验证(仅限调试):在
config/mail.php的stream键下加'stream' => ['ssl' => ['verify_peer' => false, 'verify_peer_name' => false]],但生产环境严禁这么做
真正难排查的,往往是多个条件叠加:比如阿里云服务器上,MAIL_PORT=25 配置没改,firewall-cmd 开了 25 却没用,setenforce 0 也试了,最后发现是 PHP 没装 openssl 扩展——连 TLS 握手都发起不了,日志里连“connection refused”都不会出现,只有静默失败。动手前,先盯住日志,再一层层剥开系统限制。


















