SMTP连接超时主因是网络阻断或协议不匹配,应先用telnet/openssl直连验证;CI4配置键名大小写敏感、值类型严格,需正确设置SMTPHost、SMTPPort(整数)、SMTPCrypto;Gmail须用应用专用密码而非登录密码。

SMTP 连接超时的常见原因和快速验证方法
CI3 和 CI4 邮件超时,90% 不是代码写错,而是底层连接被阻断或协议不匹配。先别改代码,用 telnet 或 openssl 直连 SMTP 服务器验证基础连通性:
-
telnet smtp.gmail.com 465—— 如果卡住或报Connection refused,说明防火墙、PHP 禁用了 socket 或服务器不允许直连 -
openssl s_client -connect smtp.gmail.com:465 -crlf—— 成功返回证书信息,说明 SSL 层通;失败则可能是端口/加密方式错(比如误配 TLS 端口 587 却设了smtp_crypto = ssl) - 本地开发环境(如 XAMPP/MAMP)默认禁用
fsockopen,检查php.ini中是否设置了disable_functions = fsockopen,stream_socket_client
CI4 中 .env 配置必须严格匹配键名和值类型
CI4 的邮件配置键名大小写敏感且路径固定,写错一个字符就退化为 mail() 函数(导致超时或静默失败):
- 必须用
email.default.SMTPHost,不是email.smtp.host或email.production.SMTPHost -
email.default.SMTPPort必须是整数,不能带引号:465✅,"465"❌(CI4 会转成字符串,内部调用失败) -
email.default.SMTPCrypto只接受ssl或tls,大小写敏感;Gmail 465 端口必须用ssl,587 端口必须用tls - 确认
app/Config/Boot/environment.php中已调用DotEnv::load(),否则 .env 里所有配置都不生效
CI3 和 CI4 初始化方式差异导致的隐性超时
CI3 允许在控制器里反复 $this->email->initialize(),CI4 则更严格:一旦 Email 实例初始化过,再次调用 initialize() 不会覆盖已有配置,容易沿用旧的错误参数(比如缓存了超时的 host):
- CI3 中推荐每次发送前都重新
initialize($config),避免复用残留状态 - CI4 中应直接使用
service('email')获取新实例,而不是复用$this->email(尤其在 CLI 或队列场景下) - 若用 CI4 的
service('email'),确保没在构造函数或类属性里提前赋值$this->email,否则后续调用仍走旧实例 - 超时发生时,打开 CI4 的日志(
app/Logs),搜索SMTP connect() failed或fsockopen(): unable to connect,比页面错误提示更准
Gmail/Outlook 等第三方邮箱的认证陷阱
2022 年后 Gmail 已彻底关闭“低安全性应用访问”,用登录密码必然超时或拒绝连接:
- 必须启用两步验证,再生成应用专用密码(16 位),填入
email.default.SMTPPass—— 不能是你的 Gmail 登录密码 - Outlook/Hotmail 使用
smtp-mail.outlook.com,端口 587 +tls,不是 465;填错加密方式会导致握手卡死,表现就是超时 - 国内阿里云/腾讯云服务器常被 Gmail 拒绝连接(IP 被标记为高风险),此时即使配置全对也会超时;换 VPS 或用企业邮箱 SMTP 更稳定
- CI4 默认开启
SMTPKeepAlive = false,单次发送完即断开;若需连续发多封,可手动设为true避免重复握手开销
超时问题最麻烦的地方在于它不报明确错误,只卡住几秒然后失败。务必从网络层开始验证,而不是一上来就调代码逻辑。


















