跳到主要内容

5. 操作考虑事项

此处列出以下规则, 以确保所有 IMAP4rev2 实现能够正确互操作.

5.1 Mailbox 命名​

在 IMAP4rev2 中, mailbox 名称以 Net-Unicode [NET-UNICODE] 编码 (这不同于 IMAP4rev1). 客户端实现 MAY 尝试创建 Net-Unicode mailbox 名称, 并且 MUST 将 LIST 返回的任何 8-bit mailbox 名称解释为 [NET-UNICODE]. 服务器实现 MUST 禁止创建不符合 Net-Unicode 的 8-bit mailbox 名称. 但是, 服务器 MAY 接受非规范化的 UTF-8 mailbox 名称, 并在创建 mailbox 之前将其转换为 Unicode Normalization Form C (NFC) (按照 Net-Unicode 的要求). 选择接受这种非规范化 UTF-8 mailbox 名称的服务器, MUST 在所有具有 mailbox 名称参数的 IMAP 命令中接受这些名称. 特别是, SELECT <name> 必须打开与 CREATE <name> 成功创建的同一 mailbox, 即使 <name> 是非规范化的 UTF-8 mailbox 名称.

大小写不敏感的 mailbox 名称 INBOX 是一个保留的特殊名称, 表示 "此服务器上此用户的主 mailbox". (注意, 对于某些服务器上的某些用户, 此特殊名称可能不存在, 例如当用户无法访问个人 namespace 时.) 所有其他名称的解释取决于实现.

特别是, 本规范不对非 INBOX mailbox 名称的大小写敏感性作出规定. 一些服务器实现在 ASCII 范围内完全大小写敏感; 另一些服务器保留新创建名称的大小写, 但除此之外大小写不敏感; 还有一些服务器会将名称强制转换为特定大小写. 客户端实现必须能够与这些实现中的任一种交互.

创建新的 mailbox 名称时, 客户端需要考虑以下事项:

  1. 任何属于 atom-specials 的字符 (见第 9 节的 "Formal Syntax") 都会要求将 mailbox 名称表示为 quoted string 或 literal.

  2. CTL 和其他非图形字符难以在用户界面中表示, 最好避免使用. 服务器 MAY 拒绝创建包含 Unicode CTL 字符的 mailbox 名称.

  3. 尽管 list-wildcard 字符 ("%" 和 "*") 在 mailbox 名称中是有效的, 但由于会与通配符解释冲突, 这类 mailbox 名称很难与 LIST 命令一起使用.

  4. 通常会保留一个字符 (由服务器实现决定) 用于分隔层级结构的各级.

  5. 两个字符 "#" 和 "&" 按约定具有含义, 除按该约定使用外应避免使用. 分别见第 5.1.2.1 节和附录 A.1.

5.1.1 Mailbox 层级命名​

如果希望导出分层 mailbox 名称, mailbox 名称 MUST 是从左到右的层级结构, 并使用单个 ASCII 字符分隔层级级别. 在单个名称内, 所有层级级别都使用同一个层级分隔符字符.

5.1.2 命名空间​

Personal Namespace: 服务器认为在特定连接上属于已认证用户个人作用域的 namespace. 通常, 只有已认证用户能够访问其 Personal Namespace 中的 mailbox. 这是 namespace 中属于该用户并分配给 mailbox 的部分. 如果某个用户存在 INBOX, 它 MUST 出现在该用户的 Personal Namespace 中. 在典型情况下, 一台服务器上每个用户 SHOULD 只有一个 Personal Namespace.

Other Users' Namespace: 由其他用户的 Personal Namespace 中的 mailbox 组成的 namespace. 要访问 Other Users' Namespace 中的 mailbox, 当前已认证用户 MUST 被显式授予访问权限. 例如, 管理者通常会向其行政支持人员授予访问其 mailbox 的权限. 在典型情况下, 一台服务器上每个用户 SHOULD 只有一个 Other Users' Namespace.

Shared Namespace: 由打算在用户之间共享且不存在于某个用户 Personal Namespace 内的 mailbox 组成的 namespace.

服务器使用的 namespace MAY 因用户而异.

5.1.2.1 历史 mailbox namespace 命名约定​

按照约定, 任何以 "#" 开头的 mailbox 名称的第一个层级元素, 标识该名称其余部分的 "namespace". 这使得不同类型的 mailbox 存储之间可以消除歧义, 其中每种存储都有自己的 namespace.

例如, 提供 USENET 新闻组访问的实现 MAY 使用 "#news" namespace, 将 USENET 新闻组 namespace 与其他 mailbox 的 namespace 分隔开. 因此, comp.mail.misc 新闻组的 mailbox 名称将是 "#news.comp.mail.misc", 而名称 "comp.mail.misc" 可以指代不同对象 (例如某个用户的私有 mailbox).

包含 "#" 字符的 namespace 对 IMAP URL [IMAP-URL] 不友好, 并要求在 URL 中将 "#" 字符表示为 %23. 因此, 服务器实现者 MAY 转而考虑使用不包含 "#" 字符的 namespace 前缀.

5.1.2.2 常见 namespace 模型​

此协议的先前版本没有定义默认服务器 namespace. 目前已经形成两种常见 namespace 模型:

"Personal Mailbox" 模型, 其中呈现的默认 namespace 仅由用户的个人 mailbox 组成. 要访问共享 mailbox, 用户必须使用转义机制到达另一个 namespace.

"Complete Hierarchy" 模型, 其中呈现的默认 namespace 包含用户的个人 mailbox 以及他们有权访问的任何其他 mailbox.

5.2 Mailbox 大小和消息状态更新​

服务器可以在任何时候发送客户端未请求的数据. 有时, 这种行为由本规范和/或扩展要求. 例如, 服务器以外的 agent 可能向 mailbox 添加消息 (例如新消息投递); 更改 mailbox 中消息的 flag (例如多个 agent 同时访问同一个 mailbox); 甚至从 mailbox 中移除消息. 如果在处理命令期间观察到 mailbox 大小变化, 服务器 MUST 自动发送 mailbox 大小更新. 服务器 SHOULD 自动发送消息 flag 更新, 而不要求客户端显式请求这类更新.

服务器向客户端通知消息移除时存在特殊规则, 用于防止同步错误; 更多细节见 EXPUNGE 响应的描述 (第 7.5.1 节). 特别是, 不允许发送会减少 mailbox 中消息数量的 EXISTS 响应; 只有 EXPUNGE 响应可以做到这一点.

无论客户端在记忆来自服务器的数据方面作出何种实现决定, 客户端实现 MUST 记住 mailbox 大小更新. 它 MUST NOT 假定初始 mailbox 选择之后的任何命令都会返回 mailbox 的大小.

5.3 无正在进行的命令时的响应​

服务器实现允许在没有命令正在进行时发送不带标签的响应 (EXPUNGE 除外). 发送此类响应的服务器实现 MUST 处理流量控制方面的考虑. 具体而言, 它们 MUST 要么 (1) 验证数据大小不超过底层传输的可用窗口大小, 要么 (2) 使用非阻塞写入.

5.4 自动注销计时器​

如果服务器具有适用于认证后会话的非活动自动注销计时器, 该计时器的持续时间 MUST 至少为 30 分钟. 在该间隔内收到来自客户端的任何命令都会重置自动注销计时器.

注意, 本规范对客户端成功认证之前使用的自动注销计时器没有任何限制. 特别是, 服务器可以使用较短的认证前计时器来保护自身免受 Denial-of-Service 攻击.

5.5 多个正在进行的命令 (命令流水线)​

客户端 MAY 在不等待某个命令的完成结果响应的情况下发送另一个命令, 但需遵守歧义规则 (见下文) 以及底层数据流上的流量控制约束. 类似地, 服务器 MAY 在将当前命令处理完成之前开始处理另一个命令, 但需遵守歧义规则. 但是, 任何命令继续请求响应和命令继续都 MUST 在发起任何后续命令之前完成协商.

例外情况是, 某个命令会影响其他命令的结果, 从而产生歧义. 如果服务器检测到可能的歧义, 它 MUST 按客户端给出的顺序将命令执行完成.

最明显的歧义示例是某个命令会影响另一个命令的结果. 一个例子是会导致设置 \Seen flag 的 FETCH, 以及 SEARCH UNSEEN 命令.

一种不明显的歧义出现在允许不带标签 EXPUNGE 响应的命令中 (FETCH, STORE 和 SEARCH 以外的命令), 因为不带标签 EXPUNGE 响应可能使后续命令中的序列号失效. 对 FETCH, STORE 或 SEARCH 命令而言这不是问题, 因为服务器被禁止在这些命令中任何一个正在进行时发送 EXPUNGE 响应. 因此, 如果客户端发送 FETCH, STORE 或 SEARCH 以外的任何命令, 它 MUST 在发送带有消息序列号的命令之前等待完成结果响应.

注意: 在 UID FETCH, UID STORE 和 UID SEARCH 正在进行时, 允许 EXPUNGE 响应. 如果客户端发送 UID 命令, 它 MUST 在发送使用消息序列号的命令之前等待完成结果响应 (这可能包括 UID SEARCH). UID SEARCH 参数中的任何消息序列号都与 UID SEARCH 返回的任何不带标签 EXPUNGE 响应产生效果之前的消息相关联.

例如, 以下非等待命令序列无效: