摘要

  • 客户端明确启用 UIDONLY 后,RFC 9586 禁用消息序号,并让 UIDFETCH 与 VANISHED 以 UID 标识对象。它消除的是一张随时变动的对照表,不是一切邮箱状态的不确定性。
  • 可持久引用仍须同时包含邮箱名、UIDVALIDITY 与 UID。能力公告、连接启用、命令结束、缓存提交和应用对账是不同的回执。

一只装有八万封邮件的邮箱删掉了靠前的一封。其后的每个消息序号都随之移动,客户端若仍按位置识别邮件,就必须一边接收新变化,一边维护序号到 UID 的映射。UIDONLY 对准的正是这项负担:不再让相对位置进入消息操作。

但服务器在 CAPABILITY 中写出 UIDONLY,不代表某条连接已经使用它。客户端必须发送 ENABLE UIDONLY。启用后,普通 FETCH、STORE、SEARCH、COPY 和 MOVE 才会被禁止,误用时服务器返回 UIDREQUIRED;属性变化通过 UIDFETCH 表达,删除通过 VANISHED 表达。公告和生效之间存在一条可审计的边界。

这项简化有实际价值。消息序号只是当前排序中的位置,一次 EXPUNGE 就能让后来位置重新编号。舍弃这套命名空间,能降低延迟响应被贴到错误邮件上的风险,也能减少客户端维持双重标识的成本。

留下来的 UID 却不是全局名字。RFC 9051 将它限定在某个邮箱世代中;可靠引用是邮箱名、UIDVALIDITY 和 UID 的组合。如果服务器无法继续保留原有命名空间,就会改变 UIDVALIDITY,客户端必须撤销旧 UID 的当前权威。审计记录里只有一个裸 UID,证据并不完整。

UIDNEXT 也不是对下一个对象的承诺。它为以后分配的 UID 给出下界,不保证恰好存在那个编号。UID 可以留有空洞,消息可以被删除,标志等可变属性也会在身份不变时继续改变。标识稳定与状态已定是两件事。

UIDONLY 不改变 EXISTS 或 RECENT。它能和 CONDSTORE、QRESYNC 同时使用,MODSEQ 也能出现在 UIDFETCH 中,但规范没有要求 UIDONLY 自带这些同步能力。QRESYNC 中可选的消息序号匹配参数反而被禁止,因为它会把已舍弃的命名空间带回来。更干净的寻址不等于完整历史。

复制与移动同样暴露出证据边界。COPYUID 可以把源 UID、目标 UIDVALIDITY 和目标 UID 连起来,带标签的结果可以证明 IMAP 命令结束。它们不能证明索引器、归档、搜索页面或手机缓存已持久写入目标对象;下游系统仍要给出自己的回执。

被放弃的零值方案尤其值得记住。早期草案曾考虑保留普通 FETCH 外形,只把消息序号位置填成零。规范最终拒绝这种做法,因为把零当作有效位置的旧客户端可能损坏缓存。表面兼容会掩盖语义断裂,明确的新响应形态反而更安全。

运营证据因此应形成完整链条:服务器公告了能力;这条连接完成启用;邮箱以这个 UIDVALIDITY 被选择;这些 UID、修改状态、到达与消失被观察;带标签命令完成;客户端持久提交增量;消费应用完成自身对账。任何一个绿色状态都不应冒充整条链。

来源