邮件别名与自动转发为什么会成环?系统靠什么发现并切断循环?

1 邮件别名与自动转发为什么会成环?系统靠什么发现并切断循环?
环从哪里来:别名与列表的展开规则

RFC 5321 第 3.9 节(Mailing Lists and Aliases)规定:具备 SMTP 能力的主机应当同时支持别名与列表两种地址展开模型;当邮件被投递或转发到展开后列表中的每个地址时,信封中的返回地址(MAIL FROM)必须被改为管理该列表的人或实体的地址,但邮件头部分必须保持不变,特别是 From 字段不受影响。第 3.9.1 节说明别名的展开方式:接收方邮件系统只是把信封中的伪邮箱地址逐一替换为展开后的各个地址,信封其余部分与邮件正文保持不变,然后投递或转发。正因为展开只换地址、不改内容,若两个别名互相指向对方,或转发目标最终又指回源邮箱,邮件就会在两个系统之间被无限次重新投递。

标准的环路检测手段:数 Received

RFC 5321 第 6.3 节(Loop Detection)给出的方法很朴素但有效:简单统计邮件中 Received 头字段的数量,已被证明是一种有效(尽管很少是最优)的邮件系统环路检测方法。使用该技术的服务器应当采用一个较大的拒绝阈值,通常至少 100 条 Received 条目。同节还规定:无论采用何种机制,服务器必须包含检测并阻止简单环路的措施。这一方法之所以成立,正是因为第 4.4 节强制要求每一跳都必须前置一条 Received 且不得删除已有的行——环路每转一圈,计数就单调增加。

为什么阈值定得这么高

阈值取 100 而不是 5 或 10,是因为正常邮件也可能经过相当多跳:提交服务器、出口网关、若干中继、邮件列表展开器、入口网关、内部投递服务器都会各加一行。把阈值设得过低会误杀合法的多跳邮件;设得过高则环路要转很多圈才被切断,期间持续消耗队列与带宽。规范给出的「至少 100」是下限建议,实际部署时需要结合本域正常邮件的 Received 计数分布来定。

退信不得对退信:另一类环

第 4.5.4 节规定:任何排队策略都不得在任何情况下对错误邮件再发出错误邮件。配套机制在第 4.5.5 节(Messages with a Null Reverse-Path):退信通知、投递状态通知(DSN)与消息处置通知(MDN)等若干类通知邮件,被现行与拟议标准要求以空反向路径发送,并发往前一封邮件的反向路径。同节进一步要求:自动邮件处理系统的实现者不应回复空反向路径的邮件,也不应在转发这类邮件时添加非空反向路径或把空反向路径改成非空。违反这两条,就会出现「A 退给 B、B 再退给 A」的退信风暴。

排查顺序建议

结合以上条款,定位转发环的顺序是:先看被卡邮件的 Received 计数是否异常增长,从最上面一行往下读,找出重复出现的两台主机(第 4.4 节保证顺序可靠);再检查这两台主机上与该地址相关的别名表与用户级自动转发规则(第 3.9 节的展开点);最后确认通知类邮件的反向路径是否被错误地改成了非空(第 4.5.5 节)。只调大阈值不解决根因,必须找到互指的那一对规则。

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