邮件在队列里卡了几个小时才发出,属于故障吗?重试与放弃有没有标准?

1 邮件在队列里卡了几个小时才发出,属于故障吗?重试与放弃有没有标准?
排队重试是协议规定的常态

RFC 5321 第 4.5.4.1 节(Sending Strategy)写明:SMTP 客户端的通用模型是一个或多个进程周期性尝试发送外发邮件;无法立即发出的邮件必须入队,并由发送方周期性重试;队列条目不仅包含邮件本身,还包含信封信息。因此「邮件延迟数小时后成功投出」在协议层面属于正常行为,而不是故障。第 4.5.4 节还给出两条队列纪律:任何排队策略必须对所有活动按命令逐项设置超时;任何情况下排队策略都不得对错误邮件再发出错误邮件。

重试间隔与放弃时间的规范值

同样出自第 4.5.4.1 节:一次尝试失败后,发送方必须延迟对该目的地的重试;一般而言重试间隔应当至少 30 分钟,但当客户端能判断未投递原因时,更精细可变的策略会更有利。重试持续到邮件发出或发送方放弃,放弃时间通常需要至少 4 到 5 天;对退信通知及同类错误邮件,可以设置比普通邮件更少的最大重试次数。该节明确要求:重试算法的各项参数必须可配置。此外客户端应当维护一份「暂时无法到达的主机及其连接超时」清单,而不是简单地把排队邮件逐条重投。

经验性退避节奏

第 4.5.4.1 节转述实践经验:失败通常是瞬态的(目标系统或其连接崩溃),因此倾向于采用这样的策略——邮件进入队列的第一个小时内尝试两次连接,随后退避到每两三小时一次。该节还解释了为什么不能对同一不可达主机的全部队列邮件每轮都重试:客户端通常要等待数分钟超时才能判定投递失败,即使每连接只超时一分钟,对同一主机的几十甚至上百封排队邮件反复重试也会造成极大延迟与互联网资源浪费。

两个容易踩的缓存与并发坑

同节提醒:客户端应当非常谨慎地缓存服务器的否定响应——极端情况下,同一 SMTP 连接内多次发出 EHLO,服务器可能返回不同答案;更要紧的是,对 MAIL 命令的 5yz 响应不得被缓存。效率方面,当一封邮件要投给多个收件人且下一跳服务器相同时,应当只传输一份副本,即使用 MAIL、RCPT、RCPT、…、RCPT、DATA 的命令序列,而不是反复 MAIL/RCPT/DATA;但当地址非常多时,可以对每个 MAIL 命令下的 RCPT 数量设上限。为保证及时投递,客户端可以支持多个并发外发事务,但也应设限以免主机资源被邮件占满。

DNS 临时故障也会造成堆积

第 5.1 节(Locating the Target Host)规定:解析目的域时若返回临时错误,邮件必须入队并稍后重试(并指回第 4.5.4.1 节);若返回域不存在错误,则必须作为错误报告。排查队列堆积时,先区分「4xx 被对端限速」「DNS 临时失败」「本地投递进程或存储瓶颈」三类,再对症处理,比盲目调大并发有效。

参考:https://www.rfc-editor.org/rfc/rfc5321.txt