依据 RFC 5321 的拒收语义,应如何做邮件列表卫生与无效地址清理?

1 依据 RFC 5321 的拒收语义,应如何做邮件列表卫生与无效地址清理?
拒收语义的第一判据:首位数字

RFC 5321 第 4.2.1 节规定了三位回复码首位数字的语义,这是全部清理逻辑的起点:

  • 4yz 暂时性否定完成——命令未被接受、所请求的动作未发生,但错误条件是暂时的,可以再次请求该动作。
  • 5yz 永久性否定完成——命令未被接受、动作未发生,且以完全相同的方式重试不会成功

常见的永久性拒收码及其规范含义:550 所请求的动作未执行,信箱不可用(例如信箱未找到、无访问权限,或因策略原因被拒);551 用户非本地;552 邮件动作中止,超出存储配额;553 动作未执行,信箱名不被允许(例如信箱语法不正确)。

常见的暂时性拒收码:421 服务不可用,关闭传输通道;450 信箱不可用(例如信箱忙或因策略被临时阻断);451 动作中止,处理中发生本地错误;452 动作未执行,系统存储空间不足。

值得注意的是 550 的双重身份:它既用于「信箱不存在」,也用于「因策略被拒」。仅凭 550 就断定地址无效是错误的——这正是需要第二判据的原因。

第二判据:增强状态码给出「为什么」

SMTP 基础码回答「永久还是暂时」,RFC 3463 的增强状态码回答「因为什么」。两者的 class 必须一致(550 不可能携带 4.x.x)。因此判定顺序固定为:先看首位数字,再看增强码的 subject

  • 5.1.1 / 5.1.2 / 5.1.3(地址类)—— 指向地址本身无效或语法错误。
  • 5.1.6 —— 信箱已迁移且无转发地址。
  • 5.2.1 —— 信箱已禁用、不接收消息。
  • 5.7.x(安全与策略类)—— 不是地址问题。删除这个收件人不解决任何事,应当排查认证、信誉与策略。

同一个 550,配 5.1.1 时应移除地址,配 5.7.1 时应保留地址并开排障工单。缺了这一层区分,清理动作就会一边误删有效地址,一边掩盖真实的认证故障。

何时移除,何时保留重试

立即移除:RCPT 阶段收到 550/553 且增强码为 5.1.x,或 DSN 中 Action=failedStatus5.1.x / 5.2.1。这些明确指向地址无效或信箱禁用,继续投递只会持续产生无效投递记录,直接损害信誉。

按 class 判断552(超出配额)与 5.2.2(信箱已满)在语义上是容量问题而非地址无效。不同实现可能以 4 表达(等待用户清理)或以 5 表达(信箱长期废弃)。处理原则是以实际收到的 class 为准:为 4 则重试,为 5 则按永久处理。

保留并重试:所有 4xx。RFC 5321 第 4.5.4.1 节给出的重试策略要点是——某个目标一次尝试失败后必须延迟再试,重试间隔一般不宜短于 30 分钟;重试持续到消息发出或发送方放弃,而放弃时间通常需要至少 4 至 5 天。持续软退的地址应先进入抑制列表观察,而非直接删除。

不做任何名单变更:DSN 中 Action=delayed 只是延迟通知。把它计为退信是常见错误,会导致大量有效地址被误清理。

为什么不能依赖 VRFY 或探测式发信

试图在发送前「验证地址是否存在」的两类做法都不可靠:

  • VRFY / EXPN:RFC 5321 讨论了这两个命令带来的信息泄露风险,允许站点使其不可用或返回 252(无法验证该用户,但会接收消息并尝试投递)。现实中绝大多数服务器已关闭或恒返回 252,其结果不能作为地址有效性的依据
  • 探测式 RCPT:即建立连接、发出 RCPT 后立即断开。它同样不可靠——大量服务器实现 catch-all(接受本域全部收件人)或延迟拒绝(在 DATA 之后甚至接收后才判定),RCPT 阶段的 250 并不代表信箱存在。更重要的是,这种行为在接收侧的日志中与地址收割攻击难以区分,会直接损害发送 IP 的信誉,属于得不偿失。

可靠的地址有效性信息,只能来自真实投递产生的 DSN,以及订阅环节的确认。这也是为什么列表卫生必须建立在完整的退信回收链路之上,而不是某个「验证服务」。

拒收应在 SMTP 事务内完成:反弹(backscatter)问题

RFC 5321 第 6.1 节确立了一条责任规则:SMTP 服务器一旦接受了一封消息,就承担了投递或中继的责任;若接受之后才发生投递失败,接收方必须生成并发出通知消息。第 6.2 节进一步指出,对于不受欢迎的消息,在 SMTP 事务中直接拒绝,远优于先接收再退回或丢弃

原因是:垃圾邮件的信封发件人通常是伪造的。先接收再生成退信,等于把退信发给了被伪造的无辜第三方,这就是反弹(backscatter)。它既骚扰无关方,也会使自己的出口 IP 因大量投递到不存在地址的退信而信誉受损。

这条规则同时约束两侧:作为接收方,应在 RCPT 阶段就拒绝无效收件人;作为发送方,则必须保证自己的信封回退地址域能够实际收信,并把收到的 DSN 自动驱动到名单清理流程——否则退信无人接收,清理链路就是断的。

别名与邮件列表的回退路径差异

RFC 5321 第 3.9 节区分了两种转发形态,这直接决定退信落到谁手里:

  • 别名(alias):仅替换收件人地址,不改变信封发件人。后续投递失败产生的退信回到原始发件人。
  • 邮件列表(list):列表成为新的发起者,信封回退路径应当改为指向列表维护者(而非原始发件人),以便由列表方处理成员地址失效。

工程后果很具体:列表若未改写回退路径,某个成员地址失效产生的退信会打到毫不相干的原始发件人身上——列表运营者收不到这条退信,也就无从清理;而原始发件人则被淹没在与自己无关的退信里。许多长期无法清理的「僵尸列表」,根因就在这一步配置错误。这也是 VERP 的价值所在:为每个收件人生成唯一的回退地址,使退信能被精确归因到具体订阅者。

主动卫生:不要等到退信才清理

被动清理只能处理已经失效的地址,M3AAWG Senders BCP 强调的是从源头控制列表质量:

  • 只使用收件人主动订阅获得的地址,不购买、不租用、不抓取;
  • 在订阅入口做地址格式校验与防机器人提交,避免录入错误地址与恶意注入的第三方地址;
  • 对长期零互动的地址做再确认或停发——废弃地址被回收改造为垃圾陷阱是列表老化的主要风险;
  • 监控垃圾陷阱命中,一旦出现应回溯该批地址的获取渠道,而不只是删掉命中的那一个;
  • 把退订与投诉在当日纳入抑制列表,人工批处理必然滞后,而滞后期产生的每一封邮件都在制造新的投诉。

参考:IETF RFC 5321《Simple Mail Transfer Protocol》(Draft Standard,2008-10)——尤见 4.2.1 回复码理论、4.5.4.1 重试策略、3.9 别名与列表、6.1 与 6.2 可靠性与不受欢迎的消息;增强状态码见 RFC 3463,退信报文格式见 RFC 3464;列表实践见 M3AAWG Sender BCP v3