如何解决Amazon SES发信报swift_transportexception 250响应码空响应错误
问题根因
该Swift_TransportException报错、偶发后全量发信失败、重启队列worker即可临时恢复的现象,本质是常驻队列进程复用的SMTP长连接被Amazon SES主动断开导致的:SES SMTP服务默认空闲连接超时时间为300秒,队列worker闲置超过5分钟后,持有的旧SMTP连接已经失效,Swift Mailer默认没有自动重连逻辑,复用失效连接发送请求时就会拿到空响应,且后续所有发信请求都会复用这个坏连接,直接导致全链路发信失败,重启worker会销毁旧连接新建有效连接,因此可以临时恢复。
可落地修复方案
- 每次发信新建传输实例,发信完成后主动断开
不要全局复用Swift_SmtpTransport实例,每次发信前新建传输实例,发信完成后调用stop()方法主动销毁连接,完全避免闲置连接失效问题,代码示例:
// 发信逻辑执行前新建传输实例 $transport = (new Swift_SmtpTransport('email-smtp.对应区域.amazonaws.com', 587, 'tls')) ->setUsername('你的SES SMTP用户名') ->setPassword('你的SES SMTP密码') ->setTimeout(240); $mailer = new Swift_Mailer($transport); // 组装邮件内容 $message = (new Swift_Message('邮件主题')) ->setFrom(['发件人地址' => '发件人名称']) ->setTo(['收件人地址']) ->setBody('邮件正文'); $mailer->send($message); // 发信完成后主动断开连接 $transport->stop();
- 配置队列worker自动回收机制
给常驻队列进程设置最大处理任务数或最大存活时间,比如Laravel队列启动时添加--max-jobs=50--max-time=180参数,让worker处理指定数量任务或运行指定时长后自动退出,由进程管理工具自动拉起新进程,天然规避连接超时问题。 - 添加传输异常自动重试逻辑
如果需要复用传输实例提升发信性能,新增异常捕获逻辑,触发传输异常时自动重置连接重试一次:
try { $mailer->send($message); } catch (Swift_TransportException $e) { // 重置失效连接后重试 $transport->stop(); $transport->start(); $mailer->send($message); }
- 调整端口配置
优先使用587端口的显式STARTTLS协议,避免使用465端口的隐式TLS协议,后者在部分网络环境下闲置连接被中断的概率更高。
内容的提问来源于stack exchange,提问作者Ahsan Saleem
相关产品推荐
相关产品推荐

