邮箱满了服务器应该回哪个码?配额该怎么设计与告警?
RFC 5321 第 4.2.3 节给出两个容易混淆的代码:452 请求的动作未执行:系统存储空间不足(4yz,瞬态);552 请求的邮件动作中止:超出存储配额(5yz,永久)。RFC 3463 在细分码层面把语义分得更清楚:第 3.3 节的 X.2.2 邮箱已满——用户超出了单邮箱管理配额或物理容量,语义上收件人可以删除邮件腾出空间,该码应当作为持续性瞬态失败使用;而第 3.4 节的 X.3.1 邮件系统已满指的是整个邮件系统层面的空间耗尽。结论:单个用户邮箱超配额,正确的处置是回 4xx 让对方重试,而不是永久拒收。
RFC 5321 第 4.2.1 节给出的判据是:如果一条命令在命令形式与收发双方属性都不变的前提下重复执行有可能成功,它就属于 4yz。邮箱满属于典型的「用户清理后即可成功」情形,因而符合 4yz 的定义。若错误地返回 552 或 550,发送方按第 4.2.1 节「不应重复相同请求」的规定会立即产生永久退信,用户清空邮箱后也无法自动恢复。反过来,若整个存储系统真的耗尽(X.3.1),继续接收会导致更大范围的数据风险,此时用 452 拒收新连接是恰当的。
RFC 9208(IMAP QUOTA 扩展)第 5 节定义了四类资源:STORAGE(配额根所辖邮箱占用的物理空间估算,以 1024 个八位组为单位,可能包含元数据或压缩差异,不一定等于各邮件 RFC822.SIZE 之和)、MESSAGE(邮件数量)、MAILBOX(邮箱数量)、ANNOTATION-STORAGE(邮件注解的最大总大小,同样以 1024 个八位组为单位)。第 4.1 节定义三条命令:GETQUOTA(按配额根名查询用量与限额)、GETQUOTAROOT(按邮箱名查询其所属配额根列表及各根的用量与限额,且该邮箱不必真实存在)、SETQUOTA(修改某配额根的限额,未列出的旧限额将被丢弃)。能力声明上,符合本文档的服务器必须至少返回一个带 QUOTA=RES- 前缀的能力(如 QUOTA=RES-STORAGE);若实现了 SETQUOTA,则必须返回 QUOTASET 能力。
RFC 9208 第 4.3.1 节定义了 OVERQUOTA 响应码:当执行 APPEND、COPY 或 MOVE 会导致目标邮箱超出任一配额限制时,服务器应当在带标签的 NO 响应中返回该响应码(例如 A003 NO [OVERQUOTA] APPEND Failed);当邮箱因外部投递或其他连接上的操作而超出软配额时,服务器可以在已认证或已选中状态下以无标签 NO 响应返回(例如 * NO [OVERQUOTA] Soft quota has been exceeded),但在没有选中邮箱且没有添加邮件的命令时不得返回。这套机制的价值在于让客户端能明确区分「配额问题」与「其他失败」,从而给出正确的用户提示。
RFC 1939 第 8 节针对大规模多用户服务器给出的建议同样适用于配额设计:一是对每用户投递区实施存储配额之类的限制,并明确提示该选项的缺点——邮件累积可能导致用户无法接收新邮件,因此采用该选项的站点应当设法告知用户配额即将耗尽或已耗尽,例如向用户投递区插入一封提示邮件;二是制定并执行站点级的邮件保留策略。把「阈值告警 + 保留策略」和「超限回 4xx」配套起来,才能既保住存储又不丢邮件。
参考:https://www.rfc-editor.org/rfc/rfc5321.txt 、https://www.rfc-editor.org/rfc/rfc3463.txt 、https://www.rfc-editor.org/rfc/rfc9208.txt 与 https://www.rfc-editor.org/rfc/rfc1939.txt
