程序发不出邮件:SMTP连接与认证排查

程序提示“邮件发送失败”时,先保留错误码、发生时间和邮件服务端返回的文字。超时、证书错误、认证拒绝与投递失败对应不同环节。以下适用于应用通过已有SMTP服务提交邮件,排查应从实际运行应用的服务器或容器发起。

SMTP排查关系图:连接、TLS、认证与提交分别核验;服务端接收后仍需检查收件箱投递。
排查示意图:连接成功、TLS成功、服务端接收和收件人收到邮件,需要分别验证。

先核对服务地址与加密方式

从邮件服务的实际配置确认SMTP主机名、端口、加密方式、认证方式和允许使用的发件人。SMTP地址不一定等于邮箱域名,也不要把收信域的MX记录直接当作应用提交地址。下面的smtp.example.com只是占位,执行前必须替换。

常见提交方式 连接过程 配置要点
465 / 隐式TLS 建立连接后立即进行TLS握手 客户端选择隐式TLS,不能按普通明文SMTP连接
587 / STARTTLS 先进行SMTP协商,再升级为TLS 启用并要求TLS升级成功,随后才认证和提交

这是常见约定,最终以服务端提供的端口和加密配置为准。不能只改端口数字却保留原来的加密模式。

连接失败,先停在网络层

Windows PowerShell可测试实际SMTP端口:

Test-NetConnection -ComputerName smtp.example.com -Port 587

TcpTestSucceeded为True只说明建立了TCP连接。解析失败时查主机名和应用所在环境的DNS;超时时检查出站规则、路由和服务是否可达;连接被拒绝时核对监听端口。产品是否有邮件端口限制,应按实际产品与工单结果确认,不直接假定全部开放。

TLS握手通过了吗

以下适用于有OpenSSL 3.x与GNU timeout的Linux环境,按实际服务方式只选一条。它们不登录账户、不发送邮件,不要在会话中输入密码。

隐式TLS示例:

timeout 15s openssl s_client \
  -connect smtp.example.com:465 \
  -servername smtp.example.com \
  -verify_hostname smtp.example.com \
  -verify_return_error -brief

STARTTLS示例:

timeout 15s openssl s_client \
  -connect smtp.example.com:587 -starttls smtp \
  -servername smtp.example.com \
  -verify_hostname smtp.example.com \
  -verify_return_error -brief

查看协议、证书验证和错误信息。示例要求验证主机名,证书验证失败时返回错误;不要通过关闭验证让报错消失。核对SMTP域名、系统时间、证书链与应用使用的信任库。命令到15秒会被终止,退出码124也可能只是握手后等待输入超时,应结合此前输出判断。

认证失败与发件人拒绝分开查

535 5.7.8通常指认证凭据无效或不足。按服务要求核对用户名格式、SMTP功能是否启用,以及应使用应用专用密码还是其他认证方式;网页登录密码未必就是SMTP凭据。保密保存更新后的凭据,再按应用说明让实际发信进程加载新配置,不把密码写进诊断命令。

登录成功后仍可能因发件人未授权而被拒绝,需检查允许的发件地址、账号策略和完整返回文字。调试日志里的AUTH交换、令牌和Base64内容都可能泄露凭据,不要原样截图或提交。

服务端接收后,继续查投递结果

邮件内容提交结束后收到成功响应,说明服务器接收了投递责任,不等于收件箱已经收到。保存队列编号或消息标识,查看邮件服务日志、退信和收件箱垃圾邮件目录;其他阶段出现的250也不能单独当作整封邮件提交成功。

修改前保留原配置且保护凭据。修复后先检查待发送队列,避免重复通知,再向自己控制的收件箱发送一封已授权测试邮件,确认应用记录、服务端接收与实际到达三项一致。失败则撤回本次配置变动,并提交脱敏错误和发生阶段。

延伸阅读