Laravel应用邮件发送失败求助:Swift_TransportException错误(预期响应码250却收到空响应)
首先,这个Swift_TransportException空响应错误,本质是Laravel的SwiftMailer在和Office365 SMTP服务器建立连接或发送命令时,没有收到预期响应就直接断连了。结合你已经做的排查步骤,我来梳理几个最可能的根源和修复方法:
1. TLS版本兼容性问题
Office365现在强制要求TLS 1.2或更高版本,但旧版本的SwiftMailer或PHP环境可能默认使用更低版本的TLS,导致握手失败后静默断连。
修复方法:
在config/mail.php的SMTP配置数组中,添加强制指定TLS 1.2的stream配置:
'smtp' => [ 'transport' => 'smtp', 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 'port' => env('MAIL_PORT', 587), 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 'username' => env('MAIL_USERNAME'), 'password' => env('MAIL_PASSWORD'), 'timeout' => null, 'auth_mode' => null, // 添加下面这段配置 'stream' => [ 'ssl' => [ 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, 'verify_peer' => true, 'verify_peer_name' => true, ], ], ],
修改后执行php artisan config:clear,再测试邮件发送。
2. 服务器网络/防火墙限制
虽然你手动能发邮件,但服务器的网络环境可能被防火墙、安全组或者服务商限制了出站的587端口,导致无法和Office365的SMTP服务器建立连接。
验证方法:
在服务器上执行命令测试端口连通性:
telnet smtp.office365.com 587
如果连接失败(提示无法打开连接),说明是网络限制,需要联系服务器管理员或服务商开放587端口的出站权限。
3. SwiftMailer版本过时
旧版本的SwiftMailer可能和Office365的最新SMTP协议不兼容,导致交互过程中出现异常断连。
修复方法:
根据你的Laravel版本,更新SwiftMailer到兼容的最新版本:
# 适用于Laravel 5.8及以上版本 composer require swiftmailer/swiftmailer:^6.3
更新后执行composer dump-autoload和php artisan config:clear。
4. 队列进程未完全重启
虽然你执行了php artisan queue:restart和重启supervisor,但有时候队列进程可能没有被彻底杀掉,仍然加载着旧的配置或有残留问题。
修复方法:
- 停止supervisor服务:
service supervisor stop - 手动杀掉所有队列进程:
pkill -f "php artisan queue:work" - 重新启动supervisor:
service supervisor start
5. Office365账号的隐性安全限制
即使你能手动发邮件,服务器的IP可能被Office365的安全系统标记为可疑,或者账号有特殊限制:
- 如果账号开启了多因素认证(MFA),必须使用应用密码代替普通密码(手动发邮件用的是MFA验证,但Laravel无法处理MFA,所以需要在Office365后台创建应用密码)。
- 登录Office365管理后台,查看安全日志,确认服务器IP是否被阻止。
快速测试方法
为了排除队列的干扰,先测试同步发送邮件:
创建一个临时路由或Artisan命令,直接发送邮件:
// 在routes/web.php中添加 Route::get('/test-smtp', function() { try { \Illuminate\Support\Facades\Mail::raw('Test SMTP Connection', function($message) { $message->to('your-test-email@example.com') ->subject('Laravel SMTP Test'); }); return '邮件发送成功!'; } catch (\Exception $e) { return '错误信息:'.$e->getMessage(); } });
访问这个路由,查看实时的错误信息,能更精准定位问题。
内容的提问来源于stack exchange,提问作者Fokwa Best

