2. 协议概览 (Protocol Overview)
2.1. 链路层级 (Link Level)
IMAP4rev1 协议假定使用可靠的数据流, 例如 TCP 提供的数据流. 使用 TCP 时, IMAP4rev1 服务器监听端口 143.
2.2. 命令和响应 (Commands and Responses)
IMAP4rev1 连接由客户端/服务器网络连接的建立, 服务器的初始问候, 以及客户端/服务器交互组成. 这些客户端/服务器交互由客户端命令, 服务器数据, 以及服务器完成结果响应组成.
客户端和服务器传输的所有交互都采用行的形式, 即以 CRLF 结尾的字符串. IMAP4rev1 客户端或服务器的协议接收器要么读取一行, 要么读取一个已知计数的八位组序列, 随后再读取一行.
2.2.1. 客户端协议发送器和服务器协议接收器 (Client Protocol Sender and Server Protocol Receiver)
客户端命令启动一项操作. 每个客户端命令前都有一个称为 "tag" 的标识符 (通常是短的字母数字字符串, 例如 A0001, A0002 等). 客户端为每个命令生成不同的 tag.
客户端 MUST 严格遵循本规范中给出的语法. 发送缺少空格或参数, 或带有多余空格或参数的命令是语法错误.
在两种情况下, 客户端发送的一行并不表示完整命令. 一种情况是命令参数使用八位组计数进行引用 (见 Data Formats 中 String 下对 literal 的描述); 另一种情况是命令参数需要服务器反馈 (见 AUTHENTICATE 命令). 在任一情况下, 如果服务器已准备好接收八位组 (如适用) 和命令剩余部分, 它会发送命令续行请求响应. 该响应以前缀 token "+" 开始.
RFC 3501 IMAPv4 March 2003
注意: 如果服务器反而检测到命令中存在错误, 它会发送一个与该命令 tag 匹配的 BAD 完成响应 (如下所述), 以拒绝该命令并阻止客户端继续发送该命令的更多内容.
服务器也可能为其它某个命令发送完成响应 (如果有多个命令正在进行), 或发送未标记数据. 在任一情况下, 命令续行请求仍处于挂起状态; 客户端针对该响应采取适当动作, 然后从服务器读取另一个响应. 在所有情况下, 客户端 MUST 在发起新命令之前发送完整命令 (包括接收该命令的所有命令续行请求响应和发送该命令的所有命令续行).
IMAP4rev1 服务器的协议接收器从客户端读取命令行, 解析命令及其参数, 并传输服务器数据和服务器命令完成结果响应.
2.2.2. 服务器协议发送器和客户端协议接收器 (Server Protocol Sender and Client Protocol Receiver)
服务器发送给客户端的数据, 以及不表示命令完成的状态响应, 都以前缀 token "*" 开始, 并称为 untagged response (未标记响应).
服务器数据 MAY 作为客户端命令的结果发送, 也 MAY 由服务器单方面发送. 由特定命令产生的服务器数据与服务器单方面发送的数据之间没有语法差异.
服务器完成结果响应表示操作成功或失败. 它带有与启动该操作的客户端命令相同的 tag.因此, 如果有多个命令正在进行, 服务器完成响应中的 tag 标识该响应适用于哪个命令. 服务器完成响应有三种可能形式: OK (表示成功), NO (表示失败), 或 BAD (表示协议错误, 例如无法识别的命令或命令语法错误).
服务器 SHOULD 严格执行本规范中给出的语法. 任何带有协议语法错误的客户端命令, 包括但不限于缺少空格或参数, 或带有多余空格或参数,
RFC 3501 IMAPv4 March 2003
SHOULD 被拒绝, 并且客户端应收到 BAD 服务器完成响应.
IMAP4rev1 客户端的协议接收器从服务器读取一行响应. 随后它根据响应的第一个 token 对该响应采取动作; 该 token 可以是 tag, "*", 或 "+".
客户端 MUST 随时准备接受任何服务器响应. 这包括未被请求的服务器数据. 服务器数据 SHOULD 被记录, 以便客户端能够引用其记录副本, 而不是向服务器发送命令来请求该数据. 对于某些服务器数据, 数据 MUST 被记录.
该主题在 Server Responses 章节中有更详细的讨论.
2.3. 消息属性 (Message Attributes)
除消息文本外, 每条消息还关联若干属性. 这些属性可以单独检索, 也可以与其它属性或消息文本一起检索.
2.3.1. 消息编号 (Message Numbers)
IMAP4rev1 中的消息通过两种编号之一访问: unique identifier (唯一标识符) 或 message sequence number (消息序列号).
2.3.1.1. 唯一标识符 (UID) 消息属性 (Unique Identifier (UID) Message Attribute)
分配给每条消息的 32-bit 值. 该值与 unique identifier validity value (唯一标识符有效性值, 见下文) 一起使用时形成一个 64-bit 值, 该值 MUST NOT 在当前 mailbox 或今后任何同名 mailbox 中指代任何其它消息. 唯一标识符在 mailbox 中严格按升序分配; 每当向 mailbox 添加一条消息时, 该消息会被分配一个比此前添加的消息更高的 UID.与消息序列号不同, 唯一标识符不一定连续.
消息的唯一标识符 MUST NOT 在 session 期间改变, 并且 SHOULD NOT 在 session 之间改变. session 之间唯一标识符的任何变化 MUST 能够通过下文讨论的 UIDVALIDITY 机制检测到. 客户端需要持久唯一标识符, 才能把它以前 session 的状态与服务器重新同步 (例如断开连接或离线访问客户端); [IMAP-DISC] 对此有进一步讨论.
RFC 3501 IMAPv4 March 2003
每个 mailbox 都关联两个有助于处理唯一标识符的值: next unique identifier value (下一个唯一标识符值) 和 unique identifier validity value (唯一标识符有效性值).
下一个唯一标识符值是预测将分配给 mailbox 中新消息的值. 除非唯一标识符有效性值也发生变化 (见下文), 下一个唯一标识符值 MUST 具有以下两个特征. 第一, 除非向 mailbox 添加新消息, 下一个唯一标识符值 MUST NOT 改变; 第二, 只要向 mailbox 添加新消息, 下一个唯一标识符值 MUST 改变, 即使这些新消息随后被 expunged.
注意: 下一个唯一标识符值旨在为客户端提供一种方法, 用于判断自它上次检查此值以来是否已有消息投递到该 mailbox.它并不旨在保证任何消息一定具有该唯一标识符. 客户端只能在取得下一个唯一标识符值时假定, 此后到达的消息会具有大于或等于该值的 UID.
唯一标识符有效性值在 mailbox 选择时通过 OK untagged response 中的 UIDVALIDITY response code 发送. 如果早期 session 中的唯一标识符未能在本 session 中保持持久, 则唯一标识符有效性值 MUST 大于早期 session 中使用的值.
注意: 理想情况下, 唯一标识符 SHOULD 始终保持持久. 尽管本规范承认在某些服务器环境中无法保持持久可能不可避免, 但它 STRONGLY ENCOURAGES 采用避免该问题的消息存储实现技术. 例如:
-
唯一标识符 MUST 在 mailbox 中始终严格递增. 如果物理消息存储被非 IMAP agent 重新排序, 则需要重新生成 mailbox 中的唯一标识符, 因为重排后原来的唯一标识符不再严格递增.
-
如果消息存储没有存储唯一标识符的机制, 它必须在每个 session 中重新生成唯一标识符, 并且每个 session 必须具有唯一的 UIDVALIDITY 值.
RFC 3501 IMAPv4 March 2003
-
如果 mailbox 被删除, 并在以后创建了同名新 mailbox, 服务器必须跟踪该 mailbox 先前实例中的唯一标识符, 或者必须为该 mailbox 的新实例分配新的 UIDVALIDITY 值. 在这种情况下, 一个好的 UIDVALIDITY 值是 mailbox 创建日期/时间的 32-bit 表示. 可以使用诸如 1 这样的常量, 但前提是保证唯一标识符永远不会被重用, 即使 mailbox 被删除 (或重命名), 并且将来创建了同名的新 mailbox.
-
mailbox 名称, UIDVALIDITY 和 UID 的组合必须在该服务器上永远指向单个不可变消息. 特别是, internal date, [RFC-2822] size, envelope, body structure, 以及 message texts (RFC822, RFC822.HEADER, RFC822.TEXT 和所有 BODY[...] fetch data items) 都绝不能改变. 这不包括消息编号, 也不包括可由 STORE 命令设置的属性 (例如 FLAGS).
2.3.1.2. 消息序列号消息属性 (Message Sequence Number Message Attribute)
从 1 到 mailbox 中消息数量的相对位置. 该位置 MUST 按唯一标识符升序排列. 每添加一条新消息时, 它会被分配一个消息序列号, 该序列号比添加该新消息之前 mailbox 中的消息数量大 1.
消息序列号可以在 session 期间重新分配. 例如, 当一条消息从 mailbox 中永久移除 (expunged) 时, 所有后续消息的消息序列号都会减 1.mailbox 中的消息数量也会减 1.类似地, 新消息可以被分配一个在某次 expunge 之前曾由其它某条消息持有的消息序列号.
除按 mailbox 中的相对位置访问消息外, 消息序列号还可用于数学计算. 例如, 如果收到 untagged "11 EXISTS", 且此前收到过 untagged "8 EXISTS", 则已有三条新消息到达, 其消息序列号为 9, 10 和 11.再举一例, 如果一个含有 523 条消息的 mailbox 中第 287 条消息的 UID 为 12345, 则恰好有 286 条消息的 UID 更小, 有 236 条消息的 UID 更大.
RFC 3501 IMAPv4 March 2003
2.3.2. flags 消息属性 (Flags Message Attribute)
与消息关联的零个或多个命名 token 列表. 将 flag 加入此列表即设置该 flag, 从列表中移除即清除该 flag.IMAP4rev1 中有两类 flags.任一类型的 flag 都可以是 permanent 或 session-only.
system flag 是本规范预定义的 flag 名称. 所有 system flags 都以 "" 开头. 某些 system flags (\Deleted 和 \Seen) 具有其它位置描述的特殊语义. 目前定义的 system flags 为:
\Seen
消息已读
\Answered
消息已回复
\Flagged
消息被 "flagged", 表示需要紧急/特殊关注
\Deleted
消息被 "deleted", 等待后续 EXPUNGE 移除
\Draft
消息尚未完成撰写 (标记为草稿).
\Recent
消息是 "recently" 到达该 mailbox 的. 本 session 是第一个收到关于该消息通知的 session; 如果该 session 是 read-write, 后续 session 将不会看到该消息设置了 \Recent.客户端不能修改此 flag.
如果无法确定本 session 是否是第一个收到某条消息通知的 session, 则该消息 SHOULD 被视为 recent.
如果多个连接同时选择了同一 mailbox, 则未定义这些连接中哪些会看到新到达消息带有 \Recent, 哪些会看到不带 \Recent.
keyword 由服务器实现定义. Keywords 不以 "" 开头. 服务器 MAY 允许客户端在 mailbox 中定义新 keywords (更多信息见 PERMANENTFLAGS response code 的描述).
RFC 3501 IMAPv4 March 2003
flag 可以按每个 flag 分别是 permanent 或 session-only.Permanent flags 是客户端可以永久加入消息 flags 或从中移除的 flags; 也就是说, 并发 session 和后续 session 都会看到 permanent flags 的任何变化. 对 session flags 的更改仅在该 session 中有效.
注意: \Recent system flag 是 session flag 的一种特殊情况. \Recent 不能作为 STORE 或 APPEND 命令的参数使用, 因此根本不能被更改.
2.3.3. 内部日期消息属性 (Internal Date Message Attribute)
消息在服务器上的内部日期和时间. 这不是 [RFC-2822] header 中的日期和时间, 而是反映消息接收时间的日期和时间. 对于通过 [SMTP] 投递的消息, 这 SHOULD 是 [SMTP] 定义的消息最终投递日期和时间. 对于通过 IMAP4rev1 COPY 命令投递的消息, 这 SHOULD 是源消息的内部日期和时间. 对于通过 IMAP4rev1 APPEND 命令投递的消息, 这 SHOULD 是 APPEND 命令描述中指定的日期和时间. 所有其它情况由实现定义.
2.3.4. [RFC-2822] 大小消息属性 ([RFC-2822] Size Message Attribute)
消息中的八位组数量, 以 [RFC-2822] 格式表示.
2.3.5. 信封结构消息属性 (Envelope Structure Message Attribute)
消息 [RFC-2822] header 的解析表示. 注意, IMAP Envelope 结构不同于 [SMTP] envelope.
2.3.6. 正文结构消息属性 (Body Structure Message Attribute)
[MIME-IMB] body structure 信息的解析表示.
RFC 3501 IMAPv4 March 2003
2.4. 消息文本 (Message Texts)
除了能够 fetch 消息的完整 [RFC-2822] 文本外, IMAP4rev1 还允许 fetch 完整消息文本的各个部分. 具体而言, 可以 fetch [RFC-2822] message header, [RFC-2822] message body, [MIME-IMB] body part, 或 [MIME-IMB] header.