RFC3501(imp4协议)中文版

因特网邮件访问协议,版本4rev1(IMAP4rev1)允许一个客户端访问和操作在一个服务器上的电子邮件。IMAP4rev1允许,以一 种功能上等效于本地文件夹的方式,操作邮箱(远程邮件文件夹)。IMAP4rev1也提供这样一个功能,一个离线客户端与服务器异步(交互)。
IMAP4rev1包括以下操作:创建、删除、及重命名邮箱,检查新邮件,永久删除邮件,设置和清除标记,RFC2822及RFC2045解 析,检索,及选择性的获取邮件属性,文本,及其中的一部分。IMAP4rev1中的邮件通过使用数字访问。这些数字或者是邮件序列号,或者是唯一标识符。
IMAP4rev1支持单个服务器。访问注册信息以支持多个IMAP4rev1服务器的机制在RFC2244中讨论。
IMAP4rev1不详述邮递邮件的方法;该职责由如RFC2821的某种邮件传输协议完成。
目录
IMAP4rev1协议规范

1. 如何阅读本文

1.1. 本文的结构

本文是基于一个IMAP4rev1客户端或者服务器的视点写的。第2章超出了本协议的范畴,对某些人而言,试图理解本协议的操作是不现实的。第3到第5章提供了IMAP4rev1操作的总体脉络和概念。
第6、7、9章分别描述了IMAP的命令、响应和语法。三者之间的联系如此紧密,甚至于我们几乎不可能独立地理解它们。特别的,不要试图单单从命令块推论命令语法,相反的,要参考正式语法。

1.2 本文用到的约定语

约定语用来描述基本的原理或者过程。本节将列出本文档的约定语。
例如,“C:”和“S:”分别表示由客户端和服务器发出的信息行。
“MUST”、“MUST  NOT”、“REQUIRE”、“SHALL”、“SHALL  NOT”、“SHOULD”、“SHOULD  NOT”、“MAY”,及“OPTIONAL”这些基本的词,在本文中解释为[关键词]。
“can”(或者“may”)用来指出某种可能情况和条件,而不是该协议的任意一种功能。
“User”用来表示一个自然人,而“client”则用来表示用户运行的软件。
“Connection”表示从网络连接初始建立直至其结束的过程中,客户端、服务器间的整个、一连串的交互。
“Session”表示从选中一个邮箱(SELECT或者EXAMINE命令)直至选中结束(CLOSE命令,或者连接终止,另一个邮箱的SELECT或者EXAMINE命令)的过程中,客户端、服务器间的一连串交互。
没有特别说明时,字符串当作7位的US-ASCII处理。其它的字符集用“CHARSET”标识,与[MIME-IMT]中描述的、[CHARSET]中定义的是一样的。除了定义字符集,CHARSETs还有其它重要的语义,更多细节参考相关文档。
IMAP中有一些协议约定语。它们涉及到协议说明的某些方面,严格讲,这些方面不属于IMAP协议的部分,但是它们反映了被普遍认可的实践经 验。协议的实现体需要考虑这些约定语,并避免冲突,不管实现这些约定语与否。例如,“&”不应该用作等级定义符――因为这与邮箱的网络命名约定冲 突,而邮箱名称中“&”的其它使用则无碍。

1.3. 实现者需要特别注意的地方

强烈建议IMAP协议的实现者阅读与本文相关的[IMAP实现]的推荐文章,以利于理解这个协议的难点,及如何最好地创建一个有效沟通的产品。
IMAP4rev1设计成从[IMAP2]和未发布的IMAP2bis协议向上兼容。IMAP4rev1很好地兼容了RFC1730中描述的 IMAP4协议;RFC1730中增加的、有异常的、被证实有问题的那些功能后来被删减了。在IMAP4rev1的发展历程中,早期的协议中某些方面遭到 了废弃。[IMAP-OBSOLETE]中,描述了IMAP4rev1实现者使用早期的协议实现时,可能遇到的、废弃了的命令、响应及数据格式。
[IMAP-COMPAT]讨论了与IMAP2bis的其它兼容问题,与早期的协议的最一般性的差异。[IMAP-HISTORICAL]全面讨论了与[IMAP2]因罕见(被擅自主张者去除了)差异而产生的兼容问题;本文是历史关注的源头。
IMAP起初是为旧的[RFC-822]标准发展的,因此一些项目在它们的名称中把“RFC822”包含进来。除了RFC822.SIZE,还 有更先进的取代;例如,  RFC822.HEADER在新版中是BODY.PEEK[HEADER]。在所有案例中,“RFC822”应该解释为升级的 [RFC-822]标准的参考。

2. 协议概述

2.1. 链路层

IMAP4rev1协议假定了类似TCP提供的可靠数据流。使用TCP时,IMAP4rev1服务器监听143端口。

2.2. 命令及响应

一次IMAP4rev1连接的组成有:一次客户端、服务器的网络连接的建立,服务器的初始欢迎,以及客户端、服务器的交互。这些客户端、服务器的交互由客户端命令、服务器数据和服务器的完成结果响应组成。
传送于客户端和服务器间的所有交互都是以行的形式,即,以一个CRLF为结束标志的字符串。一个IMAP4rev1客户端或者服务器的协议接收端要么是按行读取,要么是以一个已知的数值n,每次读取n个字节的串。

2.2.1. 客户端的协议发送和服务器端的协议接收

客户端命令引发操作。每个客户端命令以一个标识作为前缀(典型的有字母、数字构成的短字符串,如:A0001,A0002,等等)――它称为“标签”。客户端为每个命令生成不同的“标签”。
客户端必须严格遵守本说明中的语法大纲。发送缺损的命令,或者多余的空格、变量都属于语法错误。
客户端没有描述一个完整的命令,有两种情形。一种是,一个命令参数被以一个字节数引用(参看Data  Formats下的String的原义描 述);另一种是,命令参数要求服务器的反馈(参看AUTHENTICATE命令)。这再者中的任何一种情形下,服务器发送命令以不停地请求响应――如果为 字节串(如果适当)和剩余命令准备就绪。响应用“+”作为前缀。
注意:而如果服务器发现命令的一个错误,它就发送一个带有匹配于命令(如下所描述的)的标签的BAD完整响应,以拒绝该命令,避免客户端再发送更多的命令。
服务器对一些其它的命令(如果多个命令相继发生)、或者非标签化的数据,请求发送完整的响应,这也是可能的。在两者中的任何一种情形下,连续的 请求命令仍然是悬而不决的;客户端对响应采取相应的动作,并读取服务器的其它响应。所有情形下,客户端必须在初始化一个新的命令前发送一个完整命令(包括 接收所有连续请求响应命令)
IMAP4rev1服务器端的协议接收端,从客户端读取命令行,解析该命令行及其参数,并传送服务器数据及一个服务器命令完成结果的响应。

2.2.2. 服务器端的协议发送和客户端的协议接收

那些没有标识命令完成的、被服务器传送至客户端的数据和状态响应,用“*”作为前缀,并称为非标签化的响应。
服务器数据可能被作为客户端命令的结果发送,或者可能被服务器单方面发送。源于特定命令的服务器数据,和单方面发送的服务器数据,二者之间没有语法上的差异。
服务器完成结果响应表示操作的成功或者失败。它具有与开始操作的客户端命令一样的标签。然而,如果有多于一个的命令在行进中,服务器完成响应的 标签将标识该响应适用的命令。可能的服务器完成响应有三种:OK(表示成功),NO(表示失败),或者BAD(表示协议错误,如:未知命令,或者命令语法 错误)。
服务器应当严格遵照本文档的语法大纲。任何带有协议语法错误,包括(但不限于)少了、多了空格或者参数,都应该被拒绝,并且服务器应当给客户端一个BAD服务器完成响应。
IMAP4rev1客户端的协议接收端从服务器读取一条响应行。它可以根据响应的第一个标记――可以是标签,一个“*”,或者一个“+”,做出动作作为响应。
客户端必须一直准备着接收任何服务器响应,包括非请求的服务器数据。服务器数据应当存储下来,以便客户端可以参照它存储的副本,而不是发送命令至服务器去请求数据。某些服务器数据则必须存储下来。
这个主题在服务器响应一节中有更细节的讨论。

2.3. 邮件属性

除了邮件文本,每个邮件都有一些与其相关的属性。这些属性可以被单独收回,或者与其它属性、或者邮件文本组合。

2.3.1. 邮件号

IMAP4rev1的邮件通过两个数值中的一个访问:唯一标识符,或者邮件序列号。
2.3.1.1. 唯一标识符(UID)的邮件属性
分配给每一个邮件的32位值,和唯一标识符的值(见下)形成一个64位的值,这个值永远不能指向这个邮箱中的其它任何邮件,或者它后面的同名邮 箱。分配时,邮箱中的唯一标识符严格地按升序排列;每个邮件添加至邮箱时,它将被派予一个比它先加进来的邮件的唯一标识符更大的唯一标识符。与邮件序列号 不同,唯一标识符可以是不连续的。
在其会话存活期,一个邮件的唯一标识符不能改变,也不应该在不同的会话间改变。唯一标识符在不同会话间的改变必须使用下面谈到的唯一标识符校验 机制审查。永久唯一标识符要求客户端刷新其状态,以区别于与服务器的前面一个会话(例如:无连接,或者离线访问的客户端);这将在[IMAP-DISC] 进一步地讨论。
与每个邮箱关联,有两个值维护着唯一标识符的指针:后续唯一标识符的值,和当前唯一标识符的值。
后续唯一标识符的值,是以后分配给这个邮箱中的新邮件的预留值。若非当前唯一标识符的值也改变了(见下),后续唯一标识符的值必须具有以下两个 特点。第一,若非新的邮件被加进邮箱,后续唯一标识符的值不能改变;第二,一旦新的邮件被加进邮箱,后续唯一标识符必须改变,即使这些新的邮件随后被删除 了。
注意:后续唯一标识符,是被用来提供这样一种手段,即客户端判断从上一次确认它的值后,是否有新的邮件被发送到邮箱。并不一定任何邮件都有唯一标识符。客户端只能推测,一旦它获得后续唯一标识符,此后到达的邮件的唯一标识符大于等于这个值。
当邮箱被选中时,唯一标识符的值将通过一个非标签化的OK响应的唯一标识符校验响应码发送。如果早先会话的唯一标识符不能永存于这个会话中,则唯一标识符的值必须大于早先会话的唯一标识符。
注意:理想情况下,唯一标识符可以一直永存。尽管本文档承认,不能永存的情况在特定服务器环境下是不可避免的,但我们极力鼓励避免这个问题的邮件存储实现技术。例如:
1)邮箱中的唯一标识符必须永远严格按升序排序。如果物理邮件存储被非IMAP代理刷新,则邮箱中的唯一标识符应当刷新,因为这种刷新(非IMAP代理刷新)导致旧的唯一标识符不再严格按升序排序了。
2)如果邮件存储没有唯一标识符的存储机制,那么它必须在每个会话刷新唯一标识符,并且每个会话必须具有一个唯一标识符校验值。
3)如果一个邮箱被删除,并且之后一个新的同名邮箱被创建,服务器必须保持区别于之前邮箱的唯一标识符的记录,或者分配给新邮箱一个新的唯一标 识符校验码。在这里,一个好的唯一标识符校验码,是代表邮箱创建日期或者时间的32位数。使用一个常数,如1,是没问题的,但这只是在这样前提下――确保 唯一标识符永远不再被使用,即使一个邮箱被删除(或者重命名),及一个新的同名邮箱不久被创建。
4)邮箱名、唯一标识符校验码、唯一标识符,三者的联合必须永远指向服务器上的一个固定邮件。特别的,实际日期、[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的唯一标识符是12345,那么,实际上,该邮箱中,有286条邮件的唯一标识符小于12345,有236个邮件的唯一标识符大于12345.

2.3.2. 标记的邮件属性

与邮件相关联的一个0串或者已命名的符号串。向该串中新增时,设置一个标记,从该串中删除时,清除该标志。IMAP4rev1中有两种标记。两种标记的实例都可以是永久化的,或者会话化的。
系统标记是指在本文档中预告确定的。所有的系统标记以“/”开头。一些系统标记(/Deleted和/Seen)在其它地方的描述中有特殊的语义。目前定义的系统标记有:
/Seen
邮件已读
/Answered
邮件已回复
/Flagged
邮件标记为紧急或者特别注意。
/Deleted
邮件为删除状态。
/Draft
邮件未写完(标记为草稿状态)。
/Recent
邮件是新到达邮箱的。这个会话是关于这个邮件的第一个会话;如果这个会话是可读写的,后续会话将看不见这个邮件的/Recent设置符。客户端不能修改该标记。
一个会话,如果不能判断它是不是关于一个邮件的第一个会话,那么就应当考虑这个邮件是新的。
如果多个连接同时选中了同一个邮箱,哪个连接会看到带有/Recent设置符的、新到达的邮件,哪个连接会看到没有/Recent设置符的邮件,这还没有定义。
关键词是由服务器实现体定义的。关键词并不以“/”开头。服务器可以允许客户端定义新邮箱中的关键词(更多信息参看PERMANENTFLAGS响应码的描述)。
一个标记可以是永久的,或者会话化的(标记的生命周期为某个会话)。对于永久标记,客户端可以增加,或者从邮件标记集中永久删除;即,当前和后续会话将可以看见永久标记集中的任何变化。对会话标记的改变只在其会话内是可视的。
注意:/Recent系统标记是会话标记的一个特例。/Recent不能在一个STORE或者APPENT命令中作为一个变量,也不能被改变。

2.3.3. 实际日期的邮件属性

服务器上邮件的实际日期和时间。它是反映何时接收到邮件的日期和时间,而不是[RFC-2822]头部中的日期和时间。按照SMTP的定义,通 过SMTP发送的邮件,其实际日期和时间反映的是这个邮件的最后发送日期和时间。通过IMAP4rev1的APPEND命令发送的邮件,其实际日期和时间 反映的是APPEND命令描述中所指定的。其它情形下,实际日期和时间遵照实现体的定义。

2.3.4. [RFC-2822]大小的邮件属性

同于[RFC-2822]版中的表述,即邮件中的字节串的长度。

2.3.5. 信封结构的邮件属性

[RFC-2822]邮件头部的一个语法表示。注意,IMAP信封结构与SMTP的不同。

2.3.6. 主体结构的邮件属性

[MIME-IMB]邮件主体结构信息的解析表示。

2.4. 邮件文本

IMAP4rev1允许获取邮件的全部[RFC-2822]文本,也允许获取它的一部分。特别的,获取[RFC-2822]邮件头部、[RFC-2822]邮件主体、一个[MIME-IMB]主体部分、或者一个[MIME-IMB]头部,也是可以的。

3. 状态和流程图

一旦客户端和服务器间的连接建立完成,一个IMAP4rev1连接就会处于4种状态中的某一种。初始状态在服务器的欢迎中标识。大多数命令只在 特定的状态中才是正确的。当连接处于不适当的状态时,客户端尝试一个不适当的命令引发协议错误,服务器将以一个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)未预认证的连接(OK欢迎)
(2)预认证的连接(PREAUTH欢迎)
(3)被拒绝的连接(BYE欢迎)
(4)成功LOGIN或者AUTHENTICATE命令
(5)成功的SELECT或者EXAMINE命令
(6)CLOSE命令,或者失败的SELECT、EXAMINE命令
(7)LOGOUT命令,服务器关闭,或者连接已关闭

4. 数据格式

IMAP4rev1使用文本型的命令和响应。IMAP4rev1中的数据可以是很多形式中的一种:原语、数字、字符串、圆括符列表、或者NIL。注意,一个特殊的数据项可能有几种形式;例如,使用“astring”语法定义的一个数据项可以是一个原语,或者一个字符串。

4.1. 原语

一个原语由一个以上普通字符组成。

4.2. 数字

一个数字由一个以上的数字字符组成,表示一个数值。

4.3. 字符串

一个字符串的两种形式:或者是原义字符串,或者是引用字符串。原义形式是普遍的字符串形式。处理原义字符串时,存在字符空间限制情况,为避免空间过载,就可以使用引用字符串。
一个原义字符串是一连串的0或者更多的字节数(包括CR和LF),左花括号形(“{”),字节数的长度,右花括号(“}”),和CRLF。如果 是从服务器发送至客户端的原义字符串,CRLF是紧跟在字节数据后的。如果是从客户端发送至服务器的原义字符串,在发送字节数据(和其余命令)前,客户端 必须等待接收一个连续请求命令(稍后讲述)。
一个引用字符串是一连串的0或者更多的7位字符,除CR和LF外,每个的后面都带有两个引用符(<”>)。
空字符串表示成“”(在两个双引号之间有0个字符的引用字符串),或者{0},其后跟着CRLF(一个原义的空字符串表示成{0})。
注意:即使字节数的长度为0,正在传送一个原义字符串的客户端也必须等待一个连续请求命令。

4.3.1. 字节及二进制字符串

通过使用[MIME-IMB]内容传输编码,就可以支持8位文本型的和二进制的邮件。IMAP4rev1实现体可以传送8位或者原义型的泛八进制字符,但只有当标识了[CHARSET]的时候才可以这样做。
虽然定义了一个二进制的主体编码,但是未编码的二进制字符串是不被接受的。一个“二进制字符串”是带有NUL字符的任意字符串。实现体必须在传送数据前,把二进制数据编码成文本形式,如BASE64。带有总数超量的CTL字符的字符串可能被认为是二进制。

4.4. 圆括符列表

表述为“圆括符列表”的数据结构;一连串的数据项,以空格为分隔,起始端和终止端带有圆括号。使用多级圆括符表示巢时,一个圆括符列表可以包含有其它的圆括符列表。
空列表表示成()――一个没有成员的圆括符列表。

4.5. NIL

“NIL”,这是个特殊的形式,它表示字符串或者圆括符列表的数据项不存在,它与空字符串“”或者空圆括符列表是有区别的。
注意:NIL永不使用于带有任何原语形式的数据项。例如,一个“NIL”的邮箱名是一个邮箱名为NIL的邮箱,而不是一个不存在的邮箱名。这是 因为邮箱使用“astring”语法,它是原语型或者字符串型的。相对的,一个NIL地址名是一个不存在的个体名,因为地址名使用“nstring”语 法,它是NIL或者一个字符串,而永远不会是一个原语。

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一节中所描述的国际命名约定。
创建一个新的邮箱名,有一些客户端的考虑:
1)原语类(参见正式语法一节)的任意一个字符要求邮箱名表述为一个引用字符串或者原义字符串。
2)CTL和其它生僻字符很难表述在用户界面,所以最好避免。
3)虽然通配符列表字符(“%”和“*”)在邮箱名中是正确的,但是因为与通配符的解释相冲突,所以很难把LIST和LSUB命令用于这样的邮箱名。
4)通常,保留一个字符(取决于服务器实现体)用于层级分隔。
5)“#”和“&”这两个字符有约定语上的意义,应当避免以其它意义使用它。

5.1.1. 邮箱层级命名

如果需要输出分层的邮箱名,邮箱名必须是从左到右的层级,并使用一个字符分隔不同层级。在一个邮箱名中,所有层级的分层使用同一个层级分隔字符表示。

5.1.2. 邮箱命名空间的约定

按照约定,任何邮箱名的第一个分层元素以“#”开头,它标识剩余名称的名称空间。这使得消除具有各自名称空间的、不同类型的邮箱存储间的含糊意义成为可能。
例如,提供访问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打印字符都可以表示邮箱名;即八进制值为0×20-0×25和0×27-0×7e的字符。字符“&”(0×26)表示成两个八进制串“&-”。
所有其它字符(八进制值为0×00-0×1f和0×7f-0xff)表示成修订版BASE64,它具有“UTF-7”之后的一个修订――“,”替代“/”使用。修订版BASE64不能用来表示任何可以表示自身的US-ASCII打印字符。
“&”用来转换至修订版BASE64,“-”用来转换回US-ASCII。不存在从BASE64至US-ASCII的隐式转换,且无效 转换(BASE64下的“-&”;注意,US-ASCII下的“&-”意为“&”)也是不允许的;就是说,一个以非 ASCII  ISO-10646字符结尾的邮箱名必须以一个“-”结尾。
这些修订是为了修正与UTF-7的以下错误:
1)UTF-7使用“+”字符实现转换;这跟邮箱名称中的“+”,特别是USENET网络组名称的一般用法相冲突。
2)UTF-7的编码是BASE64,它使用“/”字符;这跟“/”作为层级分隔符的普遍用法相冲突。
3)UTF-7禁止“/”的未编码使用;这跟“/”作为层级分隔符的普遍用法相冲突。
4)UTF-7禁止“~”的未编码合用;这跟一些服务器将“~”作为根目录标记的用法相冲突。
5)UTF-7允许选择多种形式表示同样的字符串;特别的,US-ASCII打印字符可以表示成编码后的形式。
虽然修订版UTF-7是一个约定,它在服务器建立了用一个嵌入的“&”字符处理任意邮箱名的一些请求。特别的,服务器实现体必须保留一 个修订版UTF-7名称的修订版BASE64部分的准确形式,并把这些文本视为区分大小写的,即使邮箱名是不区分大小写的或者部分区分大小写、部分不区分 大小写的。
服务器实现体应当用一个嵌入的“&”字符――用作CREATE的一个变量,检验任意邮箱名:正确修订版UTF-7语法中,不含有多余的 转换符,也不含有可表示自身的任意US-ASCII打印字符的修订版BASE64编码。但是,客户端实现体不能依赖服务器做这个,也不应当试图用一个嵌入 的“&”字符创建一个邮箱名,除非它用修订版UTF-7的语法编译。
不遵照修订版UTF-7约定、输出一个邮件存储的服务器实现体必须转换成修订版UTF-7的、含有非ASCII字符或者“&”字符的任意邮箱名。
例如,这是一个混合有英文、中文和日文文本的邮箱名:
~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),因为一个非标签化响应可以 使一个后续命令的序列号无效。这个问题不会发生于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命令。这些命令按照其被允许的状态组织。被多种状态允许的命令,只在其被允许的最小状态里列出(例如,在登录和选中状态都有效的命令,在登录状态中列出)。
命令参数,在下面的命令描述中标识为“参数:”,通过功能描述,而不是语法。命令参数的准确语法在正式语法一节中描述。
一些命令导致特定的服务器响应返回;它们在下面的命令描述中标识为“响应:”。响应一节中有这些响应的描述信息,正式语法一节中有这些响应的准 确语法。将服务器数据作为任意命令的一个结果传送,这是有可能的。这样,不特别请求服务器数据的命令描述成“此命令无特定响应”,而不是“无”。
命令描述中的“结果:”指明一个命令可能的标签化状态响应,和这些状态响应的任何特定解释。
只有成功的、改变状态的文档化命令才会改变一个连接的状态。一个被拒绝命令(BAD响应)永远不会改变一个被选中邮箱的连接状态。一个失败命令(NO响应)一般不会改变被选中邮箱的连接状态;SELECT和EXAMINE命令例外。

6.1. 客户端命令-任意状态

以下命令在任何状态下都有效:CAPABILITY,NOOP,和LOGOUT。

6.1.1. CAPABILITY命令

参数:无
响应:请求非标签化响应:CAPABILITY
结果:OK-capability完成
BAD-未知命令,或者参数无效
CAPABILITY命令请求服务器支持的功能列表。在(标签化)OK响应之前,服务器必须发送一个非标签化的、带有“IMAP4rev1”作为其功能列表之一的CAPABILITY响应。
一个以“AUTH=”开头的capability名,表示服务器支持这种特定的认证机制。所有这些名称,在定义上,都是本文档的一部分。例如, 一个实验性的“blurdybloop”认证者的认证capability可以是“AUTH=XBLURDYBLOOP”,而不是 “XAUTH=BLURDYBLOOP”或者“XAUTH=XBLURDYBLOOP”。
其它的capability名参考本文档的扩展版、修订版、或者改正版。更多信息参见CAPABILITY响应的文档。除非有明确的客户端动作激活capability,否则,超出本文档IMAP4rev1基本集的capabilities是不可用的。
客户端和服务器必须实现STARTTLS,LOGINDISABLED,和AUTH=PALIN(“IMAP-TLS”中有描述)的capabilities。重要信息参看安全考虑一节。
关于站点形式或者实现体特定的capability信息参看题为“客户端命令-试验/扩展”一节。
例子:
C:  abcd  CAPABILITY
S:  CAPABILITY  IMAP4rev1  STARTTLS  AUTH=GSSAPI
LOGINDISABLED
S:  abcd  OK  CAPABILITY  completed
C:  efgh  STARTTLS
S:  efgh  OK  STARTTLS  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命令

参数:无
响应:此命令无特定响应(见下)
结果:OK-noop完成
BAD-未知命令,或者参数无效
NOOP命令总是成功的。它什么也不做。
因为任何命令都可以返回一个状态更新作为非标签化数据,NOOP命令可以用作新邮件的周期性检测,或者在一个静止期间内的邮件状态刷新(实现这个,用这种方法是比较好的)。NOOP命令还可以用来重设服务器上任何静止的自动注销计时器。
例子:
C:  a002  NOOP
S:  a002  OK  NOOP  completed
C:  a047  NOOP
S:  22  EXPUNGE
S:  23  EXISTS
S:  RECENT
S:  14  FETCH  (FLAGS  (/Seen  /Deleted))
S:  a047  OK  NOOP  completed

6.1.3. LOGOUT命令

参数:无
响应:要求非标签化的响应:BYE
结果:OK-logout完成
BAD-未知命令,或者无效参数
LOGOUT命令告知服务器,客户端准备关闭连接。服务器必须在(标签化)OK响应前,发送一个BYE非标签化响应,并随后关闭这个网络连接。
例子:
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”中描述的ANONYMOUS“SASL”认证者实现。以前的 一个约定是使用用户ID“anonymous”的LOGIN命令;这种情况下,要求一个密码,尽管服务器可能选择接受任意密码。对匿名用户的约束依赖于实 现体。
一旦被认证(包括匿名用户),就不可能再进入未认证状态。
除了一般命令(CAPABILITY,NOOP,和LOGOUT),未认证状态下以下命令也是正确的:STARTTLS,AUTHENTICATE和LOGIN。关于这些命令的重要信息请参看安全考虑一节。

6.2.1. STARTTLS命令

参数:无
响应:此命令无需特定响应
结果:OK-starttls完成,开始TLS对话
BAD-未知命令,或者无效参数
在来自服务器端的标签化OK响应末尾的CRLF之后,一个“TLS”对话就开始了。一旦一个客户端发出一个STARTTLS命令,它就不能再发送其它命令,直到服务器响应出现并且“TLS”对话结束。
服务器保持未认证状态,即使客户端证书在“TLS”对话期间是受支持的。这不排除像EXTERNAL(“SASL”中定义的)的认证机制使用“TLS”对话决定的用户标识。
一旦“TLS”开始,客户端必须丢弃关于服务器功能的缓存信息,且应当重新发出CAPABILITY命令。这对保护免受修改功能列表指向STARTTLS的中间者攻击是有必要的。服务器可以在STARTTLS后发出不同功能。
例子:
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命令

参数:认证机制名
响应:可请求的连续数据
结果:OK-authenticate完成,当前为认证状态
NO-authenticate失败:不支持的认证机制,被拒绝的证书
BAD-未知命令,或者无效参数,认证对话被取消
AUTHENTICATE命令向服务器指出一个[SASL]认证机制。如果服务器支持被请求的认证机制,则它执行一个认证协议对话来认证并确认 客户端。它也可以为后续协议交互构建一个OPTIONAL安全层。如果被请求的认证机制不被支持,则服务器通过发送一个标签化NO响应来拒绝 AUTHENTICATE命令。
AUTHENTICATE命令不支持[SASL]的可选“初始响应”特性。[SASL]5.1一节,说明了如何处理使用一个初始响应的认证机制。
[SASL]的这个协议的片面描述的服务名称是“imap”。
认证协议对话由认证机制特定的、一系列服务器邀请和客户端响应组成。一个服务器邀请由一个以“+”开头,后跟一个BASE64编码的字符串的命 令连续请求响应组成。如果客户端希望取消一个认证对话,它就发出由一个“*”组成的一个行。如果服务器接收到这样一个响应,它必须通过发送一个标签化的 BAD响应来拒绝AUTHENTICATE命令。
如果一个安全层是通过[SASL]认证对话构建的,那么,紧跟在结束客户端的认证对话的CRLF、及服务器的标签化OK响应的CRLF之后,它就起效了。
客户端和服务器实现体必须自己执行AUTHENTICATE命令时,并不要求它实现[IMAP-TLS]中描述的简单机制以外的任何认证机制。同时,不要求一个认证机制被支持于任意安全层。
注意:一个服务器实现体必须执行一个不允许任何简单文本型密码机制的配置,除非STARTTLS命令已经启动,或者提供了保护会话免受密码窥探 的其它机制。在没有保护机制避免密码窥探的情况下使用简单文本型密码机制,服务器站点不应当使用这样的配置。客户端和服务器实现体应当执行不使用简单文本 型密码的其它[SASL]机制,像[SASL]中描述的GSSAPI机制和(或者)[DIGEST-MD5]机制。
服务器和客户端可以支持多个认证机制。服务器应当在其CAPABILITY命令的响应中列出其支持的认证机制,以便客户端知道使用何种认证机制。
在一个成功的AUTHENTICATE命令的标签化OK响应里,服务器可以包含进一个CAPABILITY响应码,以便自动发送功能。如果一个 客户端认出这些自动的功能,它就无需发送一个CAPABILITY命令。只有在一个安全层没有被AUTHENTICATE命令构建的时候,才能这样做,因 为作为一个AUTHENTICATE命令的一部分的标签化OK响应,是不受加密或者整数验证的保护的。在这种情况下,[SASL]要求客户端重新发出一个 CAPABILITY命令。
如果一个AUTHENTICATE命令以一个NO响应宣告失败,客户端可以通过发出另外一个AUTHENTICATE命令尝试另外一个认证机 制。它也可以通过使用LOGIN命令尝试认证(更多细节参看6.2.3一节)。就是说,客户端可以按降序请求认证类别,LOGIN命令则是最后的选择。
在认证对话期间,从客户端传送至服务器的授权标识被服务器解释为正处于优先级的用户名,即正请求的用户。
例子:
S:  OK  IMAP4rev1  Server
C:  A001  AUTHENTICATE  GSSAPI
S:  +
C:  YIIB+wYJKoZIhvcSAQICAQBuggHqM IIB5qADAgEFoQMCAQ6iBwMFA CAAAACjggEmYYIBIjCCAR6gA wIBBaESGxB1Lndhc2hpbmd0b 24uZWR1oi0wK6ADAgEDoSQwI hsEaW1hcBsac2hpdmFtcy5jY WMud2FzaGluZ3Rvbi5lZHWjg dMwgdCgAwIBAaEDAgEDooHDB IHAcS1GSa5b+fXnPZNmXB9SjL8Ollj2SKyb+3S0iXMljen/jNkpJXAleKTz6BQPzj8duz8E toOuNfKgweViyn/9B9bccy1uuAE2HI0yC/PHXNNU9ZrBziJ8Lm0tTNc98k UpjXnHZhsMcz5Mx2GR6dGknb I0iaGcRerMUsWOuBmKKKRmVM MdR9T3EZdpqsBd7jZCNMWotj hivd5zovQlFqQ2Wjc2+y46vKP/iXxWIuQJuDiisyXF0Y8+5GTpALpHDc1/pIGmMIGjoAMCAQGigZsEgZg2 on5mSuxoDHEA1w9bcW9nFdFx DKpdrQhVGVRDIzcCMCTzvUbo qb5KjY1NJKJsfjRQiBYBdENK fzK+g5DlV8nrw81uOcP8NOQCLR5X koMHC0Dr/80ziQzbNqhxO6652Npft0LQw JvenwDI13YxpwOdMXzkWZN/XrEqOWp6GCgXTBvCyLWLlWnb aUkZdEYbKHBPjd8t/1×5Yg==
S:  YGgGCSqGSIb3EgECAgIAb1kw V6ADAgEFoQMCAQ+iSzBJoAMCAQGiQgRAtHTEuOP 2BXb9sBYFR4SJlDZxmg39Ixm RBOhXRKdDA0uHTCOT9Bq3OsU TXUlk0CsFLoa8j+gvGDlgHuqzWHPSQg==
C:
S:  YDMGCSqGSIb3EgECAgIBAAD/6jcyG4GE3KkTzBeBiVHeceP2 CWY0SR0fAQAgAAQEBAQ=
C:  YDMGCSqGSIb3EgECAgIBAAD/3LQBHXTpFfZgrejpLlLImPwk hbfa2QteAQAgAG1yYwE=
S:  A001  OK  GSSAPI  authentication  successful
注意:服务器邀请和客户端响应中的换行是为了编辑上的清楚,而不是实际认证符。

6.2.3. LOGIN 命令

参数:用户名
密码
响应:此命令无特定响应
结果:OK-login完成,当前是认证状态
NO-login失败:用户名或者密码被拒绝
BAD-未知命令,或者无效参数
LOGIN命令向服务器确认客户端,并带有确认该用户的简单文本型密码。
在一个成功的LOGIN命令的标签化OK响应里,服务器可以包含进一个CAPABILITY响应码,以便(实现)自动发送功能。如果一个客户认出了这些自动的功能,则它无需发送一个CAPABILITY命令。
例子:
C:  a001  LOGIN  SMITH  SESAME
S:  a001  OK  LOGIN  completed
注意:在一个不安全网络(比如因特网)上使用LOGIN命令有安全风险,因为任何网络传输的监控者都可以获取简单文本型密码。LOGIN命令不应当使用,除非作为最后一种方法,同时,建议客户端实现体采取措施使LOGIN命令的任何自动使用无效。
除非STARTTLS命令已经构建,或者已经提供了保护会话免受密码窥探的机制,否则,一个服务器实现体必须实现一个机制,在这个机制里宣告 LOGINDISABLED功能并且不允许LOGIN命令。服务器站点不应当使用没有这样一个免受密码窥探(功能)的保护机制、而允许LOGIN命令的配 置。如果LOGINDISABLED功能被宣告,则一个客户端实现体不能发送一个LOGIN命令。

6.3. 客户端命令-认证状态

在认证状态下,把邮箱作为原语实体来操作的命令是允许的。在这些命令中,SELECT及EXMINE命令将会选中一个邮箱以访问及进入选中状态。
除了常见的命令(CAPABILITY,NOOP,和LOGOUT),以下命令在认证状态下也是正确 的:SELECT,EXAMINE,CREATE,DELETE,RENAME,SUBSCRIBE,UNSUBSCRIBE,LIST,LSUB,STATUS, 和APPEND。

6.3.1. SEELCT命令

参数:邮箱名
响应:要求非标签化的响应:FLAGS,EXISTS,RECENT
要求OK非标签化响应:UNSEEN,PERMANENTFLAGS,UIDNEXT,UIDVALIDITY
结果:OK-select完成,当前是选中状态
NO-select失败,当前是认证状态:不存在这个邮箱,不能访问邮箱
BAD-未知命令,或者参数无效
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命令正尝试,则没有邮箱被选中。
如果客户端被允许修改邮箱,则服务器应当把“[READ-WRITE]”响应码作为标签化OK响应的文本的前缀。
如果客户端没有修改邮箱的权限,但是有读取权限,则邮箱以只读方面选中,且服务器必须用“[READ-ONLY]”响应码作为标签化OK响应的 文本前缀,以SELECT。通过SELECT方式的只读访问,与通过EXAMINE方式的只读访问,二者的区别在于,特定的只读邮箱可能允许基于用户(而 不是全局)的永久状态的改变。在一个基于服务器的.newsrc文件中做了标记的网络论坛邮件就是这种可以被修改的、带有只读邮箱的、基于用户的永久状态 的一个例子。
例子:
C:  A142  SELECT  INBOX
S:  172  EXISTS
S:  RECENT
S:  OK  [UNSEEN  12]  Message  12  is  first  unseen
S:  OK  [UIDVALIDITY  3867529045]  UID  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命令

参数:邮箱名
响应:要求非标签化响应:FLAGS,EXISTS,RECENT
要求OK非标签化响应:UNSEEN,PERMANENTFLAGS,UIDNEXT,UIDVALIDITY
结果:OK-examine完成,当前是选中状态
NO-examine失败,当前是认证状态:没有这个邮箱,不能访问邮箱
BAD-未知命令,或者无效参数
EXAMINE命令与SELECT相同,并返回同样的输出;不过,只读方式时选中的邮箱是一样的。邮箱的永久状态下,没有变动,包括有基于用户的状态的权限;特别的,EXAMINE不能使邮件丢失/Recent标记。
EXAMINE命令的标签化OK响应文本必须以“[READ-ONLY]”开头。
例子:
C:  A932  EXAMINE  blurdybloop
S:  17  EXISTS
S:  RECENT
S:  OK  [UNSEEN  8]  Message  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命令

参数:邮箱名
响应:此命令无需特定响应
结果:OK-create完成
NO-create失败:不能创建这个名称的邮箱
BAD-未知命令,或者无效参数
CREATE命令用给定名称创建一个邮箱。只有当这个名称的新邮箱被创建完成时,才返回一个OK响应。试图创建INBOX,或者一个与已在邮箱名同名的邮箱,引发一个错误。创建过程中的任何错误都将返回一个标签化NO响应。
如果邮箱名以服务器的层级分隔符作为尾缀(就像通过LIST命令从服务器返回的),这就告诉客户端准备在这个名称的层级下创建邮箱名。不要求这个通知的的服务器实现体必须忽略这个通知。任何情况下,这个被创建邮箱的名称(应当)没有多余的层级分隔符。
如果邮箱名的其它地方出现服务器的层级分隔符,服务器应当创建CREATE命令成功完成所需要的每一个层级。即,在一个以“/”作为层级分隔符的服务器上创建“foo/bar/zap”的尝试,如果foo/和foo/bar不存在,则应当创建它们。
如果一个被创建的邮箱,它的名称与已经被删除的邮箱名相同,那么,它的唯一标识符必须大于邮箱中先前引用中用到的任何一个唯一标识符,除非新的引用有一个不同的唯一标识符值。更多细节参看UID命令的描述。
例子:
C:  A003  CREATE  owatagusiam/
S:  A003  OK  CREATE  completed
C:  A004  CREATE  owatagusiam/blurdybloop
S:  A004  OK  CREATE  completed
注意:这个例子的解释依赖于,从LIST“/”是否返回为层级分隔符。如果“/”是层级分隔符,带有一个名为“blurdybloop”成员的一个新层级“owatagusiam”被创建。否则,处在同一层级的两个邮箱被创建。

6.3.4. DELETE命令

参数:邮箱名
响应:此命令无需特定响应
结果:OK-delete完成
NO-delete失败:不能删除这个名称的邮箱
BAD-未知命令,或者无效参数
DELETE命令永久删除给定名称的邮箱。若邮箱被删除,则返回一个标签化的OK响应。尝试删除INBOX,或者一个不存在的邮箱,是错误的。
DELETE命令不能删除子级。例如,如果一个邮箱有一个子级“foo.bar”(假设“.”是层级定义符),删除“foo”不能删除“foo.bar”。尝试删除一个带有子级、并且有/Noselect属性的邮箱名,是错误的(更多细节参看LIST响应的描述)。
删除一个带有子级、并且没有/Noselect属性的邮箱名,是允许的。这种情况下,这个邮箱中的所有邮件被删除,且这个邮箱名将取得/Noselect邮箱名属性。
删除了的邮箱使用的最高唯一标识符的值必须保留,这样一个新创建的同名邮箱就不会再使用先前引用的标识符,除非这个新的引用有一个不同的唯一标识符值。更多细节参看UID命令的描述。
例子:
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  DELTE  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命令

参数:已经存在的邮箱名
新的邮箱名
响应:此命令无需特定响应
结果:OK-rename完成
NO-rename失败:不能重命名邮箱为这个名称,不能以这个名称重命名至邮箱
BAD-未知命令,或者无效参数
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重命名的影响。
例子:
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命令

参数:邮箱
响应:此命令无需特定
结果:OK-subscribe完成
NO-subscribe失败:不能订阅这个邮箱名
BAD-未知命令,或者无效参数
SUBSCRIBE命令增加指定邮箱名至服务器的活动邮箱序列或者订阅邮箱序列中,通过LSUB命令返回。当且仅当订阅成功时,该命令返回一个标签化的OK响应。
服务器可以向SUBSCRIBE证实邮箱参数以确保它的存在。但是,它不能单方面从订阅列表中删除一个存在的邮箱名,即使该邮箱名不存在了。
注意:这个需求是出于,一个服务器可以选择,在一个邮箱名众所周知的邮箱的内容过期后,常规地删除该邮箱(比如,“system-alerts”),以便在新的内容匹配时重新创建它。
例子:
C:  A002  SUBSCRIBE  #news.comp.mail.mime
S:  A002  OK  SUBSCRIBE  completed

6.3.7. UNSUBSCRIBE命令

参数:邮箱名
响应:此命令无需特定响应
结果:OK-unsubscribe完成
NO-unsubscribe失败:不能取消订阅该邮箱名
BAD-未知命令,无效参数
UNSUBSCRIBE从服务器的活动邮箱序列或者订阅邮箱序列中删除特定邮箱名,通过LSUB命令返回。当且仅当取消订阅成功时,该命令返回一个标签化的OK响应。
例子:
C:  A002  UNSUBSCRIBE  #news.comp.mail.mime
S:  A002  OK  UNSUBSCRIBE  completed

6.3.8. LIST命令

参数:引用名,带可能的通配符的邮箱名
响应:非标签化的响应:LIST
结果:OK-list完成
NO-list失败:不能列出该引用或者名称
BAD-未知命令,或者无效参数
LIS命令返回客户端可用的所有名称的完整序列的一个名称子序列。返回0,或者更多的非标签化LIST答复,包含名称属性,层级定义符,和名称;更多细节参看LIST答复的描述。
LIST命令应当迅速返回其数据,没有过度的延时。例如,它不应当节外生枝地计算/Marked或者/Unmarked状态,或者进行其它处理;如果每一个名称需要1秒钟的处理,那么列出1200个名称则需要20分钟!
一个空的(“”空串)引用名参数表明邮箱名是通过SELECT解释的。返回的邮箱名必须与受支持的邮箱名模式匹配。一个非空的引用名参数是一个邮箱名,或者邮箱的一个层级,它指定了被解释的邮箱名的上下文。
一个空的(“”空串)邮箱名参数是为返回层级定义符和引用中所给定名称的根结点名的一个特殊请求。如果引用不是根结点,或者是一个空串,返回作 为根结点的值可能是空串。在所有情况下,都返回一个层级定义符(或者NIL-如果没有层级)。这允许客户端取得层级定义符(或者证实邮箱名是在同一级 的),即使当前没有那个名称的邮箱存在。
引用和邮箱名参数被解释成一个规范形式,它表示成一个清晰的从左到右层级。返回的邮箱名将会在解释形式中。
注意:引用参数的解释是基于实现体定义的。它取决于服务器实现体是否有一个“当前工作目录”,及开头的、可替代当前工作目录的“折断符”的概念,
例如,在一个输出UNIX或者NT文件系统的服务器上,引用参数包含当前工作目录,且邮箱名可能包含被解释成在当前工作目录中的名称。
如果一个服务器没有折断符的概念,则规范形式应是带邮箱名的引用名。注意,如果服务器实现了名称空间的约定(5.1.2一节),则“#”必须被作为折断符对待。
如果服务器参数不是一个邮箱层级(即,它是一个/NoInferiors名称),且/或引用参数不以层级定义符结束,则引用参数的解释是基于实 现体的。例如,一个“foo/bar”的引用和“rag/baz”的邮箱名可以解释成“foo/bar/rag/baz”,“foo/barrage /baz”,或者“foo/rag/baz”。客户端不应当使用这样的一个引用参数,除非有用户的明确请求。一个分层的浏览器不能对服务器的引用解释作任 何的假设,除非引用是一个邮箱层级并且以层级定义符结束。
包含于被解释形式的、引用参数的任何部分应当以被解释形式为前缀。它应当与引用名称参数有相同的形式。这个规则允许客户端决定返回的邮箱名是否 是在引用参数的上下文中,或者邮箱参数的一些相关信息是否可以代替引用参数。没有这个上下文,可能客户端得知道服务器名称语义,包括什么字符串是可以代替 一个名称上下文的折断符。
例如,这里是在一个基于UNIX的服务器上,引用和邮箱名可能被如何解释的一些例子:
引用邮箱名解释
~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/*
开头的三个例子演示了引用参数的上下文中的解释。注意,“~simth/Mail”不应当改成类似“/u2/users/smith/Mail”,否则客户端就不可能断定这个解释是在引用的上下文中。
字符“*”是一个通配符,它匹配其所在位置的0个或者更多的字符。字符“%”类似于“*”,但是它不匹配一个层级定义符。如果“%”通配符是一 个邮箱名参数的最后一个字符,匹配的层级也会返回。如果这些层级不是可选择的邮箱,则它们带着/Noselect邮箱属性返回(更多细节参看LIST响应 的描述)。
允许服务器实现体通过禁止特定的字符或者名称,以免在特定情形下匹配一个通配符,这样就隐藏源于通配符的、不同的可访问邮箱。例如,一个基于UNIX的服务器可以限制“*”的解释,以便一个初始的“/”字符不匹配。
如果对该用户而言INBOX是受该服务器支持的,并且大写字符串“INBOX”匹配带有如上所述通配符的、被解释的参数和邮箱名参数,那么,特 殊名称INBOX包含于LIST的输出。删去INBOX的质疑是,SELECT  INBOX是否会返回失败;这无关于用户的真实INBOX是否位于这个服 务器或者其它服务器。
例子:
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命令

参数:引用名,带有可能的通配符的邮箱名
响应:非标签化的响应:LSUB
结果:OK-lsub完成
NO-lsub失败:不能列出那个引用或者名称
BAD-未知命令,或者无效参数
LSUB命令返回的是,用户已经声明为活动的、或者订阅了的名称序列的一个名称子集。0个或者更多的非标签化LSUB答复被返回。LSUB的参数同于LIST的形式。
返回的非标签化LSUB响应可能包含从一个非标签化LIST响应的不同邮箱标记。如果出现这个,那么在非标签化LIST中的标记会被认为是更可信的。
当使用带有%通配符的LSUB时,一种特殊的情形就出现了。试想一下,如果“foo/bar”(带有一个“/”层级定义符)是已订阅的,而 “foo”不是。在LSUB响应中,LSUB的一个“%”通配符必须返回foo,而不是foo/bar,并且它必须标记为带/Noselect属性的。
服务器不能单方面从订阅列表中移除一个已经存在的邮箱名,即使那个名称的邮箱已经不存在了。
例子:
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命令

参数:邮箱名,状态数据项名
响应:非标签化响应:STATUS
结果:OK-status完成
NO-status失败:没有那个名称的status
BAD-未知命令,或者无效参数
STATUS命令请求指定邮箱的状态。它不改变当前被选中的邮箱,也不影响被请求的邮箱中的任何邮件的状态(特别的,STATUS不能使邮件失去/Recent标记)。
STATUS提供了这样一个选择:在没有取消选择第一次IMAP4rev1连接中的当前邮箱的情况下,就打第二次IMAP4rev1连接,并在一个邮箱上进行一个EXAMINE命令以请求那个邮箱的状态。
与LIST命令不同,STATUS命令不一定是快速响应的。在特定条件下,它可能是很慢的。在某些实现体中,服务器被希望以只读方式内部打开邮箱获取特定的状态信息。STATUS命令不接受通配符,这一点也与LIST命令不同。
注意: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标记位的邮件数量。
例子:
C:  A042  STATUS  blurdybloop  (UIDNEXT  MESSAGES)
S:  STATUS  blurdybloop  (MESSAGES  231  UIDNEXT  44292)
S:  A042  OK  STATUS  completed

6.3.11. APPEND命令

参数:邮箱名,OPTIONAL位的组合列表,OPTIONAL日期/时间串,邮件原义
响应:此命令无特定响应
结果:OK-append完成
NO-append错误:不能添加到该邮箱,标记、或者日期/时间、或者邮件文本有错误
BAD-未知命令,或者无效参数
APPEND命令将原义参数像一个新邮件一样添加到指定的目标邮箱末尾。这个参数应当是一个[RFC-2822]邮件的格式。邮件中允许8位字 符串。一个不能正确保存8位数据的服务器执行体必须能够用一个[MIME-IMB]内容转换编码,进行8位APPEND数据与7位(APPEND数据)之 间的可逆转换。
注意:可能有例外,比如,草稿邮件――其中被请求的[RFC-2822]头在APPEND的邮件原义参数中被省略了。这样做的整个关联必须被理解并小心权衡。
如果一个组合列表被声明,则标记位应当在结果邮件中被设置;否则,结果邮件的标记列表默认设置为空。两种情况下,Recent标记都要设置。
如果声明了一个日期-时间,实际日期应当在结果邮件中被设置;否则,结果邮件的实际日期默认设置为当前日期和时间。
如果插入操作因为某种原因不能成功,邮箱必须恢复至APPEND尝试前的状态;不允许局部的插入操作。
如果目标邮箱不存在,服务器必须返回一个错误,且不能自动创建邮箱。除非确定目标邮箱不能被创建,否则,服务器必须发送响应码 “[TRYCREATE]”作为标签化NO响应的文本的前缀。这给客户端一个暗示,即它可以尝试一个CREATE命令,并且,如果CREATE成功,还可 以重试APPEND。
如果邮箱当前被选中,正常的新邮件动作应当发生。特别地,服务器应当通过一个非标签化的EXISTS响应迅速通知客户端。如果服务器不这样做,客户端可以在一个或者多个APPEND命令之后发出一个NOOP命令(或者,NOOP命令失败,发出一个CHECK命令)。
例子:
C:  A003  APPEND  saved-messages  (/Seen)  {310}
S:  Ready  for  literal  data
C:  Date:  Mon,  Feb  1994  21:52:25  -0800  (PST)
C:  From:  Fred  Foobar  foobar@Blurdybloop.COM
C:  Subject:  afternoon  meeting
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]信封信息的机制。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值