摘要
- RFC 5258 把“哪些名称进入结果”的 selection option 与“为结果补充哪些信息”的 return option 分开;只保存一棵渲染后的树,会丢掉每个节点出现的原因。
- 使用 RECURSIVEMATCH 时,父名称可以因为订阅后代而被返回,即便父名称自身未订阅,甚至带有
\NonExistent;CHILDINFO 才是这条因果关系的凭据。
展开箭头不是对象登记证
邮箱客户端里的层级树极具说服力。缩进暗示包含,箭头暗示孩子,屏幕上的一行看上去就像一个可以选择、同步和移动的对象。但 RFC 5258 给 LIST-EXTENDED 的定义更克制:服务器是在回答一个带模式、筛选项和返回项的问题。
同一份服务器状态,面对不同问题可以产生不同而且都正确的树。一个请求只选择订阅名称;另一个先选择所有本地邮箱,再标出哪些已订阅;第三个把远程邮箱也纳入范围;第四个为了让用户看懂层级,返回一个本身不符合订阅条件的父名称。
因此,树的真实性有明确边界:它对某个服务器、认证主体、请求与处理时刻为真。它不自动成为永久目录,也不证明每一行都对应现存、可选、可读或已同步的邮箱。
如果审计只保存响应里的名称,就已经丢掉了决定名称含义的半份证据。最小记录还应包括能力集的代际、认证身份、reference name、原始模式、服务器形成的规范匹配模式、selection options、return options、命令标签、全部未标记响应以及处理时间。否则后来的人只能看到答案,却不知道服务器回答了什么问题。
筛选决定成员,返回项决定附带信息
RFC 5258 对两类 option 的区分看似语法,实质上是权力边界。selection option 决定哪些邮箱名称可以成为结果成员。通常,一个名称必须匹配至少一个规范 LIST 模式,并满足所有选择条件;RECURSIVEMATCH 是有明文特殊规则的例外。
return option 只决定为已经匹配的名称返回什么信息。它不能让服务器多报告名称。一个实现若把注释请求当成筛选条件,或者把筛选条件当成普通注释,就可能产生外观合理、问题却完全不同的答案。
SUBSCRIBED 的两种位置最能说明这条界线。作为 selection option,它要求服务器选择订阅名称,而不是选择所有现存邮箱。这个集合可能比现存邮箱少,也可能包含已经订阅但并不存在的名称。作为 return option,它只给基础 LIST 已经选中的每个名称添加准确的订阅状态,既不把结果限制为订阅项,也不能创造新的结果成员。
SUBSCRIBED selection 会隐含同名 return option,所以被选中的名称会带上 \Subscribed。但这种便利没有消灭两种含义。迁移或治理工具仍必须知道:订阅是某一行进入集合的原因,还是这行因别的条件进入集合后附带的一项状态。
这也是 LIST (SUBSCRIBED) 不能简单等同 LSUB 的原因。扩展 LIST 要求属性准确完整,并保持普通含义;LSUB 的部分属性承载旧的特殊语义。把两种响应都压成一个“已订阅文件夹列表”,恰好会抹去 RFC 5258 新机制想修正的歧义。
父名称可以没有通过订阅条件
设想只有 Foo/Baz 被订阅,Foo 没有订阅。若客户端用只显示一层的模式查询订阅名称,父项因未订阅而失败,子项又不在模式范围内,于是结果可能为空。用户却无法从空结果知道深处存在订阅项。
加入 RECURSIVEMATCH 后,服务器可以返回 Foo,并附上 CHILDINFO (SUBSCRIBED)。父名称仍须匹配请求的规范模式;导致它出现的后代却不必匹配该模式。这里的准确含义是:这个名称提供层级上下文,因为至少一个后代满足订阅条件。它并不表示父项自身订阅。
客户端如果丢掉 CHILDINFO,只剩一行 Foo,就很容易把因果上下文缓存成直接订阅。再把每个可见节点变成 SELECT 目标,说明性祖先就获得了服务器从未授予的对象权力。
规范还禁止 RECURSIVEMATCH 单独使用,也禁止它仅与 REMOTE 组合。递归匹配必须解释另一个选择条件如何在后代成立,否则服务器应返回 BAD。这条有效性规则说明,“递归”不是随意请求完整邮箱树的通配开关。
不存在的父节点也可以正确出现
IMAP 的层级名称不要求每一个文本祖先都是现存邮箱。服务器可以有 Customers/ABC,却没有名为 Customers 的邮箱。为了呈现后代所在的位置,RECURSIVEMATCH 仍可能需要返回那个祖先名称。
此时父行可以同时带 \NonExistent 和 CHILDINFO (SUBSCRIBED)。两项信息是相加而非互相否定:父名称不指向现存邮箱;它出现,是因为后代满足订阅选择。\NonExistent 还蕴含 \NoSelect。
同理,一个名称也可以同时 \Subscribed 和 \NonExistent。订阅是关联在名称上的状态,存在性是邮箱对象的状态。邮箱删除后,订阅记录可能留下。若系统把订阅直接解释为存在,就会删除清理陈旧状态所需的关键信号。
这与既有 RFC 2342 文章的边界相邻但不重合。NAMESPACE 说明个人、其他用户和共享名称如何组织,并不证明对象存在。RFC 5258 进一步提出运行时问题:即使执行了发现查询,一行也可能因后代而非自身被纳入。名称语法与查询因果必须分别留证。
CHILDINFO 说明原因,却不是孩子清单
CHILDINFO 记录使非匹配祖先进入响应的选择条件,并说明至少一个后代满足该条件。它不会给出那个后代的名字,不会冻结后代,也不保证下一次请求还能找到它。
RFC 5258 明确要求客户端接受后续找不到合格孩子的情况。LIST 响应发出后,到客户端继续访问之前,另一个参与者可能删除或重命名孩子,访问控制也可能改变。所以 CHILDINFO 是带时间边界的观察,不是永久外键。
它仍有重要价值。返回的条件可以区分因本次请求产生的响应与 unsolicited response,还可以区分多条流水线 LIST 命令分别造成的结果。当客户端连续发送多个问题时,命令标签并不足以为每条未标记 LIST 行提供业务含义;请求参数、接收顺序与 CHILDINFO 原因共同构成依赖记录。
服务器应在匹配孩子也同时返回时抑制冗余 CHILDINFO,但 SHOULD 不能成为客户端推断不存在的依据。客户端既要允许冗余原因而不重复计算,也不能在未授权返回 CHILDINFO 的响应里,把它的缺席解释为没有合格后代。
CHILDINFO 也不同于 \HasChildren。前者回答“为什么筛选让这行出现”,后者回答“在当前访问视图里,这个邮箱是否有孩子”。一个是查询因果,一个是层级导航元数据。
\HasNoChildren 只对当前主体成立
CHILDREN return option 要求服务器返回 \HasChildren 或 \HasNoChildren,让客户端无需先抓取整个巨大层级就能绘制折叠树。这项优化把服务器观察转换成用户熟悉的展开箭头。
但箭头也有作用域。若孩子确实存在,而当前认证用户一个也无权访问,服务器不应报告 \HasChildren;在某些实现里,计算所有访问关系可能并不高效。即使属性在处理时准确,用户点击时孩子也可能已经删除或变得不可访问。
\HasNoChildren 的含义是:对当前认证用户,没有可访问的子邮箱。它不是“任何主体都看不到孩子”,更不是“孩子永远不可能存在”。后者接近 \NoInferiors 的意义:当前不存在下级,而且未来也不能创建。把二者都永久缓存成 leaf=true,会把当前可见性误写成结构不可能性。
可靠缓存至少要把服务器、账户或认证主体、名称空间代际、邮箱名称、访问策略代际和观察时间纳入键。可靠界面把展开视为可能变化的发现动作,而不会因为某个主体曾收到 \HasNoChildren,便删除其他证据里的后代或宣布全局空树。
更多返回信息不会把投影升级成总账
REMOTE 是一个特殊 selection option:它把远程邮箱与本地邮箱一并纳入处理,因此扩大而非缩小候选集合,也没有对应的 return option。即便返回名称带有 \Remote,它也不证明远端此刻可达、SELECT 会成功或消息可读。
后续标准继续丰富 LIST 表面。LIST-STATUS 可以附带状态数据,SPECIAL-USE 可以附带用途属性,NOTIFY 和 CONTEXT 可以提供更新机制,ACL 则定义与名称出现分离的权利。信息更丰富、更新更及时,仍不等于脱离请求和认证主体的永恒库存。
IANA 能力与邮箱名称属性注册表保存共同词汇及规范引用。注册证明各方可以说同一种协议语言,不证明某个部署已启用扩展、正确计算所有属性、展示同样的远程范围或保持客户端缓存同步。
RFC 9051 延续现代 IMAP 语义,但取证问题仍然具体:究竟是哪条命令,在什么状态和身份下执行,每一行为何出现?“支持 IMAP4rev2”这样的宽泛字段回答不了这些问题。
在树驱动行动前保留因果
可辩护的发现记录不仅存名称。每次调用都应保存能力、服务器与会话身份、认证主体、reference name、原始与规范模式、selection options、return options、命令标签以及全部响应。每一行还应注明直接命中还是递归纳入、所有相加属性、CHILDINFO 条件和处理时间。
下游再把这份投影与独立证据连接:当前存在性、订阅所有者与代际、ACL、SELECT 或 EXAMINE 结果、STATUS 代际、同步状态、消息获取和最终渲染。任何一项都不能仅由缩进推出。
Lu Heng 关于现实层的纪律给出了管理规则。返回的父名称在一次查询结果层是真实的;匹配后代在某个时刻作为原因也是真实的;邮箱对象、订阅、访问权和屏幕节点则分别属于其他层。高效抽象只有在这些连接可逆时才值得信任。
领导风险始于便利的树被提升为迁移、保留、授权审查或删除的真源。原本只为解释后代而出现的节点会被当成邮箱处理,访问范围内的叶子会被宣告为全局空,陈旧订阅会被误认为现存对象。先保存问题与原因,再允许答案获得操作权力。
来源
- RFC 5258:IMAP4 LIST 命令扩展
- RFC Editor 的 RFC 5258 记录
- IETF Datatracker 的 RFC 5258 记录
- RFC 5258 勘误检索
- RFC 3501:IMAP4rev1
- RFC 2342:IMAP4 Namespace
- RFC 5255:IMAP 国际化
- RFC 4466:IMAP4 扩展 ABNF 汇编
- RFC 5256:IMAP SORT 与 THREAD
- RFC 5267:IMAP CONTEXT
- RFC 5465:IMAP NOTIFY
- RFC 5819:IMAP LIST-STATUS
- RFC 6154:IMAP SPECIAL-USE
- RFC 4314:IMAP 访问控制列表扩展
- RFC 9051:IMAP4rev2
- IANA IMAP 能力注册表
- IANA IMAP 邮箱名称属性注册表
- Lu Heng:运行代码优先
- Lu Heng:现实层
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
