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 名称时, 客户端需要考虑以下事项:
-
任何属于 atom-specials 的字符 (见第 9 节的 "Formal Syntax") 都会要求将 mailbox 名称表示为 quoted string 或 literal.
-
CTL 和其他非图形字符难以在用户界面中表示, 最好避免使用. 服务器 MAY 拒绝创建包含 Unicode CTL 字符的 mailbox 名称.
-
尽管 list-wildcard 字符 ("%" 和 "*") 在 mailbox 名称中是有效的, 但由于会与通配符解释冲突, 这类 mailbox 名称很难与 LIST 命令一起使用.
-
通常会保留一个字符 (由服务器实现决定) 用于分隔层级结构的各级.
-
两个字符 "#" 和 "&" 按约定具有含义, 除按该约定使用外应避免使用. 分别见第 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 响应产生效果之前的消息相关联.
例如, 以下非等待命令序列无效: