程序发不出邮件:SMTP连接与认证排查
程序提示“邮件发送失败”时,先保留错误码、发生时间和邮件服务端返回的文字。超时、证书错误、认证拒绝与投递失败对应不同环节。以下适用于应用通过已有SMTP服务提交邮件,排查应从实际运行应用的服务器或容器发起。
先核对服务地址与加密方式
从邮件服务的实际配置确认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也不能单独当作整封邮件提交成功。
修改前保留原配置且保护凭据。修复后先检查待发送队列,避免重复通知,再向自己控制的收件箱发送一封已授权测试邮件,确认应用记录、服务端接收与实际到达三项一致。失败则撤回本次配置变动,并提交脱敏错误和发生阶段。