You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 8队列发邮件执行失败 进入失败队列报两类错误求解决

问题记录
  • 服务使用supervisor管理Laravel队列进程处理邮件发送,上线初期所有邮件写入jobs表后均可被正常消费投递
  • 异常出现后无通知邮件送达,当前jobs表为空,所有发送失败的任务全部落入failed_jobs表
  • 任务执行过程中固定抛出两类错误:
    第一类错误:
    ErrorException: fwrite(): SSL operation failed with code 1. OpenSSL Error messages:
    error:1420C0CF:SSL routines:ssl_write_internal:protocol is shutdown in /var/www/html/admin/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php:223
    
    第二类错误:
    Swift_TransportException: Expected response code 250 but got an empty response in /var/www/html/admin/vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/AbstractSmtpTransport.php:447
    
  • 当前已完成配置:
    • 使用Google Workspace(原GApps)邮箱,已在对应账号开启低安全应用访问权限
    • supervisor worker配置如下:
      [program:offerletter]
      process_name=%(program_name)s_%(process_num)02d
      command=php /var/www/html/admin/artisan queue:work database --sleep=3 --tries=3 --daemon
      autostart=true
      autorestart=true
      user=root
      numprocs=10
      redirect_stderr=true
      stdout_logfile=/var/www/html/admin/offerletter.log
      stopwaitsecs=3600
      
    • .env文件中SMTP配置如下:
      MAIL_MAILER=smtp
      MAIL_HOST=smtp.googlemail.com
      MAIL_PORT=587
      MAIL_USERNAME=###
      MAIL_PASSWORD=###
      MAIL_ENCRYPTION=tls
      MAIL_FROM_ADDRESS=###
      MAIL_FROM_NAME="${APP_NAME}"
      
    • 完成上述配置后问题仍未解决,需可落地的排查思路与解决方案。
排查思路与解决方案

1. 修正Google账号侧配置

  • Google已于2022年5月全面下线个人账号、Workspace账号的「低安全性应用访问」能力,即使后台显示开关为开启状态,该规则实际已不生效,不可依赖该配置实现SMTP发信
  • 先在Google Workspace管理员后台开启域内「允许应用访问账号」的相关权限,再对发信账号开启两步验证,生成16位应用专用密码,使用该密码替换.env中MAIL_PASSWORD的原有值,禁止使用账号原登录密码作为SMTP认证密码
  • 登录发信账号的Gmail网页端,检查是否存在安全告警、发信频率超限被临时封禁SMTP权限、发信行为被判定为垃圾邮件的通知,如有需先解除账号限制。

2. 修正SMTP配置并重载生效

  • 将MAIL_HOST配置项从smtp.googlemail.com替换为官方标准SMTP地址smtp.gmail.com,旧域名部分节点存在SSL证书异常、连接握手不稳定的问题
  • 配置修改完成后,先执行php artisan config:cache清除框架配置缓存,必须重启所有supervisor管理的队列进程:daemon模式下的队列进程会常驻内存,启动时已加载旧配置,不重启永远不会读取新的配置内容,重启命令为supervisorctl restart offerletter:*。

3. 修复队列长驻场景下的SMTP连接复用问题

  • 当前配置10个并发队列进程处理任务,SwiftMailer默认会复用SMTP长连接,进程长时间运行时,闲置连接会被Gmail侧主动断开,进程持有已失效的连接发信就会触发SSL关闭、空响应的错误
  • 调整队列启动参数,增加--timeout=120配置,限制单任务最长执行时间为120秒,避免进程长时间挂起持有无效连接
  • 适当下调并发进程数:SMTP发信属于IO密集型任务,10个并发很容易触发Gmail的发信频率限制,先将numprocs调整为2,验证功能正常后再按需逐步上调
  • 在邮件发送逻辑中增加连接重置逻辑,每次发信前主动断开旧连接重建,从代码层面规避长连接失效问题:
    // 发信前主动重置SMTP连接
    Mail::getSwiftMailer()->getTransport()->stop();
    // 原有发信逻辑
    Mail::to($target)->send(new NotificationMail());
    

4. 服务器网络与环境排查

  • 在服务器命令行手动测试SMTP连通性:执行telnet smtp.gmail.com 587,确认能正常收到SMTP服务端的欢迎响应,不存在服务器防火墙、安全组拦截出口587端口的问题
  • 检查服务器出口IP是否被Gmail列入垃圾邮件黑名单,若IP近期存在批量发信、发送垃圾内容的记录,会被Gmail主动断开连接返回空响应
  • 更新服务器系统的OpenSSL、ca-certificates组件到最新版本,执行update-ca-certificates更新系统根证书库,避免证书校验失败导致SSL连接异常。

5. 验证步骤

  • 上述所有调整完成后,执行php artisan queue:restart触发所有队列worker平滑重启,再执行php artisan queue:retry all将failed_jobs表中的失败任务重新推入队列消费,验证邮件是否可以正常送达。

内容的提问来源于stack exchange,提问作者Hanis Harun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 12:57:12