RFC 5321 的 SMTP 回复码分级与队列重试策略应如何理解?

1 RFC 5321 的 SMTP 回复码分级与队列重试策略应如何理解?
三位回复码的结构语义(§4.2.1)

SMTP 回复码三位数字各有分工:第一位表明响应是好、坏还是不完整——实现简单的客户端仅凭首位即可决定下一步(照常推进、重做、退避等);第二位供想知道错误大类(如邮件系统错误、命令语法错误)的客户端参考;第三位及任何补充信息则保留给最细粒度的区分。文档亦指出 SMTP 的码值架构借鉴自 FTP,但 SMTP 是「一命令一响应」的同步模型,且 FTP 的 1yz 码不属于 SMTP 模型

首位数字的四类取值
  • 2yz 正向完成(Positive Completion):所请求动作已成功完成,可发起新请求。
  • 3yz 正向中间态(Positive Intermediate):命令已被接受,但动作被暂缓,等待更多信息;客户端应再发命令补足。该类用于命令序列组,典型即 DATA
  • 4yz 临时性负向完成(Transient Negative Completion):命令未被接受、动作未发生,但错误是临时的,可以再次请求,发送方应回到命令序列起点。文档坦承「临时」一词在收发双方之间难以取得一致解释,各回复的时间尺度也可能不同,但 SMTP 客户端 SHOULD 重试。
  • 5yz 永久性负向完成(Permanent Negative Completion):命令未被接受、动作未发生,客户端 SHOULD NOT 以相同序列原样重发。不过即便是「永久」错误也未必不可修复,故人工用户日后(如改正拼写、账户状态变更后)可主动指示客户端重新发起命令序列。
4yz 与 5yz 的判定经验法则

RFC 5321 给出一条实用判据:如果「命令形式不变、且收发双方属性也不变」的情况下原样重复该命令有可能成功,那它就该是 4yz;否则应为 5yz(即无需接收方部署新实现即可成功者归 4yz)。这条法则是排查「本该软退信却被硬退」类误配置的直接依据。

发送策略与重试节奏(§4.5.4.1)

SMTP 客户端的一般模型是一个或多个进程周期性尝试投递外发邮件:撰写程序通常有办法为新邮件申请「立即处理」,而无法立即发出的邮件 MUST 入队,由发送方周期性重试;队列条目不仅含邮件本身,还须含信封信息。核心参数如下:

  • 某一目的地一次尝试失败后,发送方 MUST 延迟再试;一般重试间隔 SHOULD 至少 30 分钟——但若客户端能判断投递失败的具体原因,采用更精细、可变的策略会更有益。
  • 重试持续到发出成功或发送方放弃;放弃时限通常需至少 4–5 天。对投递失败通知一类的错误邮件,MAY 设置比普通邮件更短的最大重试次数。
  • 重试算法的各项参数 MUST 可配置。
  • 客户端 SHOULD 维护一份「无法到达的主机及对应连接超时」清单,而不是单纯地对队列条目做无差别重试。
退避曲线与队列催发

文档援引运维经验:失败通常是瞬时的(目标系统或其链路崩溃),因此倾向于这样的策略——邮件入队第一小时内尝试两次连接,此后退避到每两三小时一次。此外,客户端可与服务器配合缩短排队延迟:例如既然刚从某地址收到邮件,那么排给该主机的队列邮件此刻多半也能发出。规范指出,这一原则的应用在很多情况下可以消除对 ETRN(RFC 1985)这类显式「立即发送队列」功能的需求

参考:RFC 5321《Simple Mail Transfer Protocol》,https://www.rfc-editor.org/rfc/rfc5321 —— 章节 4.2.1 / 4.5.4.1 / 3.6 / 5.1