非官方中文译本声明:本页为 IETF RFC 3501《INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1 (IMAP4rev1)》 的中文译本,由 ztpop.net 整理翻译,仅供学习参考。RFC 文档由 IETF 发布,受 BCP 78 与 IETF 信托法律条款约束;本译本保留原文编号与结构,权威性以英文原文为准。英文原文见 rfc-editor.org/rfc/rfc3501。
RFC 3501:Internet 消息访问协议(IMAP4rev1)
封面信息
本备忘录由网络工作组(Network Working Group)提交,作者为 M. Crispin(华盛顿大学)。它取代 RFC 2060,于 2003 年 3 月发布,类别为标准跟踪(Standards Track)。
本备忘录的状态
本文档为互联网团体规定了一种互联网标准跟踪协议,并征求讨论与改进建议。关于该协议的标准化状态与现状,请参考最新版的"Internet Official Protocol Standards"(STD 1)。本备忘录的分发不受限制。
版权声明
Copyright (C) The Internet Society (2003)。保留所有权利。
摘要
Internet 消息访问协议第 4 修订版 1(IMAP4rev1),允许客户端访问并操作服务器上的电子邮件消息。IMAP4rev1 对邮箱(远程消息文件夹)的操作,在功能上等价于对本地文件夹的操作。IMAP4rev1 还使离线客户端能够与服务器重新同步。
IMAP4rev1 包含用于创建、删除、重命名邮箱,检查新消息,永久删除消息,设置与清除标志,解析 RFC 2822 与 RFC 2045,搜索,以及有选择地获取消息属性、文本及其片段的操作。在 IMAP4rev1 中,消息通过编号来访问,这些编号可以是消息序列号,也可以是唯一标识符。
IMAP4rev1 支持单一服务器。RFC 2244 讨论了用于支持多个 IMAP4rev1 服务器的配置信息访问机制。
IMAP4rev1 并未规定投寄邮件的手段;该功能由邮件传输协议(如 RFC 2821)处理。
目录
- 摘要
- 本备忘录的状态
- 版权声明
- 1. 如何阅读本文档
- 2. 协议概述
- 2.1. 链路层
- 2.2. 命令与响应
- 2.2.1. 客户端协议发送方与服务器协议接收方
- 2.2.2. 服务器协议发送方与客户端协议接收方
- 2.3. 消息属性
- 2.3.1. 消息编号
- 2.3.1.1. 唯一标识符(UID)消息属性
- 2.3.1.2. 消息序列号消息属性
- 2.3.2. 标志消息属性
- 2.3.3. 内部日期消息属性
- 2.3.4. [RFC-2822] 大小消息属性
- 2.3.5. 信封结构消息属性
- 2.3.6. 主体结构消息属性
- 2.3.1. 消息编号
- 2.4. 消息文本
- 3. 状态与流程图
- 4. 数据格式
- 4.1. 原子(Atom)
- 4.2. 数字(Number)
- 4.3. 字符串(String)
- 4.3.1. 8 位与二进制字符串
- 4.4. 括号列表(Parenthesized List)
- 4.5. NIL
- 5. 运维考量
- 5.1. 邮箱命名
- 5.1.1. 邮箱层级命名
- 5.1.2. 邮箱命名空间命名约定
- 5.1.3. 邮箱国际化命名约定
- 5.2. 邮箱大小与消息状态更新
- 5.3. 当无命令执行时的响应
- 5.4. 自动登出计时器
- 5.5. 并发执行的多个命令
- 5.1. 邮箱命名
- 6. 客户端命令
- 6.1. 客户端命令 - 任意状态
- 6.1.1. CAPABILITY 命令
- 6.1.2. NOOP 命令
- 6.1.3. LOGOUT 命令
- 6.2. 客户端命令 - 未认证状态
- 6.2.1. STARTTLS 命令
- 6.2.2. AUTHENTICATE 命令
- 6.2.3. LOGIN 命令
- 6.3. 客户端命令 - 已认证状态
- 6.3.1. SELECT 命令
- 6.3.2. EXAMINE 命令
- 6.3.3. CREATE 命令
- 6.3.4. DELETE 命令
- 6.3.5. RENAME 命令
- 6.3.6. SUBSCRIBE 命令
- 6.3.7. UNSUBSCRIBE 命令
- 6.3.8. LIST 命令
- 6.3.9. LSUB 命令
- 6.3.10. STATUS 命令
- 6.3.11. APPEND 命令
- 6.4. 客户端命令 - 已选状态
- 6.5. 客户端命令 - 实验性/扩展
- 6.5.1. X<atom> 命令
- 6.1. 客户端命令 - 任意状态
- 7. 服务器响应
- 7.1. 服务器响应 - 状态响应
- 7.1.1. OK 响应
- 7.1.2. NO 响应
- 7.1.3. BAD 响应
- 7.1.4. PREAUTH 响应
- 7.1.5. BYE 响应
- 7.2. 服务器响应 - 服务器与邮箱状态
- 7.3. 服务器响应 - 邮箱大小
- 7.4. 服务器响应 - 消息状态
- 7.4.1. EXPUNGE 响应
- 7.4.2. FETCH 响应
- 7.5. 服务器响应 - 命令延续请求
- 7.1. 服务器响应 - 状态响应
- 8. IMAP4rev1 连接示例
- 9. 形式文法
- 10. 作者说明
- 11. 安全考量
- 11.1. STARTTLS 安全考量
- 11.2. 其他安全考量
- 12. IANA 考量
- 附录 A. 参考文献
- 附录 B. 相对 RFC 2060 的变更
- 附录 C. 关键词索引
- 作者地址
- 完整版权声明
1. 如何阅读本文档
1.1 本文档的组织
本文档从 IMAP4rev1 客户端或服务器实现者的视角撰写。除第 2 节的协议概述外,它并未针对试图理解协议运作方式的人进行优化。第 3 至 5 节提供了 IMAP4rev1 运行所处的一般背景与定义。
第 6、7、9 节分别描述了 IMAP 的命令、响应与语法。它们之间的关系使得几乎不可能单独理解其中任何一个。特别地,不要试图仅从命令节推断命令语法;而应参考"形式文法"一节。
1.2 本文档使用的约定
"约定(Conventions)"指基本原则或流程。本文档的约定在本节注明。
在示例中,"C:" 与 "S:" 分别表示客户端与服务器发出的行。
本文档中的关键词 "MUST(必须)"、"MUST NOT(不得)"、"REQUIRED(要求)"、"SHALL(应)"、"SHALL NOT(不应)"、"SHOULD(应该)"、"SHOULD NOT(不应该)"、"MAY(可以)" 和 "OPTIONAL(可选)" 应按照 [KEYWORDS] 中的描述进行解释。
单词 "can"(而非 "may")用于指代一种可能的情形或状况,以区别于协议的可选设施。
"User(用户)"指代人类用户,而 "client(客户端)"指代用户运行的软件。
"Connection(连接)"指代从建立网络连接开始,直到其终止为止的整个客户端/服务器交互序列。
"Session(会话)"指代从选择一个邮箱(SELECT 或 EXAMINE 命令)开始,直到选择结束(SELECT 或 EXAMINE 另一个邮箱、CLOSE 命令,或连接终止)为止的客户端/服务器交互序列。
除非另有说明,字符均为 7 位 US-ASCII。其他字符集通过 "CHARSET" 指示,如 [MIME-IMT] 所述并由 [CHARSET] 定义。CHARSET 除了定义字符集外,还具有重要的附加语义;详情请参阅这些文档。
IMAP 中存在若干协议约定,它们指规范中并非严格属于 IMAP 协议、但反映普遍接受实践的内容。实现者需要知晓这些约定,并避免与之冲突——无论是否实现了该约定。例如,"&" 不能用作层级分隔符,因为它与邮箱国际化命名约定冲突,且 "&" 在邮箱名中的其他用途也会受影响。
1.3 给实现者的特别说明
强烈建议 IMAP 协议实现者在阅读本文档的同时,一并阅读 IMAP 实现建议文档 [IMAP-IMPLEMENTATION],以帮助理解该协议的复杂性,以及如何最好地构建可互操作的产品。
IMAP4rev1 设计为从 [IMAP2] 与未公开的 IMAP2bis 协议向上兼容。IMAP4rev1 与 RFC 1730 中描述的 IMAP4 协议大体兼容;例外在于 RFC 1730 中新增的、后来被证明存在问题并已移除的某些设施。在 IMAP4rev1 的演进过程中,早期协议中的某些方面已经过时。IMAP4rev1 实现在与早期实现配合使用时可能遇到的过时命令、响应与数据格式,在 [IMAP-OBSOLETE] 中描述。
与 IMAP2bis(早期协议中最常见的变体)的其他兼容性议题,在 [IMAP-COMPAT] 中讨论。与 [IMAP2] 的罕见(且推定已灭绝)变体的兼容性完整讨论见 [IMAP-HISTORICAL];该文档主要具有历史价值。
IMAP 最初是为较早的 [RFC-822] 标准开发的,因此 IMAP 中的若干获取项在其名称中包含了 "RFC822"。除 RFC822.SIZE 外,都有更现代的替代项;例如,RFC822.HEADER 的现代版本是 BODY.PEEK[HEADER]。在所有情况下,"RFC822" 都应被解释为对更新的 [RFC-2822] 标准的引用。
2. 协议概述
2.1 链路层
IMAP4rev1 协议假设使用一个可靠的数据流,例如 TCP 所提供的那样。使用 TCP 时,IMAP4rev1 服务器监听 143 端口。
2.2 命令与响应
一次 IMAP4rev1 连接由建立客户端/服务器网络连接、服务器的初始问候,以及客户端/服务器交互组成。这些客户端/服务器交互由一条客户端命令、服务器数据与一条服务器完成结果响应构成。
客户端与服务器传输的所有交互都以行的形式出现,即以 CRLF 结尾的字符串。IMAP4rev1 客户端或服务器的协议接收方要么正在读取一行,要么正在读取一段已知计数、后随一行的八位组序列。
2.2.1 客户端协议发送方与服务器协议接收方
客户端命令启动一个操作。每条客户端命令都带有一个标识符前缀(通常是一个短字母数字字符串,例如 A0001、A0002 等),称为"标签(tag)"。客户端为每条命令生成一个不同的标签。
客户端必须严格遵循本规范概述的语法。发送缺少或多出空格或参数的命令是语法错误。
有两种情况,客户端发来的一行并不代表一条完整的命令。一种情况是,命令参数带八位组计数地加引号(参见"数据格式"下"字符串"中对 literal 的描述);另一种情况是,命令参数需要服务器反馈(参见 AUTHENTICATE 命令)。无论哪种情况,如果服务器已准备好接收八位组(如适用)以及命令的其余部分,它会发送一条命令延续请求响应。该响应以 "+" 令牌为前缀。
注意:反之,如果服务器检测到命令中的错误,它会发送一条带有与该命令匹配的标签的 BAD 完成响应(如下所述),以拒绝该命令并阻止客户端发送命令的其余部分。
服务器也可能发送针对其他命令的完成响应(若有多个命令在执行中),或无标签数据。无论哪种情况,命令延续请求仍处于挂起状态;客户端对该响应采取适当动作,并从服务器读取另一条响应。在所有情况下,客户端必须先发送一条完整命令(包括接收该命令的所有命令延续请求响应与命令延续部分),然后才能发起新命令。
IMAP4rev1 服务器的协议接收方从客户端读取一条命令行列,解析该命令及其参数,并传输服务器数据与服务器命令完成结果响应。
2.2.2 服务器协议发送方与客户端协议接收方
服务器传输给客户端的数据,以及不表示命令完成的那些状态响应,以 "*" 令牌为前缀,称为无标签响应(untagged responses)。
服务器数据可能因客户端命令而发送,也可能由服务器单方面发送。由特定命令产生的服务器数据与单方面发送的服务器数据之间,不存在语法差异。
服务器完成结果响应指示操作的成功或失败。它以启动该操作的客户端命令相同的标签标记。因此,若有多个命令在执行中,服务器完成响应中的标签即标识该响应对应的命令。共有三种可能的服务器完成响应:OK(表示成功)、NO(表示失败)或 BAD(表示协议错误,如无法识别的命令或命令语法错误)。
服务器应严格强制执行本规范概述的语法。任何带有协议语法错误的客户端命令,包括(但不限于)缺少或多出空格或参数,都应被拒绝,并向客户端给出 BAD 服务器完成响应。
IMAP4rev1 客户端的协议接收方从服务器读取一条响应行列。它随后依据响应的第一个令牌(可以是标签、"*" 或 "+")对该响应采取行动。
客户端必须随时准备接受任何服务器响应。这包括未经请求的服务器数据。服务器数据应被记录,以便客户端可以引用其记录的副本,而不是向服务器发送命令来请求该数据。对于某些服务器数据,数据必须被记录。
该主题在"服务器响应"一节中有更详细的讨论。
2.3 消息属性
除消息文本外,每条消息还关联若干属性。这些属性可以单独获取,也可以与其他属性或消息文本一并获取。
2.3.1 消息编号
在 IMAP4rev1 中,消息通过两种编号之一访问:唯一标识符或消息序列号。
2.3.1.1 唯一标识符(UID)消息属性
分配给每条消息的一个 32 位值,当它与唯一标识符有效性值(见下文)结合使用时,构成一个 64 位值,该值必须永远不指代邮箱中或任何后续同名邮箱中的其他任何消息。唯一标识符在邮箱中以严格递增的方式分配;每条消息加入邮箱时,都被赋予一个高于此前加入消息的 UID。与消息序列号不同,唯一标识符不一定是连续的。
消息的唯一标识符在会话期间不得改变,并且在会话之间也不应改变。会话间唯一标识符的任何改变,必须能够使用下文讨论的 UIDVALIDITY 机制检测到。持久的标识符是客户端从上一次会话与服务器重新同步其状态(例如,断开连接或离线访问客户端)所必需的;[IMAP-DISC] 对此有进一步讨论。
与每个邮箱关联的有两个有助于唯一标识符处理的值:下一个唯一标识符值与唯一标识符有效性值。
下一个唯一标识符值是将分配给邮箱中新消息的预测值。除非唯一标识符有效性也发生改变(见下文),否则下一个唯一标识符值必须具备以下两个特征。第一,下一个唯一标识符值不得改变,除非有新消息加入邮箱;第二,每当有新消息加入邮箱时,下一个唯一标识符值必须改变,即使那些新消息随后被清除(expunged)也是如此。
注意:下一个唯一标识符值旨在为客户端提供一种手段,以确定自其上一次检查该值以来,是否有任何消息投递到了邮箱。它并不意图提供任何关于某条消息将具有该唯一标识符的保证。客户端仅能在获取下一个唯一标识符值时假定:在该时刻之后到达的消息将具有大于或等于该值的 UID。
唯一标识符有效性值在选择邮箱时,于 OK 无标签响应中以 UIDVALIDITY 响应码发送。如果来自较早会话的唯一标识符未能在本会话中持久化,则唯一标识符有效性值必须大于较早会话中所使用的那个。
注意:理想情况下,唯一标识符应始终持久化。尽管本规范承认在某些服务器环境中无法持久化可能不可避免,但它强烈鼓励采用能够避免此问题的消息存储实现技术。例如:
- 唯一标识符在邮箱中必须始终严格递增。如果物理消息存储被非 IMAP 代理重新排序,这要求邮箱中的唯一标识符被重新生成,因为原有的唯一标识符由于重新排序而不再严格递增。
- 如果消息存储没有存储唯一标识符的机制,它必须在每个会话重新生成唯一标识符,且每个会话必须具有一个唯一的 UIDVALIDITY 值。
- 如果邮箱被删除,并在日后创建了一个同名的新邮箱,服务器必须要么跟踪来自该邮箱先前实例的唯一标识符,要么必须为该新实例分配一个新的 UIDVALIDITY 值。在这种情况下,一个好的 UIDVALIDITY 值是邮箱创建日期/时间的 32 位表示。使用诸如 1 这样的常量也是可以的,但仅当能保证唯一标识符永远不会被重用时才行——即使在邮箱被删除(或重命名)、并在未来某个时刻创建了同名新邮箱的情况下也是如此。
- 邮箱名、UIDVALIDITY 与 UID 的组合必须永远指代该服务器上的一条不可变消息。特别地,内部日期、[RFC-2822] 大小、信封、主体结构以及消息文本(RFC822、RFC822.HEADER、RFC822.TEXT,以及所有 BODY[...] 获取项)都必须永不改变。这不包括消息编号,也不包括可由 STORE 命令设置的属性(例如 FLAGS)。
2.3.1.2 消息序列号消息属性
从 1 到邮箱中消息数量的一个相对位置。该位置必须按唯一标识符升序排列。每条新消息加入时,被赋予一个比加入前邮箱中消息数量大 1 的消息序列号。
消息序列号可以在会话期间重新分配。例如,当一条消息被永久移除(清除)出邮箱时,所有后续消息的消息序列号都会递减。邮箱中的消息数量也随之递减。类似地,一条新消息可以被赋予一个曾经在清除前由其他某条消息持有的消息序列号。
除了通过邮箱中的相对位置访问消息外,消息序列号还可用于数学计算。例如,如果收到无标签的 "11 EXISTS",而此前收到无标签的 "8 EXISTS",则有三条新消息到达,其消息序列号为 9、10 和 11。另一例:若一个包含 523 条消息的邮箱中的第 287 条消息具有 UID 12345,则恰好有 286 条消息的 UID 更小,236 条消息的 UID 更大。
2.3.2 标志消息属性
与消息关联的一个包含零个或多个命名令牌的列表。添加该令牌即设置标志,移除该令牌即清除标志。IMAP4rev1 中有两类标志。任一类标志都可以是永久的或仅会话级的。
系统标志(system flag)是本规范中预定义的标志名。所有系统标志都以 "\" 开头。某些系统标志(\Deleted 与 \Seen)具有别处描述的特殊语义。当前定义的系统标志如下:
- \Seen:消息已被阅读。
- \Answered:消息已回复。
- \Flagged:消息被"标记"以便紧急/特殊关注。
- \Deleted:消息被"删除",等待后续 EXPUNGE 清除。
- \Draft:消息尚未完成撰写(标记为草稿)。
- \Recent:消息"最近"到达此邮箱。本会话是首个被通知该消息的会话;若会话为读写模式,后续会话将不会看到该消息设置了 \Recent。此标志不能被客户端改变。
- 如果无法确定本会话是否为首个被通知该消息的会话,则该消息应被视为最近的(recent)。
- 如果多个连接同时选择了同一邮箱,则其中哪个连接会看到设置了 \Recent 的新到达消息、哪个会看到未设置 \Recent 的消息,是未定义的。
关键字(keyword)由服务器实现定义。关键字不以 "\" 开头。服务器可以允许客户端在邮箱中定义新的关键字(详见 PERMANENTFLAGS 响应码的描述)。
标志可按每个标志为永久的或仅会话级的。永久标志是客户端可以永久添加或移除消息标志的那些标志;也就是说,并发及后续会话都会看到永久标志的任何改变。对会话标志的改变仅在该会话中有效。
注意:\Recent 系统标志是会话标志的一个特例。\Recent 不能用作 STORE 或 APPEND 命令的参数,因此完全无法被改变。
2.3.3 内部日期消息属性
消息在服务器上的内部日期与时间。这不是 [RFC-2822] 头中的日期与时间,而是反映消息被接收时的日期与时间。对于通过 [SMTP] 投递的消息,这应是 [SMTP] 所定义的最终投递的日期与时间。对于通过 IMAP4rev1 COPY 命令投递的消息,这应是源消息的内部日期与时间。对于通过 IMAP4rev1 APPEND 命令投递的消息,这应是 APPEND 命令描述中指定的日期与时间。所有其他情况由实现定义。
2.3.4 [RFC-2822] 大小消息属性
以 [RFC-2822] 格式表示的消息中的八位组数量。
2.3.5 信封结构消息属性
消息的 [RFC-2822] 头的已解析表示。注意,IMAP 信封结构与 [SMTP] 信封并不相同。
2.3.6 主体结构消息属性
消息的 [MIME-IMB] 主体结构信息的已解析表示。
2.4 消息文本
除能够获取消息的完整 [RFC-2822] 文本外,IMAP4rev1 还允许获取完整消息文本的部分内容。具体而言,可以获取 [RFC-2822] 消息头、[RFC-2822] 消息体、一个 [MIME-IMB] 主体部分,或一个 [MIME-IMB] 头。
3. 状态与流程图
一旦客户端与服务器之间的连接建立,一次 IMAP4rev1 连接就处于四种状态之一。初始状态在服务器问候中标识。大多数命令仅在特定状态下有效。客户端在连接处于不适当状态时尝试执行命令是协议错误,服务器将用 BAD 或 NO(取决于服务器实现)命令完成结果响应。
3.1 未认证状态
在未认证状态,客户端必须先提供认证凭据,大多数命令才会被允许。除非连接已被预认证,否则连接开始时即进入此状态。
3.2 已认证状态
在已认证状态,客户端已经过认证,并且必须先选择一个邮箱来访问,影响消息的命令才会被允许。当出现以下情况时进入此状态:预认证连接启动、提供了可接受的认证凭据、选择邮箱时出错,或成功执行了 CLOSE 命令。
3.3 已选状态
在已选状态,已选定一个邮箱以供访问。当邮箱被成功选中时进入此状态。
3.4 登出状态
在登出状态,连接正在终止。此状态可由客户端请求(通过 LOGOUT 命令)引起,也可由客户端或服务器的单方面动作引起。
若客户端请求登出状态,服务器必须在关闭连接之前,向 LOGOUT 命令发送一条无标签 BYE 响应与一条带标签的 OK 响应;而客户端必须在关闭连接之前,读取该 LOGOUT 命令的带标签 OK 响应。
服务器不得在未发送包含原因的无标签 BYE 响应的情况下单方面关闭连接。客户端不应单方面关闭连接,而应发出 LOGOUT 命令。如果服务器检测到客户端已单方面关闭连接,服务器可以省略无标签 BYE 响应,并直接关闭其连接。
以下是状态转换流程图(原图逐字保留):
+----------------------+
|connection established|
+----------------------+
||
\/
+--------------------------------------+
| server greeting |
+--------------------------------------+
|| (1) || (2) || (3)
\/ || ||
+-----------------+ || ||
|Not Authenticated| || ||
+-----------------+ || ||
|| (7) || (4) || ||
|| \/ \/ ||
|| +----------------+ ||
|| | Authenticated |<=++ ||
|| +----------------+ || ||
|| || (7) || (5) || (6) ||
|| || \/ || ||
|| || +--------+ || ||
|| || |Selected|==++ ||
|| || +--------+ ||
|| || || (7) ||
\/ \/ \/ \/
+--------------------------------------+
| Logout |
+--------------------------------------+
||
\/
+-------------------------------+
|both sides close the connection|
+-------------------------------+
(1) connection without pre-authentication (OK greeting)
(2) pre-authenticated connection (PREAUTH greeting)
(3) rejected connection (BYE greeting)
(4) successful LOGIN or AUTHENTICATE command
(5) successful SELECT or EXAMINE command
(6) CLOSE command, or failed SELECT or EXAMINE command
(7) LOGOUT command, server shutdown, or connection closed
4. 数据格式
IMAP4rev1 使用文本形式的命令与响应。IMAP4rev1 中的数据可以是以下几种形式之一:atom(原子)、number(数字)、string(字符串)、parenthesized list(括号列表),或 NIL。注意,某个特定的数据项可能采用多种形式;例如,定义为使用 "astring" 语法的数据项既可以是 atom,也可以是 string。
4.1 原子(Atom)
一个 atom 由一个或多个非特殊字符组成。
4.2 数字(Number)
一个数字由一个或多个数字字符组成,表示一个数值。
4.3 字符串(String)
一个字符串有两种形式之一:literal(字面量)或 quoted string(带引号字符串)。literal 形式是字符串的一般形式。quoted string 形式是一种替代方案,它以可用的字符受限为代价,避免了处理 literal 的开销。
literal 是一个由零个或多个八位组(包括 CR 与 LF)组成的序列,以前缀引号形式表示:一个开括号("{")、八位组数量、闭括号("})"以及 CRLF。对于从服务器传输到客户端的 literal,CRLF 之后紧跟着八位组数据。对于从客户端传输到服务器的 literal,客户端必须等待接收到一条命令延续请求(本文档后文描述)之后,才能发送八位组数据(以及命令的其余部分)。
quoted string 是一个由零个或多个 7 位字符(不包括 CR 与 LF)组成的序列,两端各有一个双引号("<">)字符。<">
空字符串表示为 ""(双引号之间包含零个字符的带引号字符串),或表示为 {0} 后随 CRLF(八位组计数为 0 的 literal)。
注意:即使八位组计数为 0,传输 literal 的客户端也必须等待接收命令延续请求。
4.3.1 8 位与二进制字符串
通过 [MIME-IMB] 内容传输编码,支持 8 位文本与二进制邮件。IMAP4rev1 实现可以在 literal 中传输 8 位或多八位组字符,但应仅在 [CHARSET] 已标识时才这样做。
尽管定义了 BINARY 主体编码,但未编码的二进制字符串是不允许的。"binary string(二进制字符串)"是任何包含 NUL 字符的字符串。实现必须将二进制数据编码为文本形式(如 BASE64)后再传输。包含过量 CTL 字符的字符串也可能被视为二进制。
4.4 括号列表(Parenthesized List)
数据结构表示为"括号列表";即以空格分隔、两端以括号包围的一串数据项。括号列表可以包含其他括号列表,使用多级括号来表示嵌套。
空列表表示为 () —— 一个不含成员的括号列表。
4.5 NIL
特殊形式 "NIL" 表示以字符串或括号列表形式表示的某个特定数据项的不存在,不同于空字符串 "" 或空括号列表 ()。
注意:NIL 从不用于任何采用 atom 形式的数据项。例如,名为 "NIL" 的邮箱就是一个名叫 NIL 的邮箱,而不是一个不存在的邮箱名。这是因为邮箱使用 "astring" 语法,它要么是 atom 要么是 string。反之,NIL 的 addr-name 是一个不存在的个人名称,因为 addr-name 使用 "nstring" 语法,它要么是 NIL 要么是 string,但绝不可能是 atom。
5. 运维考量
下述规则在此列出,以确保所有 IMAP4rev1 实现都能正确互操作。
5.1 邮箱命名
邮箱名为 7 位。客户端实现不得尝试创建 8 位邮箱名,并且应将 LIST 或 LSUB 返回的任何 8 位邮箱名解释为 UTF-8。服务器实现应禁止创建 8 位邮箱名,并且不应在 LIST 或 LSUB 中返回 8 位邮箱名。有关如何表示非 ASCII 邮箱名的更多信息,见第 5.1.3 节。
注意:8 位邮箱名在本协议的早期版本中未定义。某些站点使用本地 8 位字符集来表示非 ASCII 邮箱名。这种用法不可互操作,现已被正式弃用。
大小写不敏感的邮箱名 INBOX 是一个保留的特殊名称,意为"该用户在此服务器上的主邮箱"。所有其他名称的解释取决于实现。
特别地,本规范对非 INBOX 邮箱名的大小写敏感性不持立场。某些服务器实现是完全大小写敏感的;另一些保留新创建名称的大小写,但在其他情况下大小写不敏感;还有一些将名称强制为特定大小写。客户端实现必须与以上任何一种交互。如果某服务器实现将非 INBOX 邮箱名解释为大小写不敏感,它必须按照第 5.1.3 节所述,对使用国际化命名约定的名称作特殊处理。
创建新邮箱名时有一些客户端考量:
- 任何属于 atom-specials(见"形式文法")的字符,都会要求邮箱名表示为带引号字符串或 literal。
- CTL 及其他非图形字符难以在用户界面中表示,最好避免使用。
- 尽管列表通配符字符("%" 与 "*")在邮箱名中是有效的,但由于与通配符解释冲突,很难在 LIST 与 LSUB 命令中使用此类邮箱名。
- 通常,会保留一个字符(由服务器实现决定)来分隔层级。
- 两个字符 "#" 与 "&" 依约定具有特定含义,除按该约定使用外应避免。
5.1.1 邮箱层级命名
如果想要导出层级化的邮箱名,邮箱名必须采用自左向右的层级结构,使用单一字符来分隔层级。在同一名称的所有层级中使用相同的层级分隔符字符。
5.1.2 邮箱命名空间命名约定
依约定,任何以 "#" 开头的邮箱名的第一个层级元素,标识该名称剩余部分的"命名空间(namespace)"。这使得能够消除不同类型邮箱存储之间的歧义,每种存储都有自己的命名空间。
例如,提供对 USENET 新闻组访问的实现可以使用 "#news" 命名空间,将 USENET 新闻组命名空间与其他邮箱的命名空间区分开。因此,comp.mail.misc 新闻组将具有邮箱名 "#news.comp.mail.misc",而名称 "comp.mail.misc" 可以指代一个不同的对象(例如,用户的私有邮箱)。
5.1.3 邮箱国际化命名约定
依约定,IMAP4rev1 中的国际化邮箱名使用 [UTF-7] 中描述的 UTF-7 编码的修改版本来指定。修改版 UTF-7 也可能在实现了本协议早期版本的服务器中使用。
在修改版 UTF-7 中,可打印的 US-ASCII 字符("&" 除外)表示其自身;即八位组值为 0x20-0x25 与 0x27-0x7e 的字符。字符 "&"(0x26)由两个八位组序列 "&-" 表示。
所有其他字符(八位组值 0x00-0x1f 与 0x7f-0xff)以修改版 BASE64 表示,并相对 [UTF-7] 作了进一步修改:使用 "," 代替 "/"。修改版 BASE64 不得用于表示任何能够自行表示的打印型 US-ASCII 字符。
"&" 用于切换到修改版 BASE64,"-" 用于切回 US-ASCII。不存在从 BASE64 到 US-ASCII 的隐式切换,空切换(在 BASE64 中的 "-&",注意在 US-ASCII 中的 "&-" 表示 "&")是不允许的。然而,所有名称都以 US-ASCII 开始,并且必须以 US-ASCII 结束;也就是说,以非 ASCII 的 ISO-10646 字符结尾的名称必须以 "-" 结尾。
这些修改的目的是修正 UTF-7 的以下问题:
- UTF-7 使用 "+" 字符进行切换;这与邮箱名中(尤其是 USENET 新闻组名中)"+" 的常见使用冲突。
- UTF-7 的编码是 BASE64,它使用 "/" 字符;这与将 "/" 用作流行层级分隔符冲突。
- UTF-7 禁止未编码地使用 "\";这与将 "\" 用作流行层级分隔符冲突。
- UTF-7 禁止未编码地使用 "~";这与某些服务器将 "~" 用作主目录指示符冲突。
- UTF-7 允许用多种替代形式表示同一字符串;特别是,可打印的 US-ASCII 字符可以用编码形式表示。
尽管修改版 UTF-7 是一种约定,但它对服务器处理任何带有内嵌 "&" 字符的邮箱名确立了某些要求。特别地,服务器实现必须精确保留修改版 UTF-7 名称中修改版 BASE64 部分的精确形式,并将该文本视为大小写敏感——即使名称在其他情况下是大小写不敏感或大小写折叠的。
服务器实现应验证,用作 CREATE 参数的、带有内嵌 "&" 字符的任何邮箱名是否符合:正确的修改版 UTF-7 语法、没有多余切换,并且没有对能够自行表示的任何打印型 US-ASCII 字符进行修改版 BASE64 编码。然而,客户端实现不得依赖服务器这样做,并且除非符合修改版 UTF-7 语法,否则不应尝试创建带有内嵌 "&" 字符的邮箱名。
导出不遵循修改版 UTF-7 约定的邮件存储的服务器实现,必须将包含非 ASCII 字符或 "&" 字符的任何邮箱名转换为修改版 UTF-7。
例如,下面是一个混合了英文、中文与日文的邮箱名:
~peter/mail/&U,BTFw-/&ZeVnLIqe-
例如,字符串 "&Jjo!" 不是一个有效的邮箱名,因为它在 "!" 之前没有切换到 US-ASCII。正确形式是 "&Jjo-!"。字符串 "&U,BTFw-&ZeVnLIqe-" 是不允许的,因为它包含了多余切换。正确形式是 "&U,BTF2XlZyyKng-"。
5.2 邮箱大小与消息状态更新
服务器可以在任何时候发送客户端未请求的数据。有时,这种行为是必须的。例如,除服务器外的代理可能向邮箱添加消息(如新消息投递)、改变邮箱中消息的标志(如多个代理同时访问同一邮箱),甚至从邮箱中移除消息。如果在处理命令期间观察到邮箱大小改变,服务器必须自动发送邮箱大小更新。服务器应自动发送消息标志更新,无需客户端显式请求此类更新。
关于服务器向客户端通知消息移除,存在特殊规则以防止同步错误;详见 EXPUNGE 响应的描述。特别地,不允许发送会降低邮箱中消息数量的 EXISTS 响应;只有 EXPUNGE 响应能做到这一点。
无国产邮件系统户端在记住服务器数据方面作出何种实现决定,客户端实现都必须记录邮箱大小更新。它不得假设在初始邮箱选择之后的任何命令都会返回邮箱的大小。
5.3 当无命令执行时的响应
允许服务器实现在没有命令执行时发送无标签响应(EXPUNGE 除外)。发送此类响应的服务器实现必须处理流控考量。具体而言,它们必须要么 (1) 验证数据大小不超过底层传输的可用窗口大小,要么 (2) 使用非阻塞写入。
5.4 自动登出计时器
如果服务器具有非活跃自动登出计时器,该计时器的时长必须至少为 30 分钟。在该间隔期间收到客户端的任何命令,都应足以重置自动登出计时器。
5.5 并发执行的多个命令
客户端可以在不等待某条命令的完成结果响应的情况下发送另一条命令,但须遵守歧义规则(见下文)以及底层数据流上的流控约束。类似地,服务器可以在完成当前命令的处理之前开始处理另一条命令,但须遵守歧义规则。然而,任何命令延续请求响应与命令延续部分,必须在发起任何后续命令之前协商完成。
例外情况是:如果某条会影响其他命令结果的命令会导致歧义,则除外。如果会导致歧义,客户端不得在不等待的情况下发送多条命令。如果服务器检测到可能的歧义,它必须按客户端给出的顺序将命令执行至完成。
最明显的歧义例子是,某条命令会影响另一条命令的结果,例如,对某消息标志的 FETCH 与对同一消息标志的 STORE。
一种不明显的歧义出现在允许无标签 EXPUNGE 响应的命令上(除 FETCH、STORE 与 SEARCH 之外的命令),因为无标签 EXPUNGE 响应会使后续命令中的序列号失效。这对 FETCH、STORE 或 SEARCH 命令不是问题,因为在这些命令执行期间,服务器被禁止发送 EXPUNGE 响应。因此,如果客户端发送除 FETCH、STORE 或 SEARCH 之外的任何命令,它必须在发送带有消息序列号的命令之前,等待完成结果响应。
注意:UID FETCH、UID STORE 与 UID SEARCH 是与 FETCH、STORE、SEARCH 不同的命令。如果客户端发送一条 UID 命令,它必须在发送带有消息序列号的命令之前,等待完成结果响应。
例如,以下不等待的命令序列是无效的:
FETCH + NOOP + STORE
STORE + COPY + FETCH
COPY + COPY
CHECK + FETCH
以下是有效的不等待命令序列示例:
FETCH + STORE + SEARCH + CHECK
STORE + COPY + EXPUNGE
UID SEARCH + UID SEARCH 作为不等待命令序列可能有效也可能无效,取决于第二条 UID SEARCH 是否包含消息序列号。
6. 客户端命令
本节描述 IMAP4rev1 命令。命令按其被允许执行的状态来组织。允许多个状态下执行的命令,列在允许的最小状态中(例如,在已认证与已选状态下均有效的命令,列在已认证状态命令中)。
命令参数在下方命令描述中以 "Arguments:" 标识,按功能而非语法描述。命令参数的精确语法在"形式文法"一节描述。
某些命令会导致返回特定的服务器响应;这些在下方的命令描述中以 "Responses:" 标识。有关这些响应的信息,见"响应"一节中的响应描述,其精确语法见"形式文法"一节。任何命令都可能传输服务器数据。因此,不特别要求服务器数据的命令会指明"no specific responses for this command",而非 "none"。
命令描述中的 "Result:" 指该命令可能的带标签状态响应,以及这些状态响应的任何特殊解释。
连接的状态仅由被记录为会改变状态的成功命令改变。被拒绝的命令(BAD 响应)永远不会改变连接的状态或所选邮箱的状态。失败命令(NO 响应)一般也不会改变连接或所选邮箱的状态;例外是 SELECT 与 EXAMINE 命令。
6.1 客户端命令 - 任意状态
以下命令在任意状态下有效:CAPABILITY、NOOP 与 LOGOUT。
6.1.1 CAPABILITY 命令
Arguments: none
Responses: REQUIRED untagged response: CAPABILITY
Result: OK - capability completed
BAD - command unknown or arguments invalid
CAPABILITY 命令请求列出服务器支持的能力。服务器必须在(带标签的)OK 响应之前,发送一条单独的无标签 CAPABILITY 响应,其中 "IMAP4rev1" 作为所列能力之一。
以 "AUTH=" 开头的能力名,表示该服务器支持该特定的认证机制。所有此类名称按定义都是本规范的一部分。例如,实验性 "blurdybloop" 认证器的授权能力应为 "AUTH=XBLURDYBLOOP",而不是 "XAUTH=BLURDYBLOOP" 或 "XAUTH=XBLURDYBLOOP"。
其他能力名指对本规范的扩展、修订或修正。有关详情见 CAPABILITY 响应的文档。除本规范定义的 IMAP4rev1 基本集之外,任何能力在没有客户端显式调用该能力的动作之前都不会被启用。
客户端与服务器实现必须实现 STARTTLS、LOGINDISABLED 与 AUTH=PLAIN(在 [IMAP-TLS] 中描述)能力。重要信息见"安全考量"一节。
关于站点或实现特定能力的形式,见题为"Client Commands - Experimental/Expansion"的一节。
示例:
Example: C: abcd CAPABILITY
S: * CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI
LOGINDISABLED
S: abcd OK CAPABILITY completed
C: efgh STARTTLS
S: efgh OK STARTLS completed
<TLS negotiation, further commands are under [TLS] layer>
C: ijkl CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=GSSAPI AUTH=PLAIN
S: ijkl OK CAPABILITY completed
6.1.2 NOOP 命令
Arguments: none
Responses: no specific responses for this command (but see below)
Result: OK - noop completed
BAD - command unknown or arguments invalid
NOOP 命令总是成功。它不做任何事。
由于任何命令都可以无标签数据的形式返回状态更新,NOOP 命令可用作在空闲期间定期轮询新消息或消息状态更新的手段(这是这样做的首选方法)。NOOP 命令也可用于重置服务器上的任何非活跃自动登出计时器。
示例:
Example: C: a002 NOOP
S: a002 OK NOOP completed
. . .
C: a047 NOOP
S: * 22 EXPUNGE
S: * 23 EXISTS
S: * 3 RECENT
S: * 14 FETCH (FLAGS (\Seen \Deleted))
S: a047 OK NOOP completed
6.1.3 LOGOUT 命令
Arguments: none
Responses: REQUIRED untagged response: BYE
Result: OK - logout completed
BAD - command unknown or arguments invalid
LOGOUT 命令告知服务器客户端已结束使用该连接。服务器必须在(带标签的)OK 响应之前发送一条 BYE 无标签响应,然后关闭网络连接。
示例:
Example: C: A023 LOGOUT
S: * BYE IMAP4rev1 Server logging out
S: A023 OK LOGOUT completed
(Server and client then close the connection)
6.2 客户端命令 - 未认证状态
在未认证状态,AUTHENTICATE 或 LOGIN 命令建立认证并进入已认证状态。AUTHENTICATE 命令为多种认证技术、隐私保护与完整性检查提供了通用机制;而 LOGIN 命令使用传统的用户名与明文口令对,没有建立隐私保护或完整性检查的手段。
STARTTLS 命令是建立会话隐私保护与完整性检查的另一种形式,但它不建立认证,也不进入已认证状态。
服务器实现可以允许在未建立认证的情况下访问某些邮箱。这可以通过 [ANONYMOUS] 中描述的 [SASL] 匿名认证器来实现。一种较旧的约定是使用用户标识 "anonymous" 的 LOGIN 命令;此时需要口令,尽管服务器可以选择接受任何口令。施加于匿名用户的限制取决于实现。
一旦完成认证(包括作为匿名),就不可能重新进入未认证状态。
除通用命令(CAPABILITY、NOOP 与 LOGOUT)外,以下命令在未认证状态下有效:STARTTLS、AUTHENTICATE 与 LOGIN。关于这些命令的重要信息,见"安全考量"一节。
6.2.1 STARTTLS 命令
Arguments: none
Responses: no specific response for this command
Result: OK - starttls completed, begin TLS negotiation
BAD - command unknown or arguments invalid
在来自服务器的带标签 OK 响应末尾的 CRLF 之后,立即开始 [TLS] 协商。一旦客户端发出 STARTTLS 命令,在看到服务器响应且 [TLS] 协商完成之前,它不得发出进一步命令。
即使客户端凭据在 [TLS] 协商期间提供,服务器仍保持非认证状态。这并不排除诸如 EXTERNAL(定义于 [SASL])之类的认证机制使用由 [TLS] 协商确定的客户端身份。
一旦启动了 [TLS],客户端必须丢弃关于服务器能力的缓存信息,并应重新发出 CAPABILITY 命令。这对于防范在 STARTTLS 之前篡改能力列表的中间人攻击是必要的。服务器可以在 STARTTLS 之后通告不同的能力。
示例:
Example: C: a001 CAPABILITY
S: * CAPABILITY IMAP4rev1 STARTTLS LOGINDISABLED
S: a001 OK CAPABILITY completed
C: a002 STARTTLS
S: a002 OK Begin TLS negotiation now
<TLS negotiation, further commands are under [TLS] layer>
C: a003 CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=PLAIN
S: a003 OK CAPABILITY completed
C: a004 LOGIN joe password
S: a004 OK LOGIN completed
6.2.2 AUTHENTICATE 命令
Arguments: authentication mechanism name
Responses: continuation data can be requested
Result: OK - authenticate completed, now in authenticated state
NO - authenticate failure: unsupported authentication
mechanism, credentials rejected
BAD - command unknown or arguments invalid,
authentication exchange cancelled
AUTHENTICATE 命令向服务器指示一种 [SASL] 认证机制。如果服务器支持所请求的认证机制,它会执行一个认证协议交换来认证并识别客户端。它也可以为后续的协议交互协商一个可选的(OPTIONAL)安全层。如果不支持所请求的认证机制,服务器应通过发送一条带标签的 NO 响应来拒绝 AUTHENTICATE 命令。
AUTHENTICATE 命令不支持 [SASL] 的可选 "initial response" 特性。[SASL] 的第 5.1 节规定了如何处理使用初始响应的认证机制。
本协议对 [SASL] 的配置文件所指定的服务名是 "imap"。
认证协议交换由一系列特定于该认证机制的服务器质询与客户端响应组成。服务器质询由一个以 "+" 令牌开头、后随 BASE64 编码字符串的命令延续请求响应构成。客户端响应由一行包含 BASE64 编码字符串的内容构成。如果客户端希望取消一次认证交换,它发出一行仅含单个 "*" 的内容。如果服务器收到这样的响应,它必须通过发送一条带标签的 BAD 响应来拒绝 AUTHENTICATE 命令。
如果通过 [SASL] 认证交换协商了一个安全层,它将在客户端结束认证交换的 CRLF 之后、以及服务器带标签 OK 响应的 CRLF 之后立即生效。
虽然客户端与服务器实现必须实现 AUTHENTICATE 命令本身,但不要求实现除 [IMAP-TLS] 中描述的 PLAIN 机制之外的任何认证机制。此外,也不要求认证机制支持任何安全层。
注意:服务器实现必须实现一种配置,在该配置中,除非已协商了 STARTTLS 命令,或已提供某种其他保护会话免遭口令嗅探的机制,否则它不允许任何明文口令机制。服务器站点不应使用任何在没有此类防口令嗅探保护机制的情况下允许明文口令机制的配置。客户端与服务器实现应实现其他不使用明文口令的 [SASL] 机制,例如 [SASL] 中描述的 GSSAPI 机制和/或 [DIGEST-MD5] 机制。
服务器与客户端可以支持多种认证机制。服务器应在对 CAPABILITY 命令的响应中列出其支持的认证机制,以便客户端知道应使用哪些认证机制。
服务器可以在成功的 AUTHENTICATE 命令的带标签 OK 响应中包含一个 CAPABILITY 响应码,以自动发送能力。如果客户端识别这些自动能力,则无需发送单独的 CAPABILITY 命令。这只应在 AUTHENTICATE 命令未协商安全层时才执行,因为作为 AUTHENTICATE 命令一部分的带标签 OK 响应不受加密/完整性检查保护。[SASL] 要求客户端在这种情况下重新发出 CAPABILITY 命令。
如果 AUTHENTICATE 命令以 NO 响应失败,客户端可以通过发出另一条 AUTHENTICATE 命令来尝试另一种认证机制。它也可以尝试使用 LOGIN 命令进行认证(详见第 6.2.3 节)。换言之,客户端可以按偏好递减的顺序请求认证类型,以 LOGIN 命令作为最后手段。
在认证交换期间从客户端传递到服务器的授权身份(authorization identity),由服务器解释为客户端正在请求其特权的用户名。
示例:
Example: S: * OK IMAP4rev1 Server
C: A001 AUTHENTICATE GSSAPI
S: +
C: YIIB+wYJKoZIhvcSAQICAQBuggHqMIIB5qADAgEFoQMCAQ6iBw
MFACAAAACjggEmYYIBIjCCAR6gAwIBBaESGxB1Lndhc2hpbmd0
b24uZWR1oi0wK6ADAgEDoSQwIhsEaW1hcBsac2hpdmFtcy5jYW
Lud2FzaGluZ3Rvbi5lZHWjgdMwgdCgAwIBAaEDAgEDooHDBIHA
cS1GSa5b+fXnPZNmXB9SjL8Ollj2SKyb+3S0iXMljen/jNkpJX
AleKTz6BQPzj8duz8EtoOuNfKgweViyn/9B9bccy1uuAE2HI0y
C/PHXNNU9ZrBziJ8Lm0tTNc98kUpjXnHZhsMcz5Mx2GR6dGknb
I0iaGcRerMUsWOuBmKKKRmVMMdR9T3EZdpqsBd7jZCNMWotjhi
vd5zovQlFqQ2Wjc2+y46vKP/iXxWIuQJuDiisyXF0Y8+5GTpAL
pHDc1/pIGmMIGjoAMCAQGigZsEgZg2on5mSuxoDHEA1w9bcW9n
FdFxDKpdrQhVGVRDIzcCMCTzvUboqb5KjY1NJKJsfjRQiBYBdE
NKfzK+g5DlV8nrw81uOcP8NOQCLR5XkoMHC0Dr/80ziQzbNqhx
O6652Npft0LQwJvenwDI13YxpwOdMXzkWZN/XrEqOWp6GCgXTB
vCyLWLlWnbaUkZdEYbKHBPjd8t/1x5Yg==
S: + YGgGCSqGSIb3EgECAgIAb1kwV6ADAgEFoQMCAQ+iSzBJoAMC
AQGiQgRAtHTEuOP2BXb9sBYFR4SJlDZxmg39IxmRBOhXRKdDA0
uHTCOT9Bq3OsUTXUlk0CsFLoa8j+gvGDlgHuqzWHPSQg==
C:
S: + YDMGCSqGSIb3EgECAgIBAAD/////6jcyG4GE3KkTzBeBiVHe
ceP2CWY0SR0fAQAgAAQEBAQ=
C: YDMGCSqGSIb3EgECAgIBAAD/////3LQBHXTpFfZgrejpLlLImP
wkhbfa2QteAQAgAG1yYwE=
S: A001 OK GSSAPI authentication successful
注意:服务器质询与客户端响应中的换行是为了编辑清晰,真实的认证器中并不包含。
6.2.3 LOGIN 命令
Arguments: user name
password
Responses: no specific responses for this command
Result: OK - login completed, now in authenticated state
NO - login failure: user name or password rejected
BAD - command unknown or arguments invalid
LOGIN 命令向服务器标识客户端,并携带认证该用户的明文口令。
服务器可以在成功的 LOGIN 命令的带标签 OK 响应中包含一个 CAPABILITY 响应码,以自动发送能力。如果客户端识别这些自动能力,则无需发送单独的 CAPABILITY 命令。
示例:
Example: C: a001 LOGIN SMITH SESAME
S: a001 OK LOGIN completed
注意:在不安全的网络(如 Internet)上使用 LOGIN 命令是一种安全风险,因为监视网络流量的任何人都可以获取明文口令。LOGIN 命令不应被使用,除非作为最后手段,并且建议客户端实现具备禁用任何自动使用 LOGIN 命令的手段。
除非已协商 STARTTLS 命令,或已提供某种其他保护会话免遭口令嗅探的机制,否则服务器实现必须实现一种配置,在该配置中通告 LOGINDISABLED 能力,并且不允许 LOGIN 命令。服务器站点不应使用任何在没有此类防口令嗅探保护机制的情况下允许 LOGIN 命令的配置。如果通告了 LOGINDISABLED 能力,客户端实现不得发送 LOGIN 命令。
6.3 客户端命令 - 已认证状态
在已认证状态,允许将邮箱作为原子实体来操作的命令。这些命令中,SELECT 与 EXAMINE 命令将选择一个邮箱以供访问,并进入已选状态。
除通用命令(CAPABILITY、NOOP 与 LOGOUT)外,以下命令在已认证状态下有效:SELECT、EXAMINE、CREATE、DELETE、RENAME、SUBSCRIBE、UNSUBSCRIBE、LIST、LSUB、STATUS 与 APPEND。
6.3.1 SELECT 命令
Arguments: mailbox name
Responses: REQUIRED untagged responses: FLAGS, EXISTS, RECENT
REQUIRED OK untagged responses: UNSEEN, PERMANENTFLAGS,
UIDNEXT, UIDVALIDITY
Result: OK - select completed, now in selected state
NO - select failure, now in authenticated state: no
such mailbox, can't access mailbox
BAD - command unknown or arguments invalid
SELECT 命令选择一个邮箱,以便可以访问其中的消息。在向客户端返回 OK 之前,服务器必须向客户端发送以下无标签数据。注意,本协议的早期版本只要求 FLAGS、EXISTS 与 RECENT 无标签数据;因此,客户端实现应针对缺失数据实现默认行为,如各条目所讨论的那样。
- FLAGS:邮箱中已定义的标志。详见 FLAGS 响应的描述。
- <n> EXISTS:邮箱中的消息数量。详见 EXISTS 响应的描述。
- <n> RECENT:设置了 \Recent 标志的消息数量。详见 RECENT 响应的描述。
- OK [UNSEEN <n>]:邮箱中第一条未读消息的消息序列号。如果缺失,客户端不能对邮箱中第一条未读消息作任何假设,若想找到它需发出 SEARCH 命令。
- OK [PERMANENTFLAGS (<list of flags>)]:客户端可以永久改变的消息标志列表。如果缺失,客户端应假定所有标志都可以被永久改变。
- OK [UIDNEXT <n>]:下一个唯一标识符值。更多信息见第 2.3.1.1 节。如果缺失,客户端不能对下一个唯一标识符值作任何假设。
- OK [UIDVALIDITY <n>]:唯一标识符有效性值。更多信息见第 2.3.1.1 节。如果缺失,服务器不支持唯一标识符。
在一个连接中一次只能选择一个邮箱;同时对多个邮箱的访问需要多个连接。SELECT 命令在尝试新选择之前,会自动取消选择任何当前已选的邮箱。因此,如果某个邮箱已被选中,而随后尝试的 SELECT 命令失败,则没有任何邮箱被选中。
如果允许客户端修改该邮箱,服务器应在带标签 OK 响应的文本前加上 "[READ-WRITE]" 响应码。
如果不允许客户端修改该邮箱,但允许读访问,则该邮箱被选为只读,且服务器必须在 SELECT 的带标签 OK 响应文本前加上 "[READ-ONLY]" 响应码。通过 SELECT 的只读访问不同于 EXAMINE 命令,在于某些只读邮箱可以允许基于每用户(相对于全局)改变永久状态。服务器端的 .newsrc 文件中被标记的 Netnews 消息就是此类可随只读邮箱修改的每用户永久状态的一个例子。
示例:
Example: C: A142 SELECT INBOX
S: * 172 EXISTS
S: * 1 RECENT
S: * OK [UNSEEN 12] Message 12 is first unseen
S: * OK [UIDVALIDITY 3857529045] UIDs valid
S: * OK [UIDNEXT 4392] Predicted next UID
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited
S: A142 OK [READ-WRITE] SELECT completed
6.3.2 EXAMINE 命令
Arguments: mailbox name
Responses: REQUIRED untagged responses: FLAGS, EXISTS, RECENT
REQUIRED OK untagged responses: UNSEEN, PERMANENTFLAGS,
UIDNEXT, UIDVALIDITY
Result: OK - examine completed, now in selected state
NO - examine failure, now in authenticated state: no
such mailbox, can't access mailbox
BAD - command unknown or arguments invalid
EXAMINE 命令与 SELECT 完全相同并返回相同的输出;然而,所选邮箱被标识为只读。不允许改变邮箱的永久状态,包括每用户状态;特别地,EXAMINE 不得导致消息丢失 \Recent 标志。
EXAMINE 命令的带标签 OK 响应文本必须以 "[READ-ONLY]" 响应码开头。
示例:
Example: C: A932 EXAMINE blurdybloop
S: * 17 EXISTS
S: * 2 RECENT
S: * OK [UNSEEN 8] Message 8 is first unseen
S: * OK [UIDVALIDITY 3857529045] UIDs valid
S: * OK [UIDNEXT 4392] Predicted next UID
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S: * OK [PERMANENTFLAGS ()] No permanent flags permitted
S: A932 OK [READ-ONLY] EXAMINE completed
6.3.3 CREATE 命令
Arguments: mailbox name
Responses: no specific responses for this command
Result: OK - create completed
NO - create failure: can't create mailbox with that name
BAD - command unknown or arguments invalid
CREATE 命令以给定名称创建一个邮箱。仅当具有该名称的新邮箱已被创建时,才返回 OK 响应。尝试创建 INBOX 或名称指向已存在邮箱的邮箱是错误。创建中的任何错误都将返回带标签的 NO 响应。
如果邮箱名以服务器的层级分隔符字符(由 LIST 命令从服务器返回)为后缀,这表示客户端打算在该名称下于层级中创建邮箱名。不要求此声明的服务器实现必须忽略该声明。无论如何,所创建的名称不带尾部层级分隔符。
如果服务器的层级分隔符字符出现在名称的其他位置,服务器应创建 CREATE 命令成功完成所需的任何上级层级名。换言之,在 "/" 为层级分隔符字符的服务器上,尝试创建 "foo/bar/zap" 时,如果 foo/ 与 foo/bar/ 尚不存在,则应创建它们。
如果创建的新邮箱与某个被删除邮箱同名,其唯一标识符必须大于前一实例中使用的任何唯一标识符,除非新实例具有不同的唯一标识符有效性值。详见 UID 命令的描述。
示例:
Example: C: A003 CREATE owatagusiam/
S: A003 OK CREATE completed
C: A004 CREATE owatagusiam/blurdybloop
S: A004 OK CREATE completed
注意:此示例的解释取决于 LIST 是否返回 "/" 作为层级分隔符。如果 "/" 是层级分隔符,则创建一个名为 "owatagusiam"、成员为 "blurdybloop" 的新层级。否则,会创建两个同一层级级别的邮箱。
6.3.4 DELETE 命令
Arguments: mailbox name
Responses: no specific responses for this command
Result: OK - delete completed
NO - delete failure: can't delete mailbox with that name
BAD - command unknown or arguments invalid
DELETE 命令永久移除具有给定名称的邮箱。仅当该邮箱已被删除时才返回带标签的 OK 响应。尝试删除 INBOX 或不存在的邮箱名是错误。
DELETE 命令不得移除下级层级名。例如,如果邮箱 "foo" 有一个下级 "foo.bar"(假设 "." 是层级分隔符字符),移除 "foo" 不得移除 "foo.bar"。尝试删除一个具有下级层级名、且同时具有 \Noselect 邮箱名属性的名称是错误的(详见 LIST 响应的描述)。
允许删除一个具有下级层级名、但不具有 \Noselect 邮箱名属性的名称。这种情况下,该邮箱中的所有消息都被移除,且该名称将获得 \Noselect 邮箱名属性。
被删除邮箱的最高已用唯一标识符的值必须被保留,以便用相同名称创建的新邮箱不会重用前一实例的标识符,除非新实例具有不同的唯一标识符有效性值。详见 UID 命令的描述。
示例:
Examples: C: A682 LIST "" *
S: * LIST () "/" blurdybloop
S: * LIST (\Noselect) "/" foo
S: * LIST () "/" foo/bar
S: A682 OK LIST completed
C: A683 DELETE blurdybloop
S: A683 OK DELETE completed
C: A684 DELETE foo
S: A684 NO Name "foo" has inferior hierarchical names
C: A685 DELETE foo/bar
S: A685 OK DELETE Completed
C: A686 LIST "" *
S: * LIST (\Noselect) "/" foo
S: A686 OK LIST completed
C: A687 DELETE foo
S: A687 OK DELETE Completed
C: A82 LIST "" *
S: * LIST () "." blurdybloop
S: * LIST () "." foo
S: * LIST () "." foo.bar
S: A82 OK LIST completed
C: A83 DELETE blurdybloop
S: A83 OK DELETE completed
C: A84 DELETE foo
S: A84 OK DELETE Completed
C: A85 LIST "" *
S: * LIST () "." foo.bar
S: A85 OK LIST completed
C: A86 LIST "" %
S: * LIST (\Noselect) "." foo
S: A86 OK LIST completed
6.3.5 RENAME 命令
Arguments: existing mailbox name
new mailbox name
Responses: no specific responses for this command
Result: OK - rename completed
NO - rename failure: can't rename mailbox with that name,
can't rename to mailbox with that name
BAD - command unknown or arguments invalid
RENAME 命令改变一个邮箱的名称。仅当该邮箱已被重命名时才返回带标签的 OK 响应。尝试从不存在的邮箱名重命名,或重命名到已存在的邮箱名,是错误。重命名中的任何错误都将返回带标签的 NO 响应。
如果该名称具有下级层级名,则下级层级名也必须被重命名。例如,将 "foo" 重命名为 "zap" 会把 "foo/bar"(假设 "/" 是层级分隔符字符)重命名为 "zap/bar"。
如果服务器的层级分隔符字符出现在名称中,服务器应创建 RENAME 命令成功完成所需的任何上级层级名。换言之,在 "/" 为层级分隔符字符的服务器上,尝试将 "foo/bar/zap" 重命名为 baz/rag/zowie 时,如果 baz/ 与 baz/rag/ 尚不存在,则应创建它们。
旧邮箱名的最高已用唯一标识符的值必须被保留,以便用相同名称创建的新邮箱不会重用前一实例的标识符,除非新实例具有不同的唯一标识符有效性值。详见 UID 命令的描述。
允许重命名 INBOX,并且具有特殊行为。它将 INBOX 中的所有消息移动到给定名称的新邮箱中,使 INBOX 留空。如果服务器实现对 INBOX 的下级层级名提供支持,这些不受 INBOX 重命名的影响。
示例:
Examples: C: A682 LIST "" *
S: * LIST () "/" blurdybloop
S: * LIST (\Noselect) "/" foo
S: * LIST () "/" foo/bar
S: A682 OK LIST completed
C: A683 RENAME blurdybloop sarasoop
S: A683 OK RENAME completed
C: A684 RENAME foo zowie
S: A684 OK RENAME Completed
C: A685 LIST "" *
S: * LIST () "/" sarasoop
S: * LIST (\Noselect) "/" zowie
S: * LIST () "/" zowie/bar
S: A685 OK LIST completed
C: Z432 LIST "" *
S: * LIST () "." INBOX
S: * LIST () "." INBOX.bar
S: Z432 OK LIST completed
C: Z433 RENAME INBOX old-mail
S: Z433 OK RENAME completed
C: Z434 LIST "" *
S: * LIST () "." INBOX
S: * LIST () "." INBOX.bar
S: * LIST () "." old-mail
S: Z434 OK LIST completed
6.3.6 SUBSCRIBE 命令
Arguments: mailbox
Responses: no specific responses for this command
Result: OK - subscribe completed
NO - subscribe failure: can't subscribe to that name
BAD - command unknown or arguments invalid
SUBSCRIBE 命令将指定的邮箱名添加到服务器由 LSUB 命令返回的"活动"或"已订阅"邮箱集合中。仅当订阅成功时,此命令才返回带标签的 OK 响应。
服务器可以验证 SUBSCRIBE 的邮箱参数以确认其存在。然而,即使具有该名称的邮箱已不再存在,它也不得单方面从订阅列表中移除一个现有的邮箱名。
注意:此要求是因为服务器站点可以选择在内容过期后,例行移除一个具有知名名称(例如 "system-alerts")的邮箱,并打算在有新内容时重新创建它。
示例:
Example: C: A002 SUBSCRIBE #news.comp.mail.mime
S: A002 OK SUBSCRIBE completed
6.3.7 UNSUBSCRIBE 命令
Arguments: mailbox name
Responses: no specific responses for this command
Result: OK - unsubscribe completed
NO - unsubscribe failure: can't unsubscribe that name
BAD - command unknown or arguments invalid
UNSUBSCRIBE 命令从服务器由 LSUB 命令返回的"活动"或"已订阅"邮箱集合中移除指定的邮箱名。仅当取消订阅成功时,此命令才返回带标签的 OK 响应。
示例:
Example: C: A002 UNSUBSCRIBE #news.comp.mail.mime
S: A002 OK UNSUBSCRIBE completed
6.3.8 LIST 命令
Arguments: reference name
mailbox name with possible wildcards
Responses: untagged responses: LIST
Result: OK - list completed
NO - list failure: can't list that reference or name
BAD - command unknown or arguments invalid
LIST 命令从客户端可用的全部名称集合中返回名称的一个子集。返回零条或多条无标签 LIST 应答,包含名称属性、层级分隔符与名称;详见 LIST 应答的描述。
LIST 命令应快速返回其数据,不得有不当延迟。例如,它不应过分费力地计算 \Marked 或 \Unmarked 状态,或执行其他处理;如果每个名称需要 1 秒处理,那么 1200 个名称的列表将耗时 20 分钟!
空的("" 字符串)reference name 参数表示邮箱名按 SELECT 的方式解释。返回的信箱名称必须与所提供的邮箱名模式匹配。非空的 reference name 参数是一个邮箱或邮箱层级级别的名称,并指示解释邮箱名时的上下文。
空的("" 字符串)邮箱名参数是一个特殊请求,用于返回 reference 中给定名称的层级分隔符与根名。如果 reference 是非根或非空字符串,作为根返回的值可以是空字符串。在所有情况下,都会返回一个层级分隔符(如果没有层级则为 NIL)。这允许客户端获取层级分隔符(或发现邮箱名是扁平的),即使当前不存在具有该名称的邮箱。
reference 与邮箱名参数被解释为一种表示无歧义的自左向右层级的规范形式。返回的信箱名称将采用解释后的形式。
注意:reference 参数的解释是实现定义的。它取决于服务器实现是否具有"当前工作目录"与用于覆盖当前工作目录的前导"跳出字符(break out characters)"的概念。
例如,在导出 UNIX 或 NT 文件系统的服务器上,reference 参数包含当前工作目录,而邮箱名参数包含按当前工作目录解释的名称。
如果服务器实现没有"跳出字符"的概念,规范形式通常是 reference 名附加邮箱名。注意,如果服务器实现了命名空间约定(第 5.1.2 节),"#" 是跳出字符,必须如此对待。
如果 reference 参数不是邮箱层级的一个级别(即,它是一个 \NoInferiors 名称),和/或 reference 参数不以层级分隔符结尾,则如何解释是实现相关的。例如,reference 为 "foo/bar"、邮箱名为 "rag/baz" 可能被解释为 "foo/bar/rag/baz"、"foo/barrag/baz" 或 "foo/rag/baz"。除用户显式请求外,客户端不应使用这样的 reference 参数。层级浏览器不得对服务器解释 reference 作任何假设,除非 reference 是邮箱层级的一个级别并且以层级分隔符结尾。
reference 参数中被包含在解释形式中的任何部分,都应当以解释形式作为前缀。它也应与 reference name 参数具有相同的形式。此规则允许客户端确定返回的邮箱名是否处于 reference 参数的上下文中,或者关于邮箱参数的某些内容是否覆盖了 reference 参数。没有此规则,客户端就必须了解服务器的命名语义,包括哪些字符是覆盖命名上下文的"跳出"字符。
例如,以下是基于 UNIX 的服务器上 reference 与邮箱名可能如何解释的一些示例:
Reference Mailbox Name Interpretation
------------ ------------ --------------
~smith/Mail/ foo.* ~smith/Mail/foo.*
archive/ % archive/%
#news. comp.mail.* #news.comp.mail.*
~smith/Mail/ /usr/doc/foo /usr/doc/foo
archive/ ~fred/Mail/* ~fred/Mail/*
前三个示例演示了在 reference 参数上下文中的解释。注意,"~smith/Mail" 不应被转换为类似 "/u2/users/smith/Mail" 的形式,否则客户端将无法判断该解释处于 reference 的上下文中。
字符 "*" 是通配符,匹配该位置零个或多个字符。字符 "%" 类似于 "*",但它不匹配层级分隔符。如果 "%" 通配符是邮箱名参数的最后一个字符,则也返回匹配的层级级别。如果这些层级级别也不可选为邮箱,则它们以 \Noselect 邮箱名属性返回(详见 LIST 响应的描述)。
服务器实现可以"隐藏"原本可访问的邮箱,使其免于被通配符匹配,方式是防止某些字符或名称在特定情况下匹配通配符。例如,基于 UNIX 的服务器可能限制 "*" 的解释,使其不匹配起始的 "/" 字符。
如果本服务器为本用户支持 INBOX,并且大写字符串 "INBOX" 与上述带通配符的解释后 reference 与邮箱名参数匹配,则 INBOX 这一特殊名称会包含在 LIST 的输出中。省略 INBOX 的标准是:SELECT INBOX 是否会返回失败;至于用户的真实 INBOX 是位于本服务器还是其他服务器,与此无关。
示例:
Example: C: A101 LIST "" ""
S: * LIST (\Noselect) "/" ""
S: A101 OK LIST Completed
C: A102 LIST #news.comp.mail.misc ""
S: * LIST (\Noselect) "." #news.
S: A102 OK LIST Completed
C: A103 LIST /usr/staff/jones ""
S: * LIST (\Noselect) "/" /
S: A103 OK LIST Completed
C: A202 LIST ~/Mail/ %
S: * LIST (\Noselect) "/" ~/Mail/foo
S: * LIST () "/" ~/Mail/meetings
S: A202 OK LIST completed
6.3.9 LSUB 命令
Arguments: reference name
mailbox name with possible wildcards
Responses: untagged responses: LSUB
Result: OK - lsub completed
NO - lsub failure: can't list that reference or name
BAD - command unknown or arguments invalid
LSUB 命令从用户声明为"活动"或"已订阅"的名称集合中返回名称的一个子集。返回零条或多条无标签 LSUB 应答。LSUB 的参数与 LIST 的参数形式相同。
返回的无标签 LSUB 响应可能包含与 LIST 无标签响应不同的邮箱标志。如果发生这种情况,无标签 LIST 中的标志被视为更具权威性。
使用 LSUB 与 % 通配符时会出现一种特殊情况。考虑如果订阅了 "foo/bar"(层级分隔符为 "/")但未订阅 "foo" 时会发生什么。对 LSUB 的 "%" 通配符必须在 LSUB 响应中返回 foo 而非 foo/bar,并且它必须被标记为 \Noselect 属性。
即使具有该名称的邮箱已不再存在,服务器也不得单方面从订阅列表中移除一个现有的邮箱名。
示例:
Example: C: A002 LSUB "#news." "comp.mail.*"
S: * LSUB () "." #news.comp.mail.mime
S: * LSUB () "." #news.comp.mail.misc
S: A002 OK LSUB completed
C: A003 LSUB "#news." "comp.%"
S: * LSUB (\NoSelect) "." #news.comp.mail
S: A003 OK LSUB completed
6.3.10 STATUS 命令
Arguments: mailbox name
status data item names
Responses: untagged responses: STATUS
Result: OK - status completed
NO - status failure: no status for that name
BAD - command unknown or arguments invalid
STATUS 命令请求指定邮箱的状态。它不改变当前所选邮箱,也不影响被查询邮箱中任何消息的状态(特别地,STATUS 不得导致消息丢失 \Recent 标志)。
STATUS 命令提供了一条替代途径,免去了打开第二个 IMAP4rev1 连接并对某邮箱执行 EXAMINE 命令、以在不取消选择第一个 IMAP4rev1 连接中当前所选邮箱的情况下查询该邮箱状态的操作。
与 LIST 命令不同,STATUS 命令不保证响应迅速。在某些情况下,它可能相当缓慢。在某些实现中,服务器不得不以只读方式在内部打开邮箱以获取某些状态信息。同样与 LIST 命令不同,STATUS 命令不接受通配符。
注意:STATUS 命令旨在访问当前所选邮箱之外的邮箱状态。因为 STATUS 命令可能导致邮箱在内部被打开,并且因为此信息在所选邮箱上可通过其他方式获得,所以不应在当前所选邮箱上使用 STATUS 命令。
STATUS 命令不得用作"检查所选邮箱中的新消息"操作(关于新消息检查的正确方法,见第 7、7.3.1 与 7.3.2 节)。
因为 STATUS 命令不保证结果迅速,客户端不应期望能够发出许多连续的 STATUS 命令并获得合理的性能。
当前可请求的状态数据项有:
- MESSAGES:邮箱中的消息数量。
- RECENT:设置了 \Recent 标志的消息数量。
- UIDNEXT:邮箱的下一个唯一标识符值。更多信息见第 2.3.1.1 节。
- UIDVALIDITY:邮箱的唯一标识符有效性值。更多信息见第 2.3.1.1 节。
- UNSEEN:未设置 \Seen 标志的消息数量。
示例:
Example: C: A042 STATUS blurdybloop (UIDNEXT MESSAGES)
S: * STATUS blurdybloop (MESSAGES 231 UIDNEXT 44292)
S: A042 OK STATUS completed
6.3.11 APPEND 命令
Arguments: mailbox name
OPTIONAL flag parenthesized list
OPTIONAL date/time string
message literal
Responses: no specific responses for this command
Result: OK - append completed
NO - append error: can't append to that mailbox, error
in flags or date/time or message text
BAD - command unknown or arguments invalid
APPEND 命令将 literal 参数作为新消息附加到指定目标邮箱的末尾。此参数应采用 [RFC-2822] 消息的格式。消息中允许 8 位字符。无法正确保留 8 位数据的服务器实现,必须能够使用 [MIME-IMB] 内容传输编码将 8 位 APPEND 数据可逆地转换为 7 位。
注意:可能存在例外,例如草稿消息,其中在传给 APPEND 的 message literal 参数中省略了必需的 [RFC-2822] 头行。这样做可能产生的全部后果必须被理解并仔细权衡。
如果指定了标志括号列表,则应在生成的消息中设置这些标志;否则,生成的消息的标志列表默认设为空。无论哪种情况,Recent 标志也会被设置。
如果指定了日期时间,则应在生成的消息中设置内部日期;否则,生成的消息的内部日期默认设为当前日期与时间。
如果附加因任何原因未成功,邮箱必须恢复到 APPEND 尝试之前的状态;不允许部分附加。
如果目标邮箱不存在,服务器必须返回错误,并且不得自动创建邮箱。除非确定目标邮箱无法被创建,否则服务器必须将响应码 "[TRYCREATE]" 作为带标签 NO 响应文本的前缀发送。这向客户端提示,它可以尝试 CREATE 命令,并在 CREATE 成功时重试 APPEND。
如果目标邮箱当前已被选中,则正常的"新消息"动作应当发生。特别地,服务器应立即通过无标签 EXISTS 响应通知客户端。如果服务器没有这样做,客户端可以在一条或多条 APPEND 命令之后发出 NOOP 命令(若不行,则发出 CHECK 命令)。
示例:
Example: C: A003 APPEND saved-messages (\Seen) {310}
S: + Ready for literal data
C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
C: From: Fred Foobar <foobar@Blurdybloop.COM>
C: Subject: afternoon meeting
C: To: mooch@owatagu.siam.edu
C: Message-Id: <B27397-0100000@Blurdybloop.COM>
C: MIME-Version: 1.0
C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
C:
C: Hello Joe, do you think we can meet at 3:30 tomorrow?
C:
S: A003 OK APPEND completed
注意:APPEND 命令不用于邮件投递,因为它没有提供传输 [SMTP] 信封信息的机制。
6.4 客户端命令 - 已选状态
在已选状态,允许操作邮箱中消息的命令。
除通用命令(CAPABILITY、NOOP 与 LOGOUT),以及已认证状态命令(SELECT、EXAMINE、CREATE、DELETE、RENAME、SUBSCRIBE、UNSUBSCRIBE、LIST、LSUB、STATUS 与 APPEND)外,以下命令在已选状态下有效:CHECK、CLOSE、EXPUNGE、SEARCH、FETCH、STORE、COPY 与 UID。
6.4.1 CHECK 命令
Arguments: none
Responses: no specific responses for this command
Result: OK - check completed
BAD - command unknown or arguments invalid
CHECK 命令请求对当前所选邮箱执行一次检查点(checkpoint)。检查点指与邮箱相关的任何实现相关的内务处理(例如,将服务器在内存中的邮箱状态与其磁盘状态相调和),这些通常不是作为每条命令的一部分来执行的。检查点可能需要非瞬时量的真实时间来完成。如果服务器实现没有此类内务考量,CHECK 等同于 NOOP。
不能保证 CHECK 会导致 EXISTS 无标签响应。新消息轮询应使用 NOOP 而非 CHECK。
示例:
Example: C: FXXZ CHECK
S: FXXZ OK CHECK Completed
6.4.2 CLOSE 命令
Arguments: none
Responses: no specific responses for this command
Result: OK - close completed, now in authenticated state
BAD - command unknown or arguments invalid
CLOSE 命令永久移除当前所选邮箱中所有设置了 \Deleted 标志的消息,并从已选状态返回到已认证状态。不发送无标签 EXPUNGE 响应。
如果邮箱是由 EXAMINE 命令选中的,或以其他方式选为只读,则不移除任何消息,也不给出错误。
即使已选中某个邮箱,也可以在先前不发出 CLOSE 命令的情况下发出 SELECT、EXAMINE 或 LOGOUT 命令。SELECT、EXAMINE 与 LOGOUT 命令会隐式关闭当前所选邮箱,而不执行清除(expunge)。然而,当许多消息被删除时,CLOSE-LOGOUT 或 CLOSE-SELECT 序列比 EXPUNGE-LOGOUT 或 EXPUNGE-SELECT 快得多,因为不会发送无标签 EXPUNGE 响应(客户端大概会忽略它们)。
示例:
Example: C: A341 CLOSE
S: A341 OK CLOSE completed
6.4.3 EXPUNGE 命令
Arguments: none
Responses: untagged responses: EXPUNGE
Result: OK - expunge completed
NO - expunge failure: can't expunge (e.g., permission
denied)
BAD - command unknown or arguments invalid
EXPUNGE 命令永久移除当前所选邮箱中所有设置了 \Deleted 标志的消息。在向客户端返回 OK 之前,为每条被移除的消息发送一条无标签 EXPUNGE 响应。
示例:
Example: C: A202 EXPUNGE
S: * 3 EXPUNGE
S: * 3 EXPUNGE
S: * 5 EXPUNGE
S: * 8 EXPUNGE
S: A202 OK EXPUNGE completed
注意:在此示例中,消息 3、4、7 与 11 设置了 \Deleted 标志。详见 EXPUNGE 响应的描述。
6.4.4 SEARCH 命令
Arguments: OPTIONAL [CHARSET] specification
searching criteria (one or more)
Responses: REQUIRED untagged response: SEARCH
Result: OK - search completed
NO - search error: can't search that [CHARSET] or
criteria
BAD - command unknown or arguments invalid
SEARCH 命令在邮箱中搜索匹配给定搜索条件的消息。搜索条件由一个或多个搜索键组成。来自服务器的无标签 SEARCH 响应包含与匹配搜索条件的那些消息相对应的消息序列号列表。
当指定多个键时,结果是匹配这些键的所有消息的交集(AND 函数)。例如,条件 DELETED FROM "SMITH" SINCE 1-Feb-1994 指自 1994 年 2 月 1 日以来放入邮箱、来自 Smith 的所有已删除消息。一个搜索键也可以是一个包含一个或多个搜索键的括号列表(例如,用于配合 OR 与 NOT 键)。
服务器实现可以从 SEARCH 匹配考量中排除终端内容媒体类型不是 TEXT 或 MESSAGE 的 [MIME-IMB] 主体部分。
可选的 [CHARSET] 规范由单词 "CHARSET" 后随一个已注册的 [CHARSET] 组成。它表示出现在搜索条件中的字符串的 [CHARSET]。在比较非 US-ASCII 的 [CHARSET] 中的文本之前,必须解码 [MIME-IMB] 内容传输编码,以及 [RFC-2822]/[MIME-IMB] 头中的 [MIME-HDRS] 字符串。必须支持 US-ASCII;其他 [CHARSET] 可以支持。
如果服务器不支持指定的 [CHARSET],它必须返回带标签的 NO 响应(而非 BAD)。此响应应包含 BADCHARSET 响应码,其中可以列出服务器支持的 [CHARSET]。
在所有使用字符串的搜索键中,如果字符串是该字段的子串,消息即匹配该键。匹配是大小写不敏感的。
定义的搜索键如下。参数精确语法定义见"形式文法"一节。
- <sequence set>:消息序列号对应于指定消息序列号集合的消息。
- ALL:邮箱中的所有消息;AND 操作的默认初始键。
- ANSWERED:设置了 \Answered 标志的消息。
- BCC <string>:在信封结构的 BCC 字段中包含指定字符串的消息。
- BEFORE <date>:内部日期(忽略时间与时区)早于指定日期的消息。
- BODY <string>:在消息正文中包含指定字符串的消息。
- CC <string>:在信封结构的 CC 字段中包含指定字符串的消息。
- DELETED:设置了 \Deleted 标志的消息。
- DRAFT:设置了 \Draft 标志的消息。
- FLAGGED:设置了 \Flagged 标志的消息。
- FROM <string>:在信封结构的 FROM 字段中包含指定字符串的消息。
- HEADER <field-name> <string>:具有以指定 field-name(如 [RFC-2822] 所定义)命名、且其头文本(冒号之后的内容)包含指定字符串的头的消息。如果要搜索的字符串长度为零,则匹配所有具有以该 field-name 命名的头行的消息,无论其内容如何。
- KEYWORD <flag>:设置了指定关键字标志的消息。
- LARGER <n>:具有大于指定八位组数的 [RFC-2822] 大小的消息。
- NEW:设置了 \Recent 标志但未设置 \Seen 标志的消息。功能上等价于 "(RECENT UNSEEN)"。
- NOT <search-key>:不匹配指定搜索键的消息。
- OLD:未设置 \Recent 标志的消息。功能上等价于 "NOT RECENT"(而非 "NOT NEW")。
- ON <date>:内部日期(忽略时间与时区)在指定日期内的消息。
- OR <search-key1> <search-key2>:匹配两个搜索键中任一个的消息。
- RECENT:设置了 \Recent 标志的消息。
- SEEN:设置了 \Seen 标志的消息。
- SENTBEFORE <date>:其 [RFC-2822] Date: 头(忽略时间与时区)早于指定日期的消息。
- SENTON <date>:其 [RFC-2822] Date: 头(忽略时间与时区)在指定日期内的消息。
- SENTSINCE <date>:其 [RFC-2822] Date: 头(忽略时间与时区)在指定日期或晚于指定日期的消息。
- SINCE <date>:其内部日期(忽略时间与时区)在指定日期或晚于指定日期的消息。
- SMALLER <n>:具有小于指定八位组数的 [RFC-2822] 大小的消息。
- SUBJECT <string>:在信封结构的 SUBJECT 字段中包含指定字符串的消息。
- TEXT <string>:在消息的头或正文中包含指定字符串的消息。
- TO <string>:在信封结构的 TO 字段中包含指定字符串的消息。
- UID <sequence set>:唯一标识符对应于指定唯一标识符集合的消息。允许序列号集合范围。
- UNANSWERED:未设置 \Answered 标志的消息。
- UNDELETED:未设置 \Deleted 标志的消息。
- UNDRAFT:未设置 \Draft 标志的消息。
- UNFLAGGED:未设置 \Flagged 标志的消息。
- UNKEYWORD <flag>:未设置指定关键字标志的消息。
- UNSEEN:未设置 \Seen 标志的消息。
示例:
Example: C: A282 SEARCH FLAGGED SINCE 1-Feb-1994 NOT FROM "Smith"
S: * SEARCH 2 84 882
S: A282 OK SEARCH completed
C: A283 SEARCH TEXT "string not in mailbox"
S: * SEARCH
S: A283 OK SEARCH completed
C: A284 SEARCH CHARSET UTF-8 TEXT {6}
C: XXXXXX
S: * SEARCH 43
S: A284 OK SEARCH completed
注意:由于本文档限于 7 位 ASCII 文本,无法展示实际的 UTF-8 数据。"XXXXXX" 是在实际事务中应为 6 个八位组 8 位数据的占位符。
6.4.5 FETCH 命令
Arguments: sequence set
message data item names or macro
Responses: untagged responses: FETCH
Result: OK - fetch completed
NO - fetch error: can't fetch that data
BAD - command unknown or arguments invalid
FETCH 命令检索邮箱中消息关联的数据。要获取的数据项可以是单个 atom,也可以是一个括号列表。
大多数在形式文法下以 msg-att-static 规则标识的数据项是静态的,对于任何特定消息都不得改变。其他在形式文法下以 msg-att-dynamic 规则标识的数据项可能改变,原因可以是 STORE 命令或外部事件。
例如,如果客户端在已经知道某消息的信封时收到该消息的 ENVELOPE,它可以安全地忽略新传输的信封。
有三个宏指定常用的数据项集合,可用来代替数据项。一个宏必须单独使用,不得与其他宏或数据项配合使用。
- ALL:等价于 (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) 的宏。
- FAST:等价于 (FLAGS INTERNALDATE RFC822.SIZE) 的宏。
- FULL:等价于 (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY) 的宏。
当前可获取的数据项有:
- BODY:BODYSTRUCTURE 的不可扩展形式。
- BODY[<section>]<<partial>>:特定主体部分的文本。部分规范是一组由句点分隔的零个或多个部分说明符。部分说明符可以是部分编号,或是以下之一:HEADER、HEADER.FIELDS、HEADER.FIELDS.NOT、MIME 与 TEXT。空的部分规范指整条消息,包括头。
- BODY.PEEK[<section>]<<partial>>:BODY[<section>] 的一种替代形式,不隐式设置 \Seen 标志。
- BODYSTRUCTURE:消息的 [MIME-IMB] 主体结构。这由服务器通过解析 [RFC-2822] 头与 [MIME-IMB] 头中的 [MIME-IMB] 头字段计算得出。
- ENVELOPE:消息的信封结构。这由服务器通过将 [RFC-2822] 头解析为组成部分、按需默认化各字段计算得出。
- FLAGS:为此消息设置的标志。
- INTERNALDATE:消息的内部日期。
- RFC822:功能上等价于 BODY[],差异在于结果无标签 FETCH 数据的语法(返回 RFC822)。
- RFC822.HEADER:功能上等价于 BODY.PEEK[HEADER],差异在于结果无标签 FETCH 数据的语法(返回 RFC822.HEADER)。
- RFC822.SIZE:消息的 [RFC-2822] 大小。
- RFC822.TEXT:功能上等价于 BODY[TEXT],差异在于结果无标签 FETCH 数据的语法(返回 RFC822.TEXT)。
- UID:消息的唯一标识符。
每个消息至少有一个部分编号。非 [MIME-IMB] 消息,以及没有封装消息的非多部分 [MIME-IMB] 消息,只有部分 1。
多部分消息被赋予连续的部分编号,依其在消息中出现的顺序。如果某个特定部分是 message 或 multipart 类型,其各部分必须通过其后跟该嵌套多部分部分中的部分编号的句点来指示。
类型为 MESSAGE/RFC822 的部分也具有嵌套的部分编号,指代 MESSAGE 部分主体的各部分。
HEADER、HEADER.FIELDS、HEADER.FIELDS.NOT 与 TEXT 部分说明符可以是唯一的部分说明符,也可以由一个或多个数字部分说明符前缀,前提是数字部分说明符指代 MESSAGE/RFC822 类型的部分。MIME 部分说明符必须由一个或多个数字部分说明符前缀。
HEADER、HEADER.FIELDS 与 HEADER.FIELDS.NOT 部分说明符指消息的 [RFC-2822] 头,或封装的 [MIME-IMT] MESSAGE/RFC822 消息。[MIME-IMB] 头。HEADER.FIELDS 与 HEADER.FIELDS.NOT 后随一个字段名(如 [RFC-2822] 所定义)名称列表,并返回一个头的子集。HEADER.FIELDS 返回的子集仅包含字段名与列表中某个名称匹配的那些头字段;类似地,HEADER.FIELDS.NOT 返回的子集仅包含字段名不匹配的头字段。字段匹配是大小写不敏感的,但在其他方面完全匹配。子集化不排除头与主体之间的 [RFC-2822] 分隔空行;该空行包含在所有头部获取中,消息既无主体也无空行的情况除外。
MIME 部分说明符指该部分的 [MIME-IMB] 头。
TEXT 部分说明符指消息的文本主体,省略 [RFC-2822] 头。
以下是一个复杂消息及其部分说明符的示例:
HEADER ([RFC-2822] header of the message)
TEXT ([RFC-2822] text body of the message) MULTIPART/MIXED
1 TEXT/PLAIN
2 APPLICATION/OCTET-STREAM
3 MESSAGE/RFC822
3.HEADER ([RFC-2822] header of the message)
3.TEXT ([RFC-2822] text body of the message) MULTIPART/MIXED
3.1 TEXT/PLAIN
3.2 APPLICATION/OCTET-STREAM
4 MULTIPART/MIXED
4.1 IMAGE/GIF
4.1.MIME ([MIME-IMB] header for the IMAGE/GIF)
4.2 MESSAGE/RFC822
4.2.HEADER ([RFC-2822] header of the message)
4.2.TEXT ([RFC-2822] text body of the message) MULTIPART/MIXED
4.2.1 TEXT/PLAIN
4.2.2 MULTIPART/ALTERNATIVE
4.2.2.1 TEXT/PLAIN
4.2.2.2 TEXT/RICHTEXT
可以获取指定文本的某子串。这通过在部分说明符后附上开尖括号("<")、第一个所需八位组的位置、一个句点、所需八位组的最大数量,以及闭尖括号(">")来实现。如果起始八位组超出了文本末尾,则返回一个空字符串。
任何试图读取超出文本末尾的部分获取,都会适当地截断。从八位组 0 开始的部分获取作为部分获取返回,即使发生了此截断。
注意:这意味着,对 1500 八位组消息的 BODY[]<0.2048> 将返回 BODY[]<0> 以及大小为 1500 的 literal,而非 BODY[]。
注意:HEADER.FIELDS 或 HEADER.FIELDS.NOT 部分说明符的子串获取,是在对头进行子集化之后计算的。
\Seen 标志被隐式设置;如果这导致标志改变,它们应作为 FETCH 响应的一部分被包含。
示例:
Example: C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])
S: * 2 FETCH ....
S: * 3 FETCH ....
S: * 4 FETCH ....
S: A654 OK FETCH completed
6.4.6 STORE 命令
Arguments: sequence set
message data item name
value for message data item
Responses: untagged responses: FETCH
Result: OK - store completed
NO - store error: can't store that data
BAD - command unknown or arguments invalid
STORE 命令改变邮箱中消息关联的数据。通常,STORE 会以一条无标签 FETCH 响应返回数据的更新值。数据项名称中的 ".SILENT" 后缀阻止无标签 FETCH,服务器应假定客户端已自行确定了更新值,或并不关心更新值。
注意:无论是否使用了 ".SILENT" 后缀,如果观察到来自外部源对某消息标志的改变,服务器都应发送一条无标签 FETCH 响应。其意图是使标志的状态在没有竞争条件的情况下是确定的。
当前可存储的数据项有:
- FLAGS <flag list>:用参数替换消息的标志(\Recent 除外)。新的标志值如同对这些标志执行了一次 FETCH 那样被返回。
- FLAGS.SILENT <flag list>:等价于 FLAGS,但不返回新值。
- +FLAGS <flag list>:将参数添加到消息的标志中。新的标志值如同对这些标志执行了一次 FETCH 那样被返回。
- +FLAGS.SILENT <flag list>:等价于 +FLAGS,但不返回新值。
- -FLAGS <flag list>:从消息的标志中移除参数。新的标志值如同对这些标志执行了一次 FETCH 那样被返回。
- -FLAGS.SILENT <flag list>:等价于 -FLAGS,但不返回新值。
示例:
Example: C: A003 STORE 2:4 +FLAGS (\Deleted)
S: * 2 FETCH (FLAGS (\Deleted \Seen))
S: * 3 FETCH (FLAGS (\Deleted))
S: * 4 FETCH (FLAGS (\Deleted \Flagged \Seen))
S: A003 OK STORE completed
6.4.7 COPY 命令
Arguments: sequence set
mailbox name
Responses: no specific responses for this command
Result: OK - copy completed
NO - copy error: can't copy those messages or to that
name
BAD - command unknown or arguments invalid
COPY 命令将指定的消息复制到指定目标邮箱的末尾。消息的标志与内部日期应在副本中保留,并且 Recent 标志应设置。
如果目标邮箱不存在,服务器应返回错误。它不应自动创建邮箱。除非确定目标邮箱无法被创建,否则服务器必须将响应码 "[TRYCREATE]" 作为带标签 NO 响应文本的前缀发送。这向客户端提示,它可以尝试 CREATE 命令,并在 CREATE 成功时重试 COPY。
如果 COPY 命令因任何原因未成功,服务器实现必须将目标邮箱恢复到 COPY 尝试之前的状态。
示例:
Example: C: A003 COPY 2:4 MEETING
S: A003 OK COPY completed
6.4.8 UID 命令
Arguments: command name
command arguments
Responses: untagged responses: FETCH, SEARCH
Result: OK - UID command completed
NO - UID command error
BAD - command unknown or arguments invalid
UID 命令有两种形式。第一种形式中,它接受一条 COPY、FETCH 或 STORE 命令作为参数,参数对应于关联的命令。然而,序列号集合参数中的数字是唯一标识符而非消息序列号。允许序列号集合范围,但不能保证唯一标识符是连续的。
不存在的唯一标识符被忽略,不生成任何错误消息。因此,UID FETCH 命令可能返回不带任何数据的 OK,UID COPY 或 UID STORE 也可能返回未执行任何操作的 OK。
第二种形式中,UID 命令接受一条 SEARCH 命令及 SEARCH 命令参数。参数的解释与 SEARCH 相同;然而,UID SEARCH 命令在 SEARCH 响应中返回的数字是唯一标识符而非消息序列号。例如,命令 UID SEARCH 1:100 UID 443:557 返回对应于两个序列集合交集的唯一标识符,即消息序列号范围 1:100 与 UID 范围 443:557。
注意:在上述示例中出现了 UID 范围 443:557。关于不存在的唯一标识符被忽略而不产生错误消息的同样说明也适用于此。因此,即使 UID 443 与 557 都不存在,该范围也是有效的,并将包含存在的 UID 495。
还要注意,559:* 的 UID 范围总是包含邮箱中最后一条消息的 UID,即使 559 高于任何已分配的 UID 值。这是因为范围的内容独立于范围端点的顺序。因此,任何以 * 作为端点之一的 UID 范围至少指示一条消息(具有最高编号 UID 的消息),除非邮箱为空。
无标签 FETCH 响应中 "*" 之后的数字始终是消息序列号,而非唯一标识符,即使对于 UID 命令响应也是如此。然而,服务器实现必须将 UID 消息数据项隐式包含为任何由 UID 命令引起的 FETCH 响应的一部分,无论是否将 UID 指定为 FETCH 的消息数据项。
注意:关于将 UID 消息数据项包含为 FETCH 响应一部分的规则,主要适用于 UID FETCH 与 UID STORE 命令,包括未将 UID 包含为消息数据项的 UID FETCH 命令。尽管其他 UID 命令不太可能引起无标签 FETCH,此规则同样适用于这些命令。
示例:
Example: C: A999 UID FETCH 4827313:4828442 FLAGS
S: * 23 FETCH (FLAGS (\Seen) UID 4827313)
S: * 24 FETCH (FLAGS (\Seen) UID 4827943)
S: * 25 FETCH (FLAGS (\Seen) UID 4828442)
S: A999 OK UID FETCH completed
6.5 客户端命令 - 实验性/扩展
6.5.1 X<atom> 命令
Arguments: implementation defined
Responses: implementation defined
Result: OK - command completed
NO - failure
BAD - command unknown or arguments invalid
任何以 X 为前缀的命令都是实验性命令。不属于本规范、本规范的标准或标准跟踪修订、或 IESG 批准实验性协议的命令,必须使用 X 前缀。
实验性命令发出的任何新增无标签响应也必须以 X 为前缀。服务器实现不得发送任何此类无标签响应,除非客户端通过发出关联的实验性命令请求了它。
示例:
Example: C: a441 CAPABILITY
S: * CAPABILITY IMAP4rev1 XPIG-LATIN
S: a441 OK CAPABILITY completed
C: A442 XPIG-LATIN
S: * XPIG-LATIN ow-nay eaking-spay ig-pay atin-lay
S: A442 OK XPIG-LATIN ompleted-cay
7. 服务器响应
服务器响应有三种形式:状态响应、服务器数据与命令延续请求。服务器响应中包含的信息,在下方响应描述中以 "Contents:" 标识,按功能而非语法描述。服务器响应的精确语法在"形式文法"一节描述。
客户端必须随时准备接受任何响应。
状态响应可以是带标签或无标签的。带标签状态响应指示客户端命令的完成结果(OK、NO 或 BAD 状态),并具有与该命令匹配的标签。
某些状态响应,以及所有服务器数据,是无标签的。无标签响应以 "*" 令牌而非标签来指示。无标签状态响应指示服务器问候,或不指示命令完成的服务器状态(例如,即将发生的系统关闭警报)。由于历史原因,无标签服务器数据响应也称为"unsolicited data(主动数据)",尽管严格来说,只有单方面的服务器数据才是真正"unsolicited"的。
某些服务器数据在收到时必须由客户端记录;这在该数据描述中注明。此类数据传达影响所有后续命令与响应解释的关键信息(例如,反映消息创建或销毁的更新)。
其他服务器数据应被记录以备日后参考;如果客户端不需要记录该数据,或者记录该数据没有明显用途(例如,在没有 SEARCH 命令执行时收到 SEARCH 响应),该数据应被忽略。
单方面无标签服务器数据的一个例子发生在 IMAP 连接处于已选状态时。在已选状态,服务器作为命令执行的一部分检查邮箱中的新消息。通常,这是每条命令执行的一部分;因此,一条 NOOP 命令就足以检查新消息。如果找到新消息,服务器发送反映邮箱新大小的无标签 EXISTS 与 RECENT 响应。提供对同一邮箱多次同时访问的服务器实现,如果另一个代理改变了任何消息标志的状态或清除了任何消息,也应发送适当的单方面无标签 FETCH 与 EXPUNGE 响应。
命令延续请求响应使用 "+" 令牌而非标签。这些响应由服务器发送,以指示接受一条不完整的客户端命令,并准备好接收命令的其余部分。
7.1 服务器响应 - 状态响应
状态响应为 OK、NO、BAD、PREAUTH 与 BYE。OK、NO 与 BAD 可以是带标签或无标签的。PREAUTH 与 BYE 总是无标签的。
状态响应可以包含一个可选的"响应码(response code)"。响应码由方括号内的数据组成,形式为 atom,可能后随一个空格与参数。响应码包含超出 OK/NO/BAD 条件的、供客户端软件使用的附加信息或状态码,并且当客户端可以基于附加信息采取特定动作时才有定义。
当前定义的响应码有:
- ALERT:人类可读文本包含一个特殊警报,必须以引起用户注意该消息的方式呈现给用户。
- BADCHARSET:可选地后随一个字符集的括号列表。SEARCH 失败,因为给定的字符集不被本实现支持。如果给出了可选的字符集列表,则列出本实现支持的字符集。
- CAPABILITY:后随一个能力列表。它可以出现在初始的 OK 或 PREAUTH 响应中,以传输初始能力列表。如果客户端识别此响应,则无需发送单独的 CAPABILITY 命令。
- PARSE:人类可读文本表示在解析邮箱中消息的 [RFC-2822] 头或 [MIME-IMB] 头时的错误。
- PERMANENTFLAGS:后随一个标志的括号列表,指示客户端可以永久改变哪些已知标志。任何出现在 FLAGS 无标签响应中但不在 PERMANENTFLAGS 列表中的标志,不能被永久设置。如果客户端尝试 STORE 一个不在 PERMANENTFLAGS 列表中的标志,服务器将要么忽略该改变,要么仅将状态改变存储到当前会话的其余时间。PERMANENTFLAGS 列表也可以包含特殊标志 \*,它表示可以通过尝试将这些标志存储在邮箱中来创建新关键字。
- READ-ONLY:邮箱被选为只读,或者其在选中期间的访问已从读-写变为只读。
- READ-WRITE:邮箱被选为读-写,或者其在选中期间的访问已从只读变为读-写。
- TRYCREATE:一次 APPEND 或 COPY 尝试因目标邮箱不存在(而非其他原因)而失败。这提示客户端,如果首先通过 CREATE 命令创建邮箱,该操作就能成功。
- UIDNEXT:后随一个十进制数字,指示下一个唯一标识符值。更多信息见第 2.3.1.1 节。
- UIDVALIDITY:后随一个十进制数字,指示唯一标识符有效性值。更多信息见第 2.3.1.1 节。
- UNSEEN:后随一个十进制数字,指示第一条未设置 \Seen 标志的消息的编号。
由特定客户端或服务器实现定义的附加响应码应加上 "X" 前缀,直到它们被加入本协议的某个修订版。客户端实现应忽略它们无法识别的响应码。
7.1.1 OK 响应
Contents: OPTIONAL response code
human-readable text
OK 响应指示来自服务器的信息消息。当带标签时,它指示关联命令的成功完成。人类可读文本可以作为信息消息呈现给用户。无标签形式指示一条仅信息的消息;信息的性质可以由响应码指示。
无标签形式也用作连接启动时的三种可能问候之一。它表示连接尚未认证,需要一条 LOGIN 命令。
示例:
Example: S: * OK IMAP4rev1 server ready
C: A001 LOGIN fred blurdybloop
S: * OK [ALERT] System shutdown in 10 minutes
S: A001 OK LOGIN Completed
7.1.2 NO 响应
Contents: OPTIONAL response code
human-readable text
NO 响应指示来自服务器的操作错误消息。当带标签时,它指示关联命令的未完成。无标签形式指示一条警告;命令仍可以成功完成。人类可读文本描述了该状况。
示例:
Example: C: A222 COPY 1:2 owatagusiam
S: * NO Disk is 98% full, please delete unnecessary data
S: A222 OK COPY completed
C: A223 COPY 3:200 blurdybloop
S: * NO Disk is 98% full, please delete unnecessary data
S: * NO Disk is 99% full, please delete unnecessary data
S: A223 NO COPY failed: disk is full
7.1.3 BAD 响应
Contents: OPTIONAL response code
human-readable text
BAD 响应指示来自服务器的错误消息。当带标签时,它报告客户端命令中的协议级错误;标签指示导致错误的命令。无标签形式指示无法确定关联命令的协议级错误;它也可以指示服务器内部故障。人类可读文本描述了该状况。
示例:
Example: C: ...very long command line...
S: * BAD Command line too long
C: ...empty line...
S: * BAD Empty command line
C: A443 EXPUNGE
S: * BAD Disk crash, attempting salvage to a new disk!
S: * OK Salvage successful, no data lost
S: A443 OK Expunge completed
7.1.4 PREAUTH 响应
Contents: OPTIONAL response code
human-readable text
PREAUTH 响应总是无标签的,并且是连接启动时三种可能问候之一。它表示连接已经通过外部手段认证;因此不需要 LOGIN 命令。
示例:
Example: S: * PREAUTH IMAP4rev1 server logged in as Smith
7.1.5 BYE 响应
Contents: OPTIONAL response code
human-readable text
BYE 响应总是无标签的,表示服务器即将关闭连接。人类可读文本可以由客户端在状态报告中显示给用户。BYE 响应在以下四种情况之一下发送:
- 作为正常登出序列的一部分。服务器将在发送对 LOGOUT 命令的带标签 OK 响应后关闭连接。
- 作为紧急关闭声明。服务器立即关闭连接。
- 作为非活跃自动登出的声明。服务器立即关闭连接。
- 作为连接启动时三种可能问候之一,表示服务器不愿意接受来自此客户端的连接。服务器立即关闭连接。
作为正常登出序列一部分的 BYE(第一种情况),与因失败而发生的 BYE(其他三种情况)之间的差别在于:在失败情况下连接立即关闭。在所有情况下,客户端应继续从服务器读取响应数据,直到连接关闭;这将确保任何挂起的无标签或完成响应都被读取与处理。
示例:
Example: S: * BYE Autologout; idle for too long
7.2 服务器响应 - 服务器与邮箱状态
这些响应总是无标签的。服务器与邮箱状态数据正是这样从服务器传输到客户端。这些响应中的许多通常由同名的命令产生。
7.2.1 CAPABILITY 响应
Contents: capability listing
CAPABILITY 响应作为 CAPABILITY 命令的结果出现。能力列表包含服务器支持的、以空格分隔的能力名列表。能力列表必须包含 atom "IMAP4rev1"。
此外,客户端与服务器实现必须实现 STARTTLS、LOGINDISABLED 与 AUTH=PLAIN(在 [IMAP-TLS] 中描述)能力。重要信息见"安全考量"一节。
以 "AUTH=" 开头的能力名表示该服务器支持该特定认证机制。
LOGINDISABLED 能力表示 LOGIN 命令被禁用,并且即使用户名与口令有效,服务器也会对任何使用 LOGIN 命令的尝试以带标签 NO 响应应答。如果服务器通告 LOGINDISABLED 能力,IMAP 客户端不得发出 LOGIN 命令。
其他能力名表示服务器支持 IMAP4rev1 协议的扩展、修订或修正。在客户端发出使用关联能力的命令之前,服务器响应必须符合本文档。
能力名必须以 "X" 开头,或者是向 IANA 注册的、标准或标准跟踪的 IMAP4rev1 扩展、修订或修正。服务器不得提供未注册或非标准的能力名,除非此类名称以 "X" 为前缀。
客户端实现不应要求除 "IMAP4rev1" 之外的任何能力名,并且必须忽略任何未知的能力名。
服务器可以通过在初始 PREAUTH 或 OK 响应中使用 CAPABILITY 响应码,并在成功认证的带标签 OK 响应中发送更新的 CAPABILITY 响应码,来自动发送能力。如果客户端识别这些自动能力,就无需发送单独的 CAPABILITY 命令。
示例:
Example: S: * CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI XPIG-LATIN
7.2.2 LIST 响应
Contents: name attributes
hierarchy delimiter
name
LIST 响应作为 LIST 命令的结果出现。它返回匹配 LIST 规范的一个名称。一条 LIST 命令可以有多个 LIST 响应。
定义了四个名称属性:
- \Noinferiors:在此名称之下不可能存在任何子层级;现在不存在子层级,将来也不能创建。
- \Noselect:不可能将此名称用作可选择的邮箱。
- \Marked:邮箱已被服务器标记为"有趣的(interesting)";该邮箱可能包含自上次选择该邮箱以来新增的消息。
- \Unmarked:自上次选择该邮箱以来,邮箱不包含任何附加消息。
如果服务器无法确定邮箱是否"有趣",或者该名称是 \Noselect 名称,服务器不应发送 \Marked 或 \Unmarked。
层级分隔符是用于分隔邮箱名中层级级别的字符。客户端可以用它来创建子邮箱,并搜索命名层级中的更高或更低级别。一个顶级层级节点的所有子节点必须使用相同的分隔符字符。NIL 层级分隔符表示不存在层级;该名称是"扁平"名称。
该名称表示无歧义的自左向右层级,并且必须可作为 LIST 与 LSUB 命令中的 reference 有效使用。除非指明了 \Noselect,否则该名称也必须可作为接受邮箱名的命令(如 SELECT)的参数。
示例:
Example: S: * LIST (\Noselect) "/" ~/Mail/foo
7.2.3 LSUB 响应
Contents: name attributes
hierarchy delimiter
name
LSUB 响应作为 LSUB 命令的结果出现。它返回匹配 LSUB 规范的一个名称。一条 LSUB 命令可以有多个 LSUB 响应。数据的格式与 LIST 响应相同。
示例:
Example: S: * LSUB () "." #news.comp.mail.misc
7.2.4 STATUS 响应
Contents: name
status parenthesized list
STATUS 响应作为 STATUS 命令的结果出现。它返回匹配 STATUS 规范的邮箱名,以及所请求的邮箱状态信息。
示例:
Example: S: * STATUS blurdybloop (MESSAGES 231 UIDNEXT 44292)
7.2.5 SEARCH 响应
Contents: zero or more numbers
SEARCH 响应作为 SEARCH 或 UID SEARCH 命令的结果出现。数字指代匹配搜索条件的那些消息。对于 SEARCH,这些是消息序列号;对于 UID SEARCH,这些是唯一标识符。每个数字以空格分隔。
示例:
Example: S: * SEARCH 2 3 6
7.2.6 FLAGS 响应
Contents: flag parenthesized list
FLAGS 响应作为 SELECT 或 EXAMINE 命令的结果出现。标志括号列表标识适用于此邮箱的标志(至少包括系统定义的标志)。除系统标志外,根据服务器实现也可能存在其他标志。
FLAGS 响应的更新必须由客户端记录。
示例:
Example: S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
7.3 服务器响应 - 邮箱大小
这些响应总是无标签的。邮箱大小的改变正是这样从服务器传输到客户端。"*" 令牌之后紧跟一个代表消息计数的数字。
7.3.1 EXISTS 响应
Contents: none
EXISTS 响应报告邮箱中的消息数量。此响应作为 SELECT 或 EXAMINE 命令的结果出现,并且如果邮箱大小改变(例如,新消息)也会出现。
EXISTS 响应的更新必须由客户端记录。
示例:
Example: S: * 23 EXISTS
7.3.2 RECENT 响应
Contents: none
RECENT 响应报告设置了 \Recent 标志的消息数量。此响应作为 SELECT 或 EXAMINE 命令的结果出现,并且如果邮箱大小改变(例如,新消息)也会出现。
注意:不能保证最近消息的消息序列号会是邮箱中最高 n 条消息(其中 n 是 RECENT 响应报告的值)的连续范围。这种情况不成立的例子有:多个客户端打开了同一邮箱(首个被通知的会话会将其视为最近,其他很可能视为非最近),以及当邮箱被非 IMAP 代理重新排序时。
识别最近消息的唯一可靠方法是查看消息标志,看哪些设置了 \Recent 标志,或者执行 SEARCH RECENT。
RECENT 响应的更新必须由客户端记录。
示例:
Example: S: * 5 RECENT
7.4 服务器响应 - 消息状态
这些响应总是无标签的。消息数据正是这样从服务器传输到客户端,通常作为同名命令的结果。"*" 令牌之后紧跟一个代表消息序列号的数字。
7.4.1 EXPUNGE 响应
Contents: none
EXPUNGE 响应报告指定的消息序列号已永久从邮箱中移除。邮箱中每条后续消息的消息序列号立即递减 1,并且此递减反映在后续响应(包括其他无标签 EXPUNGE 响应)的消息序列号中。
EXPUNGE 响应也会递减邮箱中的消息数量;没有必要发送带有新值的 EXISTS 响应。
由于立即递减规则,出现在一组连续 EXPUNGE 响应中的消息序列号取决于消息是从较低编号到较高编号移除,还是从较高编号到较低编号移除。例如,如果一个 9 消息邮箱的最后 5 条消息被清除,一个"从低到高"的服务器将为消息序列号 5 发送五条无标签 EXPUNGE 响应,而一个"从高到低"的服务器将为消息序列号 9、8、7、6、5 发送连续的无标签 EXPUNGE 响应。
在没有命令执行时,或在应答 FETCH、STORE 或 SEARCH 命令期间,不得发送 EXPUNGE 响应。此规则对于防止客户端与服务器之间消息序列号同步的丢失是必要的。在完整命令被接收之前,命令不处于"执行中";特别地,在命令延续的协商期间,命令不处于"执行中"。
注意:UID FETCH、UID STORE 与 UID SEARCH 是与 FETCH、STORE、SEARCH 不同的命令。在 UID 命令期间可以发送 EXPUNGE 响应。
EXPUNGE 响应的更新必须由客户端记录。
示例:
Example: S: * 44 EXPUNGE
7.4.2 FETCH 响应
Contents: message data
FETCH 响应将数据关于一条消息返回给客户端。数据是括号中数据项名称与其值的成对组合。此响应作为 FETCH 或 STORE 命令的结果出现,也可以由服务器单方面决定(例如,标志更新)。
当前数据项有:
- BODY:一种没有扩展数据的 BODYSTRUCTURE 形式。
- BODY[<section>]<<origin octet>>:表达指定部分主体内容的字符串。客户端应根据内容传输编码、主体类型与子类型来解释该字符串。
- BODYSTRUCTURE:描述消息的 [MIME-IMB] 主体结构的括号列表。这由服务器通过解析 [MIME-IMB] 头字段、按需默认化各字段计算得出。
- ENVELOPE:描述消息信封结构的括号列表。这由服务器通过将 [RFC-2822] 头解析为组成部分、按需默认化各字段计算得出。
- FLAGS:为这条消息设置的标志的括号列表。
- INTERNALDATE:代表消息内部日期的字符串。
- RFC822:等价于 BODY[]。
- RFC822.HEADER:等价于 BODY[HEADER]。
- RFC822.SIZE:表达消息的 [RFC-2822] 大小的数字。
- RFC822.TEXT:等价于 BODY[TEXT]。
- UID:表达消息唯一标识符的数字。
信封结构的字段按以下顺序:date、subject、from、sender、reply-to、to、cc、bcc、in-reply-to 与 message-id。date、subject、in-reply-to 与 message-id 字段是字符串。from、sender、reply-to、to、cc 与 bcc 字段是地址结构的括号列表。
地址结构是一个描述电子邮件地址的括号列表。地址结构的字段按顺序为:personal name、[SMTP] at-domain-list(源路由)、mailbox name 与 host name。
示例:
Example: S: * 23 FETCH (FLAGS (\Seen) RFC822.SIZE 44827)
7.5 服务器响应 - 命令延续请求
命令延续请求响应以 "+" 令牌而非标签来指示。这种形式的响应表示服务器准备好接受来自客户端的命令延续部分。此响应的其余部分是一行文本。
此响应在 AUTHENTICATE 命令中用于向客户端传输服务器数据,并请求附加的客户端数据。如果任何命令的参数是 literal,也使用此响应。
除非服务器指示需要,否则不允许客户端发送 literal 的八位组。这允许服务器逐行处理命令并拒绝错误。命令的其余部分(包括终止命令的 CRLF)跟在 literal 的八位组之后。如果还有任何附加命令参数,literal 八位组后随一个空格与那些参数。
示例:
Example: C: A001 LOGIN {11}
S: + Ready for additional command text
C: FRED FOOBAR {7}
S: + Ready for additional command text
C: fat man
S: A001 OK LOGIN completed
C: A044 BLURDYBLOOP {102856}
S: A044 BAD No such command as "BLURDYBLOOP"
8. IMAP4rev1 连接示例
以下是一个 IMAP4rev1 连接的转录。此示例中的长行为了编辑清晰而被断开。
S: * OK IMAP4rev1 Service Ready
C: a001 login mrc secret
S: a001 OK LOGIN completed
C: a002 select inbox
S: * 18 EXISTS
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S: * 2 RECENT
S: * OK [UNSEEN 17] Message 17 is the first unseen message
S: * OK [UIDVALIDITY 3857529045] UIDs valid
S: a002 OK [READ-WRITE] SELECT completed
C: a003 fetch 12 full
S: * 12 FETCH (FLAGS (\Seen) INTERNALDATE "17-Jul-1996 02:44:25 -0700"
RFC822.SIZE 4286 ENVELOPE ("Wed, 17 Jul 1996 02:23:25 -0700 (PDT)"
"IMAP4rev1 WG mtg summary and minutes"
(("Terry Gray" NIL "gray" "cac.washington.edu"))
(("Terry Gray" NIL "gray" "cac.washington.edu"))
(("Terry Gray" NIL "gray" "cac.washington.edu"))
((NIL NIL "imap" "cac.washington.edu"))
((NIL NIL "minutes" "CNRI.Reston.VA.US")
("John Klensin" NIL "KLENSIN" "MIT.EDU")) NIL NIL
"<B27397-0100000@cac.washington.edu>")
BODY ("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 3028
92))
S: a003 OK FETCH completed
C: a004 fetch 12 body[header]
S: * 12 FETCH (BODY[HEADER] {342}
S: Date: Wed, 17 Jul 1996 02:23:25 -0700 (PDT)
S: From: Terry Gray <gray@cac.washington.edu>
S: Subject: IMAP4rev1 WG mtg summary and minutes
S: To: imap@cac.washington.edu
S: cc: minutes@CNRI.Reston.VA.US, John Klensin <KLENSIN@MIT.EDU>
S: Message-Id: <B27397-0100000@cac.washington.edu>
S: MIME-Version: 1.0
S: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
S:
S: )
S: a004 OK FETCH completed
C: a005 store 12 +flags \deleted
S: * 12 FETCH (FLAGS (\Seen \Deleted))
S: a005 OK +FLAGS completed
C: a006 logout
S: * BYE IMAP4rev1 server terminating connection
S: a006 OK LOGOUT completed
9. 形式文法
以下语法规范使用 [ABNF] 中规定的增强巴科斯-瑙尔范式(ABNF)记号。
在后续规则与较早规则重叠的可选或替代规则的情况下,列出的较早规则必须优先。例如,"\Seen" 在作为 flag 解析时是 \Seen 标志名,而不是 flag-extension,即使 "\Seen" 可以被解析为 flag-extension。此规则的部分(但非全部)实例在下方注明。
注意:[ABNF] 规则必须严格遵循;特别地:
- 除非另有说明,所有字母字符都是大小写不敏感的。使用大写或小写字符来定义令牌字符串仅为编辑清晰;实现必须以大小写不敏感的方式接受这些字符串。
- 在所有情况下,SP 指恰好一个空格。不允许用 TAB 替代、插入额外空格,或将 SP 视为等同于 LWSP。
- ASCII NUL 字符 %x00 在任何时候都不得使用。
以下为 IMAP4rev1 的完整 ABNF(逐字保留):
address = "(" addr-name SP addr-adl SP addr-mailbox SP
addr-host ")"
addr-adl = nstring
; Holds route from [RFC-2822] route-addr if
; non-NIL
addr-host = nstring
; NIL indicates [RFC-2822] group syntax.
; Otherwise, holds [RFC-2822] domain name
addr-mailbox = nstring
; NIL indicates end of [RFC-2822] group; if
; non-NIL and addr-host is NIL, holds
; [RFC-2822] group name.
; Otherwise, holds [RFC-2822] local-part
; after removing [RFC-2822] quoting
addr-name = nstring
; If non-NIL, holds phrase from [RFC-2822]
; mailbox after removing [RFC-2822] quoting
append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP
literal
astring = 1*ASTRING-CHAR / string
ASTRING-CHAR = ATOM-CHAR / resp-specials
atom = 1*ATOM-CHAR
ATOM-CHAR = <any CHAR except atom-specials>
atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards /
quoted-specials / resp-specials
authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64)
auth-type = atom
; Defined by [SASL]
base64 = *(4base64-char) [base64-terminal]
base64-char = ALPHA / DIGIT / "+" / "/"
; Case-sensitive
base64-terminal = (2base64-char "==") / (3base64-char "=")
body = "(" (body-type-1part / body-type-mpart) ")"
body-extension = nstring / number /
"(" body-extension *(SP body-extension) ")"
; Future expansion. Client implementations
; MUST accept body-extension fields. Server
; implementations MUST NOT generate
; body-extension fields except as defined by
; future standard or standards-track
; revisions of this specification.
body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
[SP body-fld-loc *(SP body-extension)]]]
; MUST NOT be returned on non-extensible
; "BODY" fetch
body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang
[SP body-fld-loc *(SP body-extension)]]]
; MUST NOT be returned on non-extensible
; "BODY" fetch
body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP
body-fld-enc SP body-fld-octets
body-fld-desc = nstring
body-fld-dsp = "(" string SP body-fld-param ")" / nil
body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
"QUOTED-PRINTABLE") DQUOTE) / string
body-fld-id = nstring
body-fld-lang = nstring / "(" string *(SP string) ")"
body-fld-loc = nstring
body-fld-lines = number
body-fld-md5 = nstring
body-fld-octets = number
body-fld-param = "(" string SP string *(SP string SP string) ")" / nil
body-type-1part = (body-type-basic / body-type-msg / body-type-text)
[SP body-ext-1part]
body-type-basic = media-basic SP body-fields
; MESSAGE subtype MUST NOT be "RFC822"
body-type-mpart = 1*body SP media-subtype
[SP body-ext-mpart]
body-type-msg = media-message SP body-fields SP envelope
SP body SP body-fld-lines
body-type-text = media-text SP body-fields SP body-fld-lines
capability = ("AUTH=" auth-type) / atom
; New capabilities MUST begin with "X" or be
; registered with IANA as standard or
; standards-track
capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1"
*(SP capability)
; Servers MUST implement the STARTTLS, AUTH=PLAIN,
; and LOGINDISABLED capabilities
; Servers which offer RFC 1730 compatibility MUST
; list "IMAP4" as the first capability.
CHAR8 = %x01-ff
; any OCTET except NUL, %x00
command = tag SP (command-any / command-auth / command-nonauth /
command-select) CRLF
; Modal based on state
command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command
; Valid in all states
command-auth = append / create / delete / examine / list / lsub /
rename / select / status / subscribe / unsubscribe
; Valid only in Authenticated or Selected state
command-nonauth = login / authenticate / "STARTTLS"
; Valid only when in Not Authenticated state
command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store /
uid / search
; Valid only when in Selected state
continue-req = "+" SP (resp-text / base64) CRLF
copy = "COPY" SP sequence-set SP mailbox
create = "CREATE" SP mailbox
; Use of INBOX gives a NO error
date = date-text / DQUOTE date-text DQUOTE
date-day = 1*2DIGIT
; Day of month
date-day-fixed = (SP DIGIT) / 2DIGIT
; Fixed-format version of date-day
date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
"Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
date-text = date-day "-" date-month "-" date-year
date-year = 4DIGIT
date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
SP time SP zone DQUOTE
delete = "DELETE" SP mailbox
; Use of INBOX gives a NO error
digit-nz = %x31-39
; 1-9
envelope = "(" env-date SP env-subject SP env-from SP
env-sender SP env-reply-to SP env-to SP env-cc SP
env-bcc SP env-in-reply-to SP env-message-id ")"
env-bcc = "(" 1*address ")" / nil
env-cc = "(" 1*address ")" / nil
env-date = nstring
env-from = "(" 1*address ")" / nil
env-in-reply-to = nstring
env-message-id = nstring
env-reply-to = "(" 1*address ")" / nil
env-sender = "(" 1*address ")" / nil
env-subject = nstring
env-to = "(" 1*address ")" / nil
examine = "EXAMINE" SP mailbox
fetch = "FETCH" SP sequence-set SP ("ALL" / "FULL" / "FAST" /
fetch-att / "(" fetch-att *(SP fetch-att) ")")
fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
"RFC822" [".HEADER" / ".SIZE" / ".TEXT"] /
"BODY" ["STRUCTURE"] / "UID" /
"BODY" section ["<" number "." nz-number ">"] /
"BODY.PEEK" section ["<" number "." nz-number ">"]
flag = "\Answered" / "\Flagged" / "\Deleted" /
"\Seen" / "\Draft" / flag-keyword / flag-extension
; Does not include "\Recent"
flag-extension = "\" atom
; Future expansion. Client implementations
; MUST accept flag-extension flags. Server
; implementations MUST NOT generate
; flag-extension flags except as defined by
; future standard or standards-track
; revisions of this specification.
flag-fetch = flag / "\Recent"
flag-keyword = atom
flag-list = "(" [flag *(SP flag)] ")"
flag-perm = flag / "\*"
greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF
header-fld-name = astring
header-list = "(" header-fld-name *(SP header-fld-name) ")"
list = "LIST" SP mailbox SP list-mailbox
list-mailbox = 1*list-char / string
list-char = ATOM-CHAR / list-wildcards / resp-specials
list-wildcards = "%" / "*"
literal = "{" number "}" CRLF *CHAR8
; Number represents the number of CHAR8s
login = "LOGIN" SP userid SP password
lsub = "LSUB" SP mailbox SP list-mailbox
mailbox = "INBOX" / astring
; INBOX is case-insensitive. All case variants of
; INBOX (e.g., "iNbOx") MUST be interpreted as INBOX
; not as an astring. An astring which consists of
; the case-insensitive sequence "I" "N" "B" "O" "X"
; is considered to be INBOX and not an astring.
; Refer to section 5.1 for further
; semantic details of mailbox names.
mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list /
"LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) /
"STATUS" SP mailbox SP "(" [status-att-list] ")" /
number SP "EXISTS" / number SP "RECENT"
mailbox-list = "(" [mbx-list-flags] ")" SP
(DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
*(SP mbx-list-oflag) /
mbx-list-oflag *(SP mbx-list-oflag)
mbx-list-oflag = "\Noinferiors" / flag-extension
; Other flags; multiple possible per LIST response
mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked"
; Selectability flags; only one per LIST response
media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" /
"MESSAGE" / "VIDEO") DQUOTE) / string) SP
media-subtype
; Defined in [MIME-IMT]
media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE
; Defined in [MIME-IMT]
media-subtype = string
; Defined in [MIME-IMT]
media-text = DQUOTE "TEXT" DQUOTE SP media-subtype
; Defined in [MIME-IMT]
message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))
msg-att = "(" (msg-att-dynamic / msg-att-static)
*(SP (msg-att-dynamic / msg-att-static)) ")"
msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")"
; MAY change for a message
msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time /
"RFC822" [".HEADER" / ".TEXT"] SP nstring /
"RFC822.SIZE" SP number /
"BODY" ["STRUCTURE"] SP body /
"BODY" section ["<" number ">"] SP nstring /
"UID" SP uniqueid
; MUST NOT change for a message
nil = "NIL"
nstring = string / nil
number = 1*DIGIT
; Unsigned 32-bit integer
; (0 <= n < 4,294,967,296)
nz-number = digit-nz *DIGIT
; Non-zero unsigned 32-bit integer
; (0 < n < 4,294,967,296)
password = astring
quoted = DQUOTE *QUOTED-CHAR DQUOTE
QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
"\" quoted-specials
quoted-specials = DQUOTE / "\"
rename = "RENAME" SP mailbox SP mailbox
; Use of INBOX as a destination gives a NO error
response = *(continue-req / response-data) response-done
response-data = "*" SP (resp-cond-state / resp-cond-bye /
mailbox-data / message-data / capability-data) CRLF
response-done = response-tagged / response-fatal
response-fatal = "*" SP resp-cond-bye CRLF
; Server closes connection immediately
response-tagged = tag SP resp-cond-state CRLF
resp-cond-auth = ("OK" / "PREAUTH") SP resp-text
; Authentication condition
resp-cond-bye = "BYE" SP resp-text
resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text
; Status condition
resp-specials = "]"
resp-text = ["[" resp-text-code "]" SP] text
resp-text-code = "ALERT" /
"BADCHARSET" [SP "(" astring *(SP astring) ")" ] /
capability-data / "PARSE" /
"PERMANENTFLAGS" SP "("
[flag-perm *(SP flag-perm)] ")" /
"READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
"UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number /
"UNSEEN" SP nz-number /
atom [SP 1*<any TEXT-CHAR except "]">]
search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key)
; CHARSET argument to MUST be registered with IANA
search-key = "ALL" / "ANSWERED" / "BCC" SP astring /
"BEFORE" SP date / "BODY" SP astring /
"CC" SP astring / "DELETED" / "FLAGGED" /
"FROM" SP astring / "KEYWORD" SP flag-keyword /
"NEW" / "OLD" / "ON" SP date / "RECENT" / "SEEN" /
"SINCE" SP date / "SUBJECT" SP astring /
"TEXT" SP astring / "TO" SP astring /
"UNANSWERED" / "UNDELETED" / "UNFLAGGED" /
"UNKEYWORD" SP flag-keyword / "UNSEEN" /
; Above this line were in [IMAP2]
"DRAFT" / "HEADER" SP header-fld-name SP astring /
"LARGER" SP number / "NOT" SP search-key /
"OR" SP search-key SP search-key /
"SENTBEFORE" SP date / "SENTON" SP date /
"SENTSINCE" SP date / "SMALLER" SP number /
"UID" SP sequence-set / "UNDRAFT" / sequence-set /
"(" search-key *(SP search-key) ")"
section = "[" [section-spec] "]"
section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list /
"TEXT"
; top-level or MESSAGE/RFC822 part
section-part = nz-number *("." nz-number)
; body part nesting
section-spec = section-msgtext / (section-part ["." section-text])
section-text = section-msgtext / "MIME"
; text other than actual body part (headers, etc.)
select = "SELECT" SP mailbox
seq-number = nz-number / "*"
; message sequence number (COPY, FETCH, STORE
; commands) or unique identifier (UID COPY,
; UID FETCH, UID STORE commands).
; * represents the largest number in use. In
; the case of message sequence numbers, it is
; the number of messages in a non-empty mailbox.
; In the case of unique identifiers, it is the
; unique identifier of the last message in the
; mailbox or, if the mailbox is empty, the
; mailbox's current UIDNEXT value.
; The server should respond with a tagged BAD
; response to a command that uses a message
; sequence number greater than the number of
; messages in the selected mailbox. This
; includes "*" if the selected mailbox is empty.
seq-range = seq-number ":" seq-number
; two seq-number values and all values between
; these two regardless of order.
; Example: 2:4 and 4:2 are equivalent and indicate
; values 2, 3, and 4.
; Example: a unique identifier sequence range of
; 3291:* includes the UID of the last message in
; the mailbox, even if that value is less than 3291.
sequence-set = (seq-number / seq-range) *("," sequence-set)
; set of seq-number values, regardless of order.
; Servers MAY coalesce overlaps and/or execute the
; sequence in any order.
; Example: a message sequence number set of
; 2,4:7,9,12:* for a mailbox with 15 messages is
; equivalent to 2,4,5,6,7,9,12,13,14,15
; Example: a message sequence number set of *:4,5:7
; for a mailbox with 10 messages is equivalent to
; 10,9,8,7,6,5,4,5,6,7 and MAY be reordered and
; overlap coalesced to be 4,5,6,7,8,9,10.
status = "STATUS" SP mailbox SP
"(" status-att *(SP status-att) ")"
status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" /
"UNSEEN"
status-att-list = status-att SP number *(SP status-att SP number)
store = "STORE" SP sequence-set SP store-att-flags
store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP
(flag-list / (flag *(SP flag)))
string = quoted / literal
subscribe = "SUBSCRIBE" SP mailbox
tag = 1*<any ASTRING-CHAR except "+">
text = 1*TEXT-CHAR
TEXT-CHAR = <any CHAR except CR and LF>
time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
; Hours minutes seconds
uid = "UID" SP (copy / fetch / search / store)
; Unique identifiers used instead of message
; sequence numbers
uniqueid = nz-number
; Strictly ascending
unsubscribe = "UNSUBSCRIBE" SP mailbox
userid = astring
x-command = "X" atom <experimental command arguments>
zone = ("+" / "-") 4DIGIT
; Signed four-digit value of hhmm representing
; hours and minutes east of Greenwich (that is,
; the amount that the given time differs from
; Universal Time). Subtracting the timezone
; from the given time will give the UT form.
; The Universal Time zone is "+0000".
10. 作者说明
本文档是对早期文档的修订或重写,并取代这些文档中的协议规范:RFC 2060、RFC 1730、未发布的 IMAP2bis.TXT 文档、RFC 1176 以及 RFC 1064。
11. 安全考量
IMAP4rev1 协议事务(包括电子邮件数据)在网络上以明文形式传输,除非协商了防止窃听的保护措施。这可以通过使用 STARTTLS、在 AUTHENTICATE 命令中协商的隐私保护,或其他某种保护机制来实现。
11.1. STARTTLS 安全考量
本文档中对 STARTTLS 命令与 LOGINDISABLED 能力的规定,取代了 [IMAP-TLS] 中的相应规定。[IMAP-TLS] 对于 PLAIN [SASL] 认证机制仍具有规范性。
IMAP 客户端与服务器实现 MUST 实现 TLS_RSA_WITH_RC4_128_MD5 [TLS] 密码套件,并且 SHOULD 实现 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA [TLS] 密码套件。这一点很重要,因为它保证了任何两个合规实现都可以被配置为互通。所有其他密码套件均为 OPTIONAL。注意,这与 [IMAP-TLS] 第 2.1 节有所不同。
在 [TLS] 协商期间,客户端 MUST 将其理解的服务器主机名与服务器证书消息中所呈现的服务器身份进行比对,以防止中间人攻击。如果比对失败,客户端 SHOULD 要么请求用户显式确认,要么终止连接并指出服务器身份可疑。比对依据以下规则进行:
- 客户端 MUST 使用其用于打开连接的服务器的主机名,作为与服务器证书中所表达服务器名称进行比对的值。客户端 MUST NOT 使用任何源自不安全远程来源(例如不安全的 DNS 查询)的服务器主机名形式。不进行 CNAME 规范化。
- 如果证书中存在 dNSName 类型的 subjectAltName 扩展,则 SHOULD 将其用作服务器身份的来源。
- 比对不区分大小写。
- "*" 通配符 MAY 用作证书中最左侧的名称组成部分。例如,*.example.com 可匹配 a.example.com、foo.example.com 等,但不匹配 example.com。
- 如果证书包含多个名称(例如多个 dNSName 字段),则只要与任意一个字段匹配即视为可接受。
客户端与服务器双方 MUST 检查 STARTTLS 命令的结果以及随后的 [TLS] 协商,以确认是否达成了可接受的认证或隐私保护。
11.2. 其他安全考量
对于因凭据无效而失败的 AUTHENTICATE 命令,服务器的错误消息 SHOULD NOT 详细说明凭据为何无效。
使用 LOGIN 命令会以明文发送密码。这可以通过使用不采用明文密码的 [SASL] 机制的 AUTHENTICATE 命令,或先通过 STARTTLS 或其他保护机制协商加密来避免。
服务器实现 MUST 实现这样一种配置:在认证时要求满足以下之一:
- (1) 已协商 STARTTLS 命令。
- (2) 已提供某种其他可防止会话密码被窃听的机制。
- (3) 已采取以下措施:
- (a) 通告 LOGINDISABLED 能力,且 CAPABILITY 列表中未通告使用明文密码的 [SASL] 机制(例如 PLAIN)。
- (b) 即使密码正确,LOGIN 命令也返回错误。
- (c) 即使密码正确,AUTHENTICATE 命令对使用明文密码的所有 [SASL] 机制都返回错误。
对于失败的 LOGIN 命令,服务器的错误消息 SHOULD NOT 指明是用户名(而非密码)无效。
服务器 SHOULD 具备限制或延迟失败 AUTHENTICATE/LOGIN 尝试的机制。
其他安全考量在讨论 AUTHENTICATE 与 LOGIN 命令的章节中论述。
12. IANA 考量
IMAP4 能力通过发布标准跟踪或 IESG 批准的实验性 RFC 来注册。该注册表当前位于:
http://www.iana.org/assignments/imap4-capabilities
由于本规范修订了此前在 [IMAP-TLS] 中定义的 STARTTLS 与 LOGINDISABLED 扩展,注册表将相应更新。
附录 A. 参考文献
以下文档包含理解本文档所必需的或适宜的定义或规范:
- [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", RFC 2234, November 1997.
- [ANONYMOUS] Newman, C., "Anonymous SASL Mechanism", RFC 2245, November 1997.
- [CHARSET] Freed, N. and J. Postel, "IANA Character Set Registration Procedures", RFC 2978, October 2000.
- [DIGEST-MD5] Leach, P. and C. Newman, "Using Digest Authentication as a SASL Mechanism", RFC 2831, May 2000.
- [DISPOSITION] Troost, R., Dorner, S. and K. Moore, "Communicating Presentation Information in Internet Messages: The Content-Disposition Header", RFC 2183, August 1997.
- [IMAP-TLS] Newman, C., "Using TLS with IMAP, POP3 and ACAP", RFC 2595, June 1999.
- [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
- [LANGUAGE-TAGS] Alvestrand, H., "Tags for the Identification of Languages", BCP 47, RFC 3066, January 2001.
- [LOCATION] Palme, J., Hopmann, A. and N. Shelness, "MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)", RFC 2557, March 1999.
- [MD5] Myers, J. and M. Rose, "The Content-MD5 Header Field", RFC 1864, October 1995.
- [MIME-HDRS] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text", RFC 2047, November 1996.
- [MIME-IMB] Freed, N. and N. Borenstein, "MIME (Multipurpose Internet Mail Extensions) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
- [MIME-IMT] Freed, N. and N. Borenstein, "MIME (Multipurpose Internet Mail Extensions) Part Two: Media Types", RFC 2046, November 1996.
- [RFC-2822] Resnick, P., "Internet Message Format", RFC 2822, April 2001.
- [SASL] Myers, J., "Simple Authentication and Security Layer (SASL)", RFC 2222, October 1997.
- [TLS] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0", RFC 2246, January 1999.
- [UTF-7] Goldsmith, D. and M. Davis, "UTF-7: A Mail-Safe Transformation Format of Unicode", RFC 2152, May 1997.
以下文档描述了实现本协议时应慎重考虑的"实现质量"问题:
- [IMAP-IMPLEMENTATION] Leiba, B., "IMAP Implementation Recommendations", RFC 2683, September 1999.
- [IMAP-MULTIACCESS] Gahrns, M., "IMAP4 Multi-Accessed Mailbox Practice", RFC 2180, July 1997.
A.1 资料性参考文献
以下文档描述了相关协议:
- [IMAP-DISC] Austein, R., "Synchronization Operations for Disconnected IMAP4 Clients", Work in Progress.
- [IMAP-MODEL] Crispin, M., "Distributed Electronic Mail Models in IMAP4", RFC 1733, December 1994.
- [ACAP] Newman, C. and J. Myers, "ACAP -- Application Configuration Access Protocol", RFC 2244, November 1997.
- [SMTP] Klensin, J., "Simple Mail Transfer Protocol", STD 10, RFC 2821, April 2001.
以下文档属于历史性质,或描述本协议的历史方面:
- [IMAP-COMPAT] Crispin, M., "IMAP4 Compatibility with IMAP2bis", RFC 2061, December 1996.
- [IMAP-HISTORICAL] Crispin, M., "IMAP4 Compatibility with IMAP2 and IMAP2bis", RFC 1732, December 1994.
- [IMAP-OBSOLETE] Crispin, M., "Internet Message Access Protocol - Obsolete Syntax", RFC 2062, December 1996.
- [IMAP2] Crispin, M., "Interactive Mail Access Protocol - Version 2", RFC 1176, August 1990.
- [RFC-822] Crocker, D., "Standard for the Format of ARPA Internet Text Messages", STD 11, RFC 822, August 1982.
- [RFC-821] Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC 821, August 1982.
附录 B. 相对 RFC 2060 的变更
- 澄清唯一标识符及其语义的描述。
- 修正 SELECT 描述,澄清在 SELECT 与 EXAMINE 响应中需要 UIDVALIDITY。
- 增加了一次失败搜索的示例。
- 修正 store-att-flags:"#flag" 应为 "1#flag"。
- 使搜索与 section 规则更清晰。
- 修正 STORE 示例。
- 修正 "BASE645" 的拼写错误。
- 在两个部分构成(文本与 BASE64 附件)的示例中去除了多余的右括号。
- 从 mailbox-data 中删除已过时的 "MAILBOX" 响应。
- 删除了 mailbox-data 规则中多余的 "<"。
- 为 continue-req 添加 CRLF。
- 在 resp-text-code 的 atom 中特别排除 "]"。
- 澄清客户端与服务器应严格遵循协议语法。
- 在 5.2 中强调 EXISTS 不能用于收缩邮箱。
- 向 resp-text-code 添加 NEWNAME。
- 澄清作为 LIST 参数的,是空字符串而非 NIL。
- 澄清若邮箱命名空间是扁平的,可以为空字符串邮箱名参数返回 NIL 作为层次分隔符。
- 澄清 addr-mailbox 与 addr-name 去除了 RFC-2822 风格的引号。
- 更新 UTF-7 引用。
- 修正 6.3.11 中的示例。
- 澄清不存在的 UID 会被忽略。
- 更新 DISPOSITION 引用。
- 扩展状态图。
- 澄清部分获取响应仅在响应部分获取命令时返回。
- 添加 UIDNEXT 响应码。修正 UIDVALIDITY 定义的引用。
- 进一步澄清 "can" 与 "MAY" 的区别。
- 引用 RFC-2119。
- 澄清在修改后的 UTF-7 中不允许多余的 shift(移位)。
- 澄清在修改后的 UTF-7 中不存在隐式 shift。
- 澄清邮箱名中的 "INBOX" 始终是 INBOX,即使以字符串形式给出。
- 在 media-basic 文法规则中添加缺失的左括号。
- 修正 mailbox-data 中的属性语法。
- 向 EXAMINE 响应添加 UIDNEXT。
- 澄清 SELECT 与 EXAMINE 中的 UNSEEN、PERMANENTFLAGS、UIDVALIDITY 与 UIDNEXT 响应。它们现在是必需的,但在旧版本中并非如此。
- 以 RFC 编号更新引用。
- 清除 text-mime2。
- 澄清修改后的 UTF-7 名称必须区分大小写,且应避免违反该约定。
- 修正 UID FETCH 示例。
- 澄清 UID FETCH、UID STORE 与 UID SEARCH 同无标签 EXPUNGE 响应的关系。
- 澄清 "convention"(约定)一词的用法。
- 澄清命令在其被完整接收之前不处于"进行中"状态(具体而言,在命令延续协商期间命令不处于"进行中")。
- 澄清信封(envelope)的默认值。
- 澄清 SP 表示且仅表示一个空格字符。
- 禁止 LIST 响应中出现无意义的状态。
- 澄清一条消息的 ENVELOPE、INTERNALDATE、RFC822*、BODY* 与 UID 是静态的。
- 添加 BADCHARSET 响应码。
- 根据 [ABNF] 约定更新形式语法。
- 澄清 CREATE 语义中尾随的层次分隔符。
- 澄清"空行"是指 [RFC-2822] 中定界的空行。
- 澄清 RENAME 还应按需为命令完成创建层次结构。
- 修正 body-ext-mpart,使其在存在 disposition 时不要求 language。
- 澄清 RFC822.HEADER 响应。
- 修正搜索中 charset astring 后缺失的空格。
- 修正 resp-text-code 中 BADCHARSET 缺失的引号。
- 澄清 ALL、FAST 与 FULL 排除了任何其他数据项的出现。
- 澄清 LIST 中 reference 参数的语义。
- 澄清搜索 HEADER X-FOO 的空字符串意味着任何具有字段名为 X-FOO 的头行的消息,不论头的内容如何。
- 明确为未来用作 UTF-8 而保留 8 位邮箱名。
- 客户端存储不在 PERMANENTFLAGS 列表中的标志并不算错误;但服务器将忽略该变更,或仅在会话内做出变更。
- 修正/澄清关于多余 shift 的文本。
- 修正"变更"章节中的印刷错误。
- 澄清 STATUS 不得用于检查选中邮箱中的新消息。
- 澄清 LSUB 在 "%" 通配符下的行为。
- 在 7.5 节中将 AUTHORIZATION 改为 AUTHENTICATE。
- 澄清 multipart 主体类型的描述。
- 澄清 STORE FLAGS 不影响 \Recent。
- 在时区描述中将 "west" 改为 "east"。
- 澄清破坏命令流水线(pipelining)的命令必须等待完成结果响应。
- 澄清 EXAMINE 不影响 \Recent。
- 使 MIME 结构的描述保持一致。
- 澄清日期搜索忽略 INTERNALDATE 或 Date: 头的时间与时区。换言之,"ON 13-APR-2000" 表示 INTERNALDATE 文本以 "13-APR-2000" 开头的消息,即使与本地时区的时差足以将该 INTERNALDATE 推到前一天或后一天。
- 澄清头获取若 [RFC-2822] 消息中没有空行,则不会添加空行。
- 澄清(在 UIDs 的讨论中)消息是不可变的。
- 增加 CHARSET 搜索的示例。
- 在 SEARCH 中澄清关键词是一种标志。
- 澄清 SELECT 数据响应的强制性。
- 在初始 OK 或 PREAUTH 中添加可选的 CAPABILITY 响应码。
- 增加说明:服务器可发送无标签 CAPABILITY 命令,作为 AUTHENTICATE 与 LOGIN 响应的一部分。
- 删除关于"在一条连接中无需多次发出 CAPABILITY 命令"的声明。该声明已不再成立。
- 澄清无标签 EXPUNGE 会使邮箱中的消息数递减。
- 修正 "body" 的定义(连接的结合性强于选择)。
- 添加"实现者特别注意事项"新章节,并引用 [IMAP-IMPLEMENTATION]。
- 澄清对 AUTHENTICATE 命令的无标签 CAPABILITY 响应,仅应在未协商安全层时才进行。
- 更改 atom 的定义以排除 "]"。更新 astring 以包含 "]" 以兼容过去。删除 resp-text-atom。
- 删除 NEWNAME。它无法工作,因为邮箱名可以是字面量且可包含 "]"。其功能可通过转介(referrals)实现。
- 移动修改后的 UTF-7 说明,以获得更符合逻辑的段落流。
- 用 MUST 明确 UID 唯一性的保证。
- 指出客户端应读取响应数据直至连接关闭,而非在收到 BYE 时立即关闭。
- 将 RFC-822 引用改为 RFC-2822。
- 澄清应当遵循 RFC-2822 而非 RFC-822。
- 将 LOGIN 与 AUTHENTICATE 中可选自动能力的建议,改为在带标签的 OK 中使用 CAPABILITY 响应码。这比无 solicited 的无标签 CAPABILITY 响应更具互操作性。
- STARTTLS 与 AUTH=PLAIN 为强制实现;增加对其它 [SASL] 机制的建议。
- 澄清"连接"(相对于"服务器"或"命令")处于四种状态之一。
- 澄清失败或被拒绝的命令不改变状态。
- 将引用分为规范性与资料性两类。
- 在安全章节中讨论认证失败问题。
- 澄清数据项不一定仅属于单一数据类型。
- 澄清序列范围独立于顺序。
- 更改一例以澄清修改后的 UTF-7 中多余的 shift 不能仅通过省略移位来修复。必须重新计算整个字符串。
- 更改信封结构定义,因为 [RFC-2822] 使用 "envelope" 指代 [SMTP] 信封,而非出现在 [RFC-2822] 头中的信封数据。
- 扩展 RFC822.HEADER 响应数据相对于 BODY[HEADER] 的内容。
- 澄清 Logout 状态语义,更改 ASCII 图。
- 为符合 IESG 要求而进行的安全变更。
- 添加 body URI 的定义。
- 将序列范围定义拆分为三个规则,并为每个重写描述。
- 将 STARTTLS 与 LOGINDISABLED 从 [IMAP-TLS] 移至此处。
- 添加 IANA 考量章节。
- 澄清客户端对于新消息 UID 相对于 UIDNEXT 的有效假设。
- 澄清对 permanentflags 的更改同时影响并发会话与后续会话。
- 澄清认证状态可由 CLOSE 命令进入。
- 强调 SELECT 与 EXAMINE 是"失败命令不改变状态"这一规则的例外。
- 澄清新追加的消息带有 Recent 标志。
- 澄清新复制的消息 SHOULD 带有 Recent 标志。
- 澄清 UID 命令总是在 FETCH 响应中返回 UID。
附录 C. 关键词索引
+FLAGS <flag list>(store 命令数据项)— 第 59 页+FLAGS.SILENT <flag list>(store 命令数据项)— 第 59 页-FLAGS <flag list>(store 命令数据项)— 第 59 页-FLAGS.SILENT <flag list>(store 命令数据项)— 第 59 页ALERT(响应码)— 第 64 页ALL(获取项)— 第 55 页ALL(搜索键)— 第 50 页ANSWERED(搜索键)— 第 50 页APPEND(命令)— 第 45 页AUTHENTICATE(命令)— 第 27 页BAD(响应)— 第 66 页BADCHARSET(响应码)— 第 64 页BCC <string>(搜索键)— 第 51 页BEFORE <date>(搜索键)— 第 51 页BODY(获取项)— 第 55 页BODY(获取结果)— 第 73 页BODY <string>(搜索键)— 第 51 页BODY.PEEK[<section>]<<partial>>(获取项)— 第 57 页BODYSTRUCTURE(获取项)— 第 57 页BODYSTRUCTURE(获取结果)— 第 74 页BODY[<section>]<<origin octet>>(获取结果)— 第 74 页BODY[<section>]<<partial>>(获取项)— 第 55 页BYE(响应)— 第 67 页- Body Structure(消息属性)— 第 12 页
CAPABILITY(命令)— 第 24 页CAPABILITY(响应码)— 第 64 页CAPABILITY(响应)— 第 68 页CC <string>(搜索键)— 第 51 页CHECK(命令)— 第 47 页CLOSE(命令)— 第 48 页COPY(命令)— 第 59 页CREATE(命令)— 第 34 页DELETE(命令)— 第 35 页DELETED(搜索键)— 第 51 页DRAFT(搜索键)— 第 51 页ENVELOPE(获取项)— 第 57 页ENVELOPE(获取结果)— 第 77 页EXAMINE(命令)— 第 33 页EXISTS(响应)— 第 71 页EXPUNGE(命令)— 第 48 页EXPUNGE(响应)— 第 72 页- Envelope Structure(消息属性)— 第 12 页
FAST(获取项)— 第 55 页FETCH(命令)— 第 54 页FETCH(响应)— 第 73 页FLAGGED(搜索键)— 第 51 页FLAGS(获取项)— 第 57 页FLAGS(获取结果)— 第 78 页FLAGS(响应)— 第 71 页FLAGS <flag list>(store 命令数据项)— 第 59 页FLAGS.SILENT <flag list>(store 命令数据项)— 第 59 页FROM <string>(搜索键)— 第 51 页FULL(获取项)— 第 55 页- Flags(消息属性)— 第 11 页
HEADER(部分说明符)— 第 55 页HEADER <field-name> <string>(搜索键)— 第 51 页HEADER.FIELDS <header-list>(部分说明符)— 第 55 页HEADER.FIELDS.NOT <header-list>(部分说明符)— 第 55 页INTERNALDATE(获取项)— 第 57 页INTERNALDATE(获取结果)— 第 78 页- Internal Date(消息属性)— 第 12 页
KEYWORD <flag>(搜索键)— 第 51 页- Keyword(标志类型)— 第 11 页
LARGER <n>(搜索键)— 第 51 页LIST(命令)— 第 40 页LIST(响应)— 第 69 页LOGIN(命令)— 第 30 页LOGOUT(命令)— 第 25 页LSUB(命令)— 第 43 页LSUB(响应)— 第 70 页MAY(规范要求术语)— 第 4 页MESSAGES(状态项)— 第 45 页MIME(部分说明符)— 第 56 页MUST(规范要求术语)— 第 4 页MUST NOT(规范要求术语)— 第 4 页- Message Sequence Number(消息属性)— 第 10 页
NEW(搜索键)— 第 51 页NO(响应)— 第 66 页NOOP(命令)— 第 25 页NOT <search-key>(搜索键)— 第 52 页OK(响应)— 第 65 页OLD(搜索键)— 第 52 页ON <date>(搜索键)— 第 52 页OPTIONAL(规范要求术语)— 第 4 页OR <search-key1> <search-key2>(搜索键)— 第 52 页PARSE(响应码)— 第 64 页PERMANENTFLAGS(响应码)— 第 64 页PREAUTH(响应)— 第 67 页- Permanent Flag(标志类别)— 第 12 页
READ-ONLY(响应码)— 第 65 页READ-WRITE(响应码)— 第 65 页RECENT(响应)— 第 72 页RECENT(搜索键)— 第 52 页RECENT(状态项)— 第 45 页RENAME(命令)— 第 37 页REQUIRED(规范要求术语)— 第 4 页RFC822(获取项)— 第 57 页RFC822(获取结果)— 第 78 页RFC822.HEADER(获取项)— 第 57 页RFC822.HEADER(获取结果)— 第 78 页RFC822.SIZE(获取项)— 第 57 页RFC822.SIZE(获取结果)— 第 78 页RFC822.TEXT(获取项)— 第 58 页RFC822.TEXT(获取结果)— 第 79 页SEARCH(命令)— 第 49 页SEARCH(响应)— 第 71 页SEEN(搜索键)— 第 52 页SELECT(命令)— 第 31 页SENTBEFORE <date>(搜索键)— 第 52 页SENTON <date>(搜索键)— 第 52 页SENTSINCE <date>(搜索键)— 第 52 页SHOULD(规范要求术语)— 第 4 页SHOULD NOT(规范要求术语)— 第 4 页SINCE <date>(搜索键)— 第 52 页SMALLER <n>(搜索键)— 第 52 页STARTTLS(命令)— 第 27 页STATUS(命令)— 第 44 页STATUS(响应)— 第 70 页STORE(命令)— 第 58 页SUBJECT <string>(搜索键)— 第 53 页SUBSCRIBE(命令)— 第 38 页- Session Flag(标志类别)— 第 12 页
- System Flag(标志类型)— 第 11 页
TEXT(部分说明符)— 第 56 页TEXT <string>(搜索键)— 第 53 页TO <string>(搜索键)— 第 53 页TRYCREATE(响应码)— 第 65 页UID(命令)— 第 60 页UID(获取项)— 第 58 页UID(获取结果)— 第 79 页UID <sequence set>(搜索键)— 第 53 页UIDNEXT(响应码)— 第 65 页UIDNEXT(状态项)— 第 45 页UIDVALIDITY(响应码)— 第 65 页UIDVALIDITY(状态项)— 第 45 页UNANSWERED(搜索键)— 第 53 页UNDELETED(搜索键)— 第 53 页UNDRAFT(搜索键)— 第 53 页UNFLAGGED(搜索键)— 第 53 页UNKEYWORD <flag>(搜索键)— 第 53 页UNSEEN(响应码)— 第 65 页UNSEEN(搜索键)— 第 53 页UNSEEN(状态项)— 第 45 页UNSUBSCRIBE(命令)— 第 39 页- Unique Identifier (UID)(消息属性)— 第 8 页
X<atom>(命令)— 第 62 页[RFC-2822] Size(消息属性)— 第 12 页\Answered(系统标志)— 第 11 页\Deleted(系统标志)— 第 11 页\Draft(系统标志)— 第 11 页\Flagged(系统标志)— 第 11 页\Marked(邮箱名属性)— 第 69 页\Noinferiors(邮箱名属性)— 第 69 页\Noselect(邮箱名属性)— 第 69 页\Recent(系统标志)— 第 11 页\Seen(系统标志)— 第 11 页\Unmarked(邮箱名属性)— 第 69 页
作者地址
Mark R. Crispin
Networks and Distributed Computing
University of Washington
4545 15th Avenue NE
Seattle, WA 98105-4527
电话: (206) 543-5762
电子邮件: MRC@CAC.Washington.EDU
完整版权声明
Copyright (C) The Internet Society (2003)。保留所有权利。
本文档及其译本可被复制并提供给他人,还可准备、复制、发布并分发对其评论或以其他方式解释、或有助于其实现的衍生作品,全部或部分均可,且不受任何限制,前提是上述版权声明与本段文字包含在所有此类副本与衍生作品之中。然而,本文档本身不得以任何方式修改,例如移除版权声明或对互联网协会及其他互联网组织的引用,除非为制定互联网标准所需(此时须遵循互联网标准流程中定义的版权程序),或为将其翻译为英语以外的语言所需。
上述授予的有限许可是永久性的,不会被互联网协会或其继承者或受让者撤销。本文档及其中包含的信息按"原样"(AS IS)提供,互联网协会与互联网工程任务组声明放弃所有明示或暗示的担保,包括但不限于任何关于使用本文档信息不会侵犯任何权利的担保,或任何关于适销性、特定用途适用性的暗示担保。
致谢
互联网协会目前为 RFC 编辑职能提供资金。
