01背景与现象
告警邮件回复遇到 SMTP 超时。若把所有超时记为失败,来源轮询器可能继续重发;但有些超时发生在正文发送之后,服务器可能已经接受邮件。
本文从实践记录中提炼投递状态设计,省略具体环境、事件时间与运行数据。下面的阶段顺序是模拟说明,不包含真实邮箱或邮件内容。
连接 → 协商与认证 → 发件人/收件人 → DATA
→ 发送正文 → 等待最终响应
↑ 此处断连:结果需要核查02排查证据
排查将网络失败发生的位置与服务器明确返回的状态分开记录。
- 正文发送之前的网络失败,与正文发送中或等待最终响应时的断连,含义不同。
- 服务器明确拒绝时,可以依据响应判断失败;最终响应没有到达客户端时,不能反推服务器未收到正文。
- 已经标为投递结果未知的记录,若又被来源轮询器按普通失败累计尝试次数,会破坏原有待核查语义。
离线测试可以验证状态分类与处理逻辑;实际投递行为需要独立的端到端验证。
03根因
问题在于失败状态过于粗糙:把“能够确定失败”与“无法确定结果”混在一起,再用同一种重试逻辑处理。业务侧希望只发送一次,但客户端无法凭一次超时证明对方没有接收。
因此必须让传输阶段、明确响应与持久化投递状态共同决定下一步,而不是由 AI 推测是否送达。
04处理
- 正文前的网络失败、明确的临时拒绝: 在同一次投递内采用有上限的重连与退避。
- 正文或最终响应阶段超时/断连: 保持“投递结果未知”,进入待核查状态,不盲目重发。
- 明确的永久拒绝: 记录确定性失败,走有限业务重试和最终失败通知边界。
- 重试身份: 首次业务邮件重试复用稳定的 Message-ID;该标识便于追踪,本身不保证收件服务器会去重。
- 来源轮询: 对已有未知结果返回待核查语义,不再反复累计失败尝试。
确定性投递达到重试上限后,应通知人工处理。未知结果不被改写为最终发送失败。
05验证
实践中的离线验证覆盖了 SMTP 阶段分类、有限重连、稳定邮件标识、未知结果状态隔离和最终失败通知。
这些结果用于验证代码处理逻辑,不能作为实际投递成功率。端到端验证还需覆盖服务端响应、状态持久化和通知行为。
06剩余问题
未知结果必须结合服务端记录、收件情况或其他可信证据人工核查。在确认之前,既不能宣称送达,也不能把它当作一定未送达。
应用这套方法时,应在隔离测试链路中验证阶段行为、状态持久化和最终失败通知。离线通过不能直接证明实际投递问题已经解决。