| < draft-melnikov-imap-disc-05.txt | draft-melnikov-imap-disc-06.txt > | |||
|---|---|---|---|---|
| IMAPEXT Working Group A. Melnikov | IMAPEXT Working Group A. Melnikov | |||
| Internet Draft: IMAP4 Disconnected Access Editor | Internet Draft: IMAP4 Disconnected Access Editor | |||
| Document: draft-melnikov-imap-disc-05.txt September 2004 | Document: draft-melnikov-imap-disc-06.txt October 2004 | |||
| Expires: March 2005 | Expires: April 2005 | |||
| Synchronization operations for disconnected IMAP4 clients | Synchronization operations for disconnected IMAP4 clients | |||
| Status of this Memo | Status of this Memo | |||
| By submitting this Internet-Draft, I certify that any applicable | By submitting this Internet-Draft, I certify that any applicable | |||
| patent or other IPR claims of which I am aware have been disclosed, or | patent or other IPR claims of which I am aware have been disclosed, or | |||
| will be disclosed, and any of which I become aware will be disclosed, | will be disclosed, and any of which I become aware will be disclosed, | |||
| in accordance with RFC 3668. | in accordance with RFC 3668. | |||
| skipping to change at line 33 ¶ | skipping to change at line 33 ¶ | |||
| ``work in progress''. | ``work in progress''. | |||
| The list of current Internet-Drafts can be accessed at | The list of current Internet-Drafts can be accessed at | |||
| http://www.ietf.org/ietf/1id-abstracts.txt | http://www.ietf.org/ietf/1id-abstracts.txt | |||
| The list of Internet-Draft Shadow Directories can be accessed at | The list of Internet-Draft Shadow Directories can be accessed at | |||
| http://www.ietf.org/shadow.html. | http://www.ietf.org/shadow.html. | |||
| This is a draft document based on the expired draft written by | This is a draft document based on the expired draft written by | |||
| the IETF IMAP Working Group. A revised version of this draft document | the IETF IMAP Working Group. A revised version of this draft document | |||
| will be submitted to the RFC editor as an Informational (or BCP) RFC for the | will be submitted to the RFC editor as an Informational (or BCP) RFC for | |||
| Internet Community. Discussion and suggestions for improvement are | the Internet Community. Discussion and suggestions for improvement are | |||
| requested, and should be sent to imap@CAC.Washington.EDU. | requested, and should be sent to imap@CAC.Washington.EDU. | |||
| This memo is for informational use and does not constitute a | This memo is for informational use and does not constitute a | |||
| standard. Distribution of this memo is unlimited. | standard. Distribution of this memo is unlimited. | |||
| Abstract | Abstract | |||
| This document attempts to address some of the issues involved in building | This document attempts to address some of the issues involved in building | |||
| a disconnected IMAP4 client. In particular, it deals with the issues | a disconnected IMAP4 [IMAP4] client. In particular, it deals with the | |||
| of what might be called the "driver" portion of the synchronization | issues of what might be called the "driver" portion of the synchronization | |||
| tool: the portion of the code responsible for issuing the correct set | tool: the portion of the code responsible for issuing the correct set | |||
| of IMAP4 commands to synchronize the disconnected client in the way | of IMAP4 commands to synchronize the disconnected client in the way | |||
| that is most likely to make the human who uses the disconnected | that is most likely to make the human who uses the disconnected | |||
| client happy. | client happy. | |||
| This note describes different strategies that can be used by disconnected | This note describes different strategies that can be used by disconnected | |||
| clients as well as shows how to use IMAP protocol in order to minimize the | clients as well as shows how to use IMAP protocol in order to minimize the | |||
| time of synchronization process. | time of synchronization process. | |||
| 1. Conventions Used in this Document | This note also lists IMAP extensions that a server should implement in | |||
| order to provide better synchronization facilities to disconnected clients. | ||||
| 1. Introduction | ||||
| Several recommendations presented in this document are generally | ||||
| applicable to all types of IMAP clients. However this document tries | ||||
| to concentrate on disconnected mail clients [IMAP-MODEL]. It also suggests | ||||
| some IMAP extensions* that should be implemented by IMAP servers in order | ||||
| to make the life of disconnected clients easier. In particular, the [UIDPLUS] | ||||
| extension was specifically designed to streamline certain disconnected | ||||
| operations, like expunging, uploading and copying messages | ||||
| (see Sections 4.2.1, 4.2.2.1 and 4.2.4). | ||||
| Readers of this document are also strongly advised to read RFC 2683 | ||||
| [RFC 2683]. | ||||
| * - note, that the functionality provided by the base IMAP protocol | ||||
| [IMAP4] is sufficient to perform basic synchronization. | ||||
| 1.1. Conventions Used in this Document | ||||
| In examples, "C:" and "S:" indicate lines sent by the client and | In examples, "C:" and "S:" indicate lines sent by the client and | |||
| server respectively. | server respectively. | |||
| The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | |||
| "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this | "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this | |||
| document are to be interpreted as described in RFC 2119 [KEYWORDS]. | document are to be interpreted as described in RFC 2119 [KEYWORDS]. | |||
| Let's call an IMAP command idempotent, if the result of executing the | Let's call an IMAP command idempotent, if the result of executing the | |||
| command twice sequentially is the same as the result of executing the | command twice sequentially is the same as the result of executing the | |||
| command just once. | command just once. | |||
| Several recommendations presented in this document are generally | ||||
| applicable to all types of IMAP clients. However this document tries | ||||
| to concentrate on disconnected mail clients. It also suggests some IMAP | ||||
| extensions that should be implemented by IMAP servers in order to make | ||||
| life of disconnected clients easier. | ||||
| Readers of this document are also strongly advised to read RFC 2683 | ||||
| [RFC 2683]. | ||||
| Editorial comments/questions or missing paragraphs are marked in the | Editorial comments/questions or missing paragraphs are marked in the | |||
| text with << and >>. | text with << and >>. | |||
| 2. Design Principles | 2. Design Principles | |||
| All mailbox state or content information stored on the disconnected | All mailbox state or content information stored on the disconnected | |||
| client should be viewed strictly as a cache of the state of the | client should be viewed strictly as a cache of the state of the | |||
| server. The "master" state remains on the server, just as it would | server. The "master" state remains on the server, just as it would | |||
| with an interactive IMAP4 client. The one exception to this rule is | with an interactive IMAP4 client. The one exception to this rule is | |||
| that information about the state of the disconnected client's cache | that information about the state of the disconnected client's cache | |||
| (the state includes flag changes while offline and scheduled message uploads) | (the state includes flag changes while offline and scheduled message | |||
| remains on the disconnected client: that is, the IMAP4 server is not | uploads) remains on the disconnected client: that is, the IMAP4 server | |||
| responsible for remembering the state of the disconnected IMAP4 client. | is not responsible for remembering the state of the disconnected IMAP4 | |||
| client. | ||||
| We assume that a disconnected client is a client that, for whatever | We assume that a disconnected client is a client that, for whatever | |||
| reason, wants to minimize the length of time that it is "on the | reason, wants to minimize the length of time that it is "on the | |||
| phone" to the IMAP4 server. Often this will be because the client is | phone" to the IMAP4 server. Often this will be because the client is | |||
| using a dialup connection, possibly with very low bandwidth, but | using a dialup connection, possibly with very low bandwidth, but | |||
| sometimes it might just be that the human is in a hurry to catch an | sometimes it might just be that the human is in a hurry to catch an | |||
| airplane, or some other event beyond our control. Whatever the | airplane, or some other event beyond our control. Whatever the | |||
| reason, we assume that we must make efficient use of the network | reason, we assume that we must make efficient use of the network | |||
| connection, both in the usual sense (not generating spurious traffic) | connection, both in the usual sense (not generating spurious traffic) | |||
| and in the sense that we would prefer not to have the connection | and in the sense that we would prefer not to have the connection | |||
| skipping to change at line 158 ¶ | skipping to change at line 170 ¶ | |||
| that operates on messages) - open the mailbox. Check its UID | that operates on messages) - open the mailbox. Check its UID | |||
| validity value (see section 4.1 for more details) returned in | validity value (see section 4.1 for more details) returned in | |||
| the UIDVALIDITY response code. If the UIDVALIDITY value returned | the UIDVALIDITY response code. If the UIDVALIDITY value returned | |||
| by the server differs, the client MUST empty the local cache of | by the server differs, the client MUST empty the local cache of | |||
| the mailbox and remove any pending "actions" which refer to UIDs | the mailbox and remove any pending "actions" which refer to UIDs | |||
| in that mailbox (and consider them failed). Note, this doesn't | in that mailbox (and consider them failed). Note, this doesn't | |||
| affect actions performed on client generated fake UIDs (see | affect actions performed on client generated fake UIDs (see | |||
| section 5). | section 5). | |||
| 2) Perform the action. If the action is to delete a mailbox (DELETE), | 2) Perform the action. If the action is to delete a mailbox (DELETE), | |||
| make sure that the mailbox is closed first. | make sure that the mailbox is closed first (see also Section | |||
| 3.4.12 of [RFC 2683]). | ||||
| d) "Server-to-client synchronization" - for each mailbox that requires | d) "Server-to-client synchronization" - for each mailbox that requires | |||
| synchronization, do the following: | synchronization, do the following: | |||
| 1) Check the mailbox UIDVALIDITY (see section 4.1 for more details). | 1) Check the mailbox UIDVALIDITY (see section 4.1 for more details). | |||
| with SELECT/EXAMINE/STATUS. | with SELECT/EXAMINE/STATUS. | |||
| If UIDVALIDITY value returned by the server differs, | If UIDVALIDITY value returned by the server differs, | |||
| the client MUST | the client MUST | |||
| * empty the local cache of that mailbox; | * empty the local cache of that mailbox; | |||
| * remove any pending "actions" which refer to UIDs in | * remove any pending "actions" which refer to UIDs in | |||
| that mailbox and consider them failed; | that mailbox and consider them failed; | |||
| * skip step 2-II; | * skip step 2-II; | |||
| 2) Fetch the current "descriptors"; | 2) Fetch the current "descriptors"; | |||
| I) Discover new messages. | I) Discover new messages. | |||
| II) Discover changes to old messages. | II) Discover changes to old messages. | |||
| 3) Fetch the bodies of any "interesting" messages that the client | 3) Fetch the bodies of any "interesting" messages that the client | |||
| doesn't already have. | doesn't already have. | |||
| d) Close all open mailboxes not required for further operations | e) Close all open mailboxes not required for further operations | |||
| (if staying online) or disconnect all open connections (if going | (if staying online) or disconnect all open connections (if going | |||
| offline). | offline). | |||
| Terms used: | Terms used: | |||
| "Actions" are queued requests that were made by the human to the | "Actions" are queued requests that were made by the human to the | |||
| client's MUA software while the client was disconnected. | client's MUA software while the client was disconnected. | |||
| Let define "descriptors" as a set of IMAP4 FETCH data items. | Let define "descriptors" as a set of IMAP4 FETCH data items. | |||
| Conceptually, a message's descriptor is that set of | Conceptually, a message's descriptor is that set of | |||
| information that allows the synchronization program to decide what | information that allows the synchronization program to decide what | |||
| protocol actions are necessary to bring the local cache to the | protocol actions are necessary to bring the local cache to the | |||
| desired state for this message; since this decision is really up | desired state for this message; since this decision is really up | |||
| to the human, this information probably includes a at least a few | to the human, this information probably includes a at least a few | |||
| header fields intended for human consumption. Exactly what will | header fields intended for human consumption. Exactly what will | |||
| constitute a descriptor depends on the client implementation. At | constitute a descriptor depends on the client implementation. At | |||
| a minimum, the descriptor contains the message's UID and FLAGS. | a minimum, the descriptor contains the message's UID and FLAGS. | |||
| Other likely candidates are the RFC822.SIZE, RFC822.HEADER and | Other likely candidates are the RFC822.SIZE, RFC822.HEADER, | |||
| BODYSTRUCTURE data items. | BODYSTRUCTURE or ENVELOPE data items. | |||
| Comments: | Comments: | |||
| 1). The list of actions should be ordered. E.g., if the human deletes | 1). The list of actions should be ordered. E.g., if the human deletes | |||
| message A1 in mailbox A, then expunges mailbox A, then deletes | message A1 in mailbox A, then expunges mailbox A, then deletes | |||
| message A2 in mailbox A, the human will expect that message A1 is | message A2 in mailbox A, the human will expect that message A1 is | |||
| gone and that message A2 is still present but is now deleted. | gone and that message A2 is still present but is now deleted. | |||
| By processing all the actions before proceeding with | By processing all the actions before proceeding with | |||
| synchronization, we avoid having to compensate for the local MUA's | synchronization, we avoid having to compensate for the local MUA's | |||
| skipping to change at line 224 ¶ | skipping to change at line 237 ¶ | |||
| synchronize itself will be the same no matter where the changes to | synchronize itself will be the same no matter where the changes to | |||
| the server's state originated. | the server's state originated. | |||
| 2). Steps a) and b) can be performed in parallel. Alternatively step a) | 2). Steps a) and b) can be performed in parallel. Alternatively step a) | |||
| can be performed after d). | can be performed after d). | |||
| 3). On step b) the set of "interesting" mailboxes pretty much has to be | 3). On step b) the set of "interesting" mailboxes pretty much has to be | |||
| determined by the human. What mailboxes belong to this set may | determined by the human. What mailboxes belong to this set may | |||
| vary between different IMAP4 sessions with the same server, | vary between different IMAP4 sessions with the same server, | |||
| client, and human. An interesting mailbox can be a mailbox | client, and human. An interesting mailbox can be a mailbox | |||
| returned by LSUB command. Special mailbox "INBOX" SHOULD always | returned by LSUB command. The special mailbox "INBOX" SHOULD always | |||
| be considered "interesting". | be considered "interesting". | |||
| 4). On step d-2-II) the client also finds out about | 4). On step d-2-II) the client also finds out about | |||
| changes to the flags of messages that the client already has in | changes to the flags of messages that the client already has in | |||
| its local cache, as well as finding out about messages in the | its local cache, as well as finding out about messages in the | |||
| local cache that no longer exist on the server (i.e., messages that | local cache that no longer exist on the server (i.e., messages that | |||
| have been expunged). | have been expunged). | |||
| 5). "Interesting" messages are those messages that the synchronization | 5). "Interesting" messages are those messages that the synchronization | |||
| program thinks the human wants to have cached locally, based on | program thinks the human wants to have cached locally, based on | |||
| the configuration and the data retrieved in step (b). | the configuration and the data retrieved in step (b). | |||
| 6). A disconnected IMAP client is a special case of an IMAP client, | ||||
| so it MUST be able to handle any "unexpected" unsolicited responses, | ||||
| like EXISTS and EXPUNGE, at any time. | ||||
| The disconnected client MAY ignore EXPUNGE response during | ||||
| "client-to-server" synchronization phase (step c)). | ||||
| The rest of this discussion will focus primarily on the synchronization | The rest of this discussion will focus primarily on the synchronization | |||
| issues for a single mailbox. | issues for a single mailbox. | |||
| 4. Mailbox synchronization steps and strategies | 4. Mailbox synchronization steps and strategies | |||
| 4.1. Checking UID Validity | 4.1. Checking UID Validity | |||
| The "UID validity" of a mailbox is a number returned in an | The "UID validity" of a mailbox is a number returned in an | |||
| UIDVALIDITY response code in an OK untagged response at mailbox | UIDVALIDITY response code in an OK untagged response at mailbox | |||
| selection time. The UID validity value changes between sessions when | selection time. The UID validity value changes between sessions when | |||
| skipping to change at line 259 ¶ | skipping to change at line 278 ¶ | |||
| Whenever the client selects a mailbox, the client must compare the | Whenever the client selects a mailbox, the client must compare the | |||
| returned UID validity value with the value stored in the local cache. | returned UID validity value with the value stored in the local cache. | |||
| If the UID validity values differ, the UIDs in the client's cache are | If the UID validity values differ, the UIDs in the client's cache are | |||
| no longer valid. The client MUST then empty the local cache of | no longer valid. The client MUST then empty the local cache of | |||
| that mailbox and remove any pending "actions" which refer to UIDs in | that mailbox and remove any pending "actions" which refer to UIDs in | |||
| that mailbox. The client MAY also issue a warning to the human. | that mailbox. The client MAY also issue a warning to the human. | |||
| The client MUST NOT cancel any scheduled uploads (i.e. APPENDs) for | The client MUST NOT cancel any scheduled uploads (i.e. APPENDs) for | |||
| the mailbox. | the mailbox. | |||
| Note that UIDVALIDITY is not only returned on a mailbox selection. | Note that UIDVALIDITY is not only returned on a mailbox selection. | |||
| COPYUID and APPENDUID response codes defined in [UIDPLUS] extension | The COPYUID and APPENDUID response codes defined in the [UIDPLUS] extension | |||
| (see also 4.2.2) and UIDVALIDITY STATUS response data item also contain | (see also 4.2.2) and the UIDVALIDITY STATUS response data item also contain | |||
| a UIDVALIDITY value for some other mailbox. The client SHOULD behave as | a UIDVALIDITY value for some other mailbox. The client SHOULD behave as | |||
| described in the previous paragraph (but it should act on the other mailbox's | described in the previous paragraph (but it should act on the other mailbox's | |||
| cache), no matter how it obtained the UIDVALIDITY value. | cache), no matter how it obtained the UIDVALIDITY value. | |||
| 4.2. Synchronizing local changes with the server | 4.2. Synchronizing local changes with the server | |||
| 4.2.1. Uploading messages to the mailbox | 4.2.1. Uploading messages to the mailbox | |||
| There are two most typical examples of operations that will result in message | Two of the most common examples of operations resulting in message | |||
| uploads: | uploads are: | |||
| 1) Saving a draft message | 1) Saving a draft message | |||
| 2) Message copy between remote mailboxes on two different IMAP servers | 2) Copying a message between remote mailboxes on two different IMAP servers | |||
| or a local mailbox and a remote mailbox. | or a local mailbox and a remote mailbox. | |||
| Message upload is performed with APPEND command. A message scheduled to be | Message upload is performed with the APPEND command. A message scheduled to be | |||
| uploaded has no UID associated with it, as all UIDs are assigned by the | uploaded has no UID associated with it, as all UIDs are assigned by the | |||
| server. The APPEND command will effectively associate a UID with the uploaded | server. The APPEND command will effectively associate a UID with the uploaded | |||
| message that can be stored in the local cache for a future reference. | message that can be stored in the local cache for future reference. | |||
| However [IMAP4] doesn't describe a simple mechanism to discover the message UID | However [IMAP4] doesn't describe a simple mechanism to discover the message UID | |||
| by just performing the APPEND command. In order to discover UID the client can | by just performing the APPEND command. In order to discover the UID the client can | |||
| do one of the following: | do one of the following: | |||
| 1) Remove the uploaded message from cache. After that use the mechanism described | 1) Remove the uploaded message from cache. After that use the mechanism described | |||
| in 4.3 to fetch the information about the uploaded message as if it was uploaded | in 4.3 to fetch the information about the uploaded message as if it had been uploaded | |||
| by some other client. | by some other client. | |||
| 2) Try to fetch header information as described in 4.2.2 in order to find a message | 2) Try to fetch header information as described in 4.2.2 in order to find a message | |||
| that corresponds to the uploaded message. One strategy of doing that is described | that corresponds to the uploaded message. One strategy for doing this is described | |||
| in 4.2.2. | in 4.2.2. | |||
| Case 1) describes a non particularly smart client. | Case 1) describes a not particularly smart client. | |||
| C: A003 APPEND Drafts (\Seen $MDNSent) {310} | C: A003 APPEND Drafts (\Seen $MDNSent) {310} | |||
| S: + Ready for literal data | S: + Ready for literal data | |||
| C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) | C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) | |||
| C: From: Fred Foobar <foobar@Blurdybloop.COM> | C: From: Fred Foobar <foobar@Blurdybloop.COM> | |||
| C: Subject: afternoon meeting | C: Subject: afternoon meeting | |||
| C: To: mooch@owatagu.siam.edu | C: To: mooch@owatagu.siam.edu | |||
| C: Message-Id: <B27397-0100000@Blurdybloop.COM> | C: Message-Id: <B27397-0100000@Blurdybloop.COM> | |||
| C: MIME-Version: 1.0 | C: MIME-Version: 1.0 | |||
| C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | |||
| C: | C: | |||
| C: Hello Joe, do you think we can meet at 3:30 tomorrow? | C: Hello Joe, do you think we can meet at 3:30 tomorrow? | |||
| C: | C: | |||
| S: A003 OK APPEND Completed | S: A003 OK APPEND Completed | |||
| Fortunately there is a simpler way to discover the message UID in the presence | Fortunately there is a simpler way to discover the message UID in the presence | |||
| of [UIDPLUS] extension: | of the [UIDPLUS] extension: | |||
| C: A003 APPEND Drafts (\Seen $MDNSent) {310} | C: A003 APPEND Drafts (\Seen $MDNSent) {310} | |||
| S: + Ready for literal data | S: + Ready for literal data | |||
| C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) | C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) | |||
| C: From: Fred Foobar <foobar@Blurdybloop.COM> | C: From: Fred Foobar <foobar@Blurdybloop.COM> | |||
| C: Subject: afternoon meeting | C: Subject: afternoon meeting | |||
| C: To: mooch@owatagu.siam.edu | C: To: mooch@owatagu.siam.edu | |||
| C: Message-Id: <B27397-0100000@Blurdybloop.COM> | C: Message-Id: <B27397-0100000@Blurdybloop.COM> | |||
| C: MIME-Version: 1.0 | C: MIME-Version: 1.0 | |||
| C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | |||
| C: | C: | |||
| C: Hello Joe, do you think we can meet at 3:30 tomorrow? | C: Hello Joe, do you think we can meet at 3:30 tomorrow? | |||
| C: | C: | |||
| S: A003 OK APPEND [APPENDUID 1022843275 77712] completed | S: A003 OK [APPENDUID 1022843275 77712] APPEND completed | |||
| The UID of the appended message is the second parameter of APPENDUID response code. | The UID of the appended message is the second parameter of APPENDUID | |||
| response code. | ||||
| 4.2.2. Optimizing "move" and "copy" operations | 4.2.2. Optimizing "move" and "copy" operations | |||
| Practical experience with IMAP, and other mailbox access | Practical experience with IMAP, and other mailbox access | |||
| protocols that support multiple mailboxes suggests that moving a | protocols that support multiple mailboxes suggests that moving a | |||
| message from one mailbox to another is an extremely common operation. | message from one mailbox to another is an extremely common operation. | |||
| 4.2.2.1. Moving a message between two mailboxes on the same server | 4.2.2.1. Moving a message between two mailboxes on the same server | |||
| In IMAP4 a "move" operation between two mailboxes on the same server | In IMAP4 a "move" operation between two mailboxes on the same server | |||
| is really a combination of a COPY operation and a STORE +FLAGS (\Deleted) | is really a combination of a COPY operation and a STORE +FLAGS (\Deleted) | |||
| operation. This makes good protocol sense for IMAP, but it leaves | operation. This makes good protocol sense for IMAP, but it leaves | |||
| a simple-minded disconnected client in the silly position of deleting | a simple-minded disconnected client in the silly position of deleting | |||
| and possibly expunging its cached copy of a message, then fetching | and possibly expunging its cached copy of a message, then fetching | |||
| an identical copy via the network. | an identical copy via the network. | |||
| However, the presence of UIDPLUS extension support in the server can help: | However, the presence of the UIDPLUS extension in the server can help: | |||
| C: A001 UID COPY 567,414 "Interesting Messages" | C: A001 UID COPY 567,414 "Interesting Messages" | |||
| S: A001 OK [COPYUID 1022843275 414,567 5:6] Completed | S: A001 OK [COPYUID 1022843275 414,567 5:6] Completed | |||
| This tells the client that the message with UID 414 in the current mailbox | This tells the client that the message with UID 414 in the current mailbox | |||
| was successfully copied to the mailbox "Interesting Messages" and was given | was successfully copied to the mailbox "Interesting Messages" and was given | |||
| the UID 5, and that the message with UID 567 was given the UID 6. | the UID 5, and that the message with UID 567 was given the UID 6. | |||
| In the absence of UIDPLUS extension support in the server the following | In the absence of UIDPLUS extension support in the server the following | |||
| trick can be used. By including the Message-ID: header and the INTERNALDATE | trick can be used. By including the Message-ID: header and the INTERNALDATE | |||
| data item as part of the descriptor, the client can check the descriptor | data item as part of the descriptor, the client can check the descriptor | |||
| of a "new" message against messages that are already in its cache, and | of a "new" message against messages that are already in its cache, and | |||
| avoid fetching the extra copy. Of course, it's possible that the | avoid fetching the extra copy. Of course, it's possible that the | |||
| cost of checking to see if the message is already in the local cache | cost of checking to see if the message is already in the local cache | |||
| may exceed the cost of just fetching it, so this technique should not | may exceed the cost of just fetching it, so this technique should not | |||
| be used blindly. If the MUA implements a "move" command, it make | be used blindly. If the MUA implements a "move" command, it makes | |||
| special provisions to use this technique when it knows that a | special provisions to use this technique when it knows that a | |||
| copy/delete sequence is the result of a "move" command. | copy/delete sequence is the result of a "move" command. | |||
| Note, that servers are not required (although they are strongly encouraged | Note, that servers are not required (although they are strongly encouraged | |||
| with "SHOULD language") to preserve INTERNALDATE when copying messages. | with "SHOULD language") to preserve INTERNALDATE when copying messages. | |||
| Also note, since it's theoretically possible for this algorithm to find | Also note, since it's theoretically possible for this algorithm to find | |||
| the wrong message (given sufficiently malignant Message-ID headers), | the wrong message (given sufficiently malignant Message-ID headers), | |||
| implementors should provide a way to disable this optimization, both | implementors should provide a way to disable this optimization, both | |||
| permanently and on a message-by-message basis. | permanently and on a message-by-message basis. | |||
| Example: Copying a message in the absence of UIDPLUS extension. | Example: Copying a message in the absence of UIDPLUS extension. | |||
| At some point in time the client has fetch the source message | At some point in time the client has fetch the source message | |||
| and some information was cached: | and some information was cached: | |||
| C: C021 UID FETCH <uids> (RFC822 INTERNALDATE FLAGS) | C: C021 UID FETCH <uids> (BODY.PEEK[] INTERNALDATE FLAGS) | |||
| ... | ... | |||
| S: * 27 FETCH (UID 123 INTERNALDATE "31-May-2002 05:26:59 -0600" | S: * 27 FETCH (UID 123 INTERNALDATE "31-May-2002 05:26:59 -0600" | |||
| FLAGS (\Seen $MDNSent) RFC822 {1036} | FLAGS (\Draft $MDNSent) BODY[] {1036} | |||
| S: ... | S: ... | |||
| S: Message-Id: <20040903110856.22a127cd@chardonnay> | S: Message-Id: <20040903110856.22a127cd@chardonnay> | |||
| S: ... | S: ... | |||
| S: ...message body... | S: ...message body... | |||
| S: ) | S: ) | |||
| ... | ... | |||
| S: C021 OK fetch completed | S: C021 OK fetch completed | |||
| Later on the client decides to copy the message: | Later on the client decides to copy the message: | |||
| skipping to change at line 400 ¶ | skipping to change at line 420 ¶ | |||
| As the server hasn't provided the COPYUID response code, the client | As the server hasn't provided the COPYUID response code, the client | |||
| tries the optimization described above: | tries the optimization described above: | |||
| C: C036 SELECT "Interesting Messages" | C: C036 SELECT "Interesting Messages" | |||
| ... | ... | |||
| C: C037 UID SEARCH ON 31-May-2002 HEADER | C: C037 UID SEARCH ON 31-May-2002 HEADER | |||
| "Message-Id" "20040903110856.22a127cd@chardonnay" | "Message-Id" "20040903110856.22a127cd@chardonnay" | |||
| S: SEARCH 12368 | S: SEARCH 12368 | |||
| S: C037 OK completed | S: C037 OK completed | |||
| Note, that the client should use the returned UID if and only if | Note, that if the server has returned multiple UIDs in the SEARCH | |||
| the server returns a single UID in the SEARCH response. | response the client MUST NOT use any of the returned UID. | |||
| 4.2.2.2. Moving a message from a remote mailbox to a local | 4.2.2.2. Moving a message from a remote mailbox to a local | |||
| Moving a message from a remote mailbox to a local is done with FETCH | Moving a message from a remote mailbox to a local is done with FETCH | |||
| (that includes FLAGS and INTERNALDATE) followed by | (that includes FLAGS and INTERNALDATE) followed by | |||
| UID STORE <uid> +FLAGS.SILENT (\Deleted): | UID STORE <uid> +FLAGS.SILENT (\Deleted): | |||
| C: A003 UID FETCH 123 (RFC822 INTERNALDATE FLAGS) | C: A003 UID FETCH 123 (BODY.PEEK[] INTERNALDATE FLAGS) | |||
| S: * 27 FETCH (UID 123 INTERNALDATE "31-May-2002 05:26:59 -0600" | S: * 27 FETCH (UID 123 INTERNALDATE "31-May-2002 05:26:59 -0600" | |||
| FLAGS (\Seen $MDNSent) RFC822 | FLAGS (\Seen $MDNSent) BODY[] | |||
| S: ...message body... | S: ...message body... | |||
| S: ) | S: ) | |||
| S: A003 OK UID FETCH completed | S: A003 OK UID FETCH completed | |||
| C: A004 UID STORE <uid> +FLAGS.SILENT (\Deleted) | C: A004 UID STORE <uid> +FLAGS.SILENT (\Deleted) | |||
| S: A004 STORE completed | S: A004 STORE completed | |||
| Note, that there is no reason to fetch the message during synchronization | Note, that there is no reason to fetch the message during synchronization | |||
| if it already in the client's cache. Also, the client SHOULD preserve | if it's already in the client's cache. Also, the client SHOULD preserve | |||
| delivery date in the local cache. | delivery date in the local cache. | |||
| 4.2.2.3. Moving a message from a local mailbox to a remote | 4.2.2.3. Moving a message from a local mailbox to a remote | |||
| Moving a message from a local mailbox to a remote is done with APPEND: | Moving a message from a local mailbox to a remote is done with APPEND: | |||
| C: A003 APPEND Drafts (\Seen $MDNSent) "31-May-2002 05:26:59 -0600" {310} | C: A003 APPEND Drafts (\Seen $MDNSent) "31-May-2002 05:26:59 -0600" {310} | |||
| S: + Ready for literal data | S: + Ready for literal data | |||
| C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) | C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) | |||
| C: From: Fred Foobar <foobar@Blurdybloop.COM> | C: From: Fred Foobar <foobar@Blurdybloop.COM> | |||
| C: Subject: afternoon meeting | C: Subject: afternoon meeting | |||
| C: To: mooch@owatagu.siam.edu | C: To: mooch@owatagu.siam.edu | |||
| C: Message-Id: <B27397-0100000@Blurdybloop.COM> | C: Message-Id: <B27397-0100000@Blurdybloop.COM> | |||
| C: MIME-Version: 1.0 | C: MIME-Version: 1.0 | |||
| C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | |||
| C: | C: | |||
| C: Hello Joe, do you think we can meet at 3:30 tomorrow? | C: Hello Joe, do you think we can meet at 3:30 tomorrow? | |||
| C: | C: | |||
| S: A003 OK APPEND [APPENDUID 1022843275 77712] completed | S: A003 OK [APPENDUID 1022843275 77712] completed | |||
| The client SHOULD specify delivery date from the local cache in the APPEND. | The client SHOULD specify delivery date from the local cache in the APPEND. | |||
| 4.2.2.4. Moving a message between two mailbox on two different servers | If the [LITERAL+] extension is available, the client can save a round trip*: | |||
| C: A003 APPEND Drafts (\Seen $MDNSent) "31-May-2002 05:26:59 -0600" {310+} | ||||
| 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 [APPENDUID 1022843275 77712] completed | ||||
| * - Note that there is a risk that the server will reject the message due to | ||||
| its size. If this happens, the client will waste bandwidth transferring | ||||
| the whole message. If the client wouldn't have used the LITERAL+, this | ||||
| could have been avoided: | ||||
| C: A003 APPEND Drafts (\Seen $MDNSent) "31-May-2004 05:26:59 -0600" | ||||
| {16777215} | ||||
| S: A003 NO Sorry, message is too big | ||||
| 4.2.2.4. Moving a message between two mailboxes on different servers | ||||
| Moving a message between two mailbox on two different servers is a | Moving a message between two mailbox on two different servers is a | |||
| combination of the operations described in 4.2.2.2 followed by the | combination of the operations described in 4.2.2.2 followed by the | |||
| operations described in 4.2.2.3. | operations described in 4.2.2.3. | |||
| 4.2.2.5. Uploading multiple messages to a remote mailbox with MULTIAPPEND | 4.2.2.5. Uploading multiple messages to a remote mailbox with MULTIAPPEND | |||
| When there is a need to upload multiple messages to a remote mailbox | When there is a need to upload multiple messages to a remote mailbox | |||
| (e.g. as per 4.2.2.3), the presence of certain IMAP extensions may | (e.g. as per 4.2.2.3), the presence of certain IMAP extensions may | |||
| significantly improve performance. One of them is [MULTIAPPEND]. | significantly improve performance. One of them is [MULTIAPPEND]. | |||
| skipping to change at line 469 ¶ | skipping to change at line 513 ¶ | |||
| Also, if the server supports both [MULTIAPPEND] and [LITERAL+] extensions, | Also, if the server supports both [MULTIAPPEND] and [LITERAL+] extensions, | |||
| the entire upload is accomplished in a single command/response round trip. | the entire upload is accomplished in a single command/response round trip. | |||
| Note: Client implementors should be aware, that [MULTIAPPEND] performs | Note: Client implementors should be aware, that [MULTIAPPEND] performs | |||
| append of multiple messages atomically. This means, for example, | append of multiple messages atomically. This means, for example, | |||
| if there is not enough space to save "n"-th message (or the message | if there is not enough space to save "n"-th message (or the message | |||
| has invalid structure and is rejected by the server) after successful | has invalid structure and is rejected by the server) after successful | |||
| upload of "n-1" messages, the whole upload operation fails and no | upload of "n-1" messages, the whole upload operation fails and no | |||
| message will be saved in the mailbox. Although, this behavior might | message will be saved in the mailbox. Although, this behavior might | |||
| be desirable in certain situations, it might not be what you want. | be desirable in certain situations, it might not be what you want. | |||
| Otherwise, the client should use the regular APPEND command (Section | ||||
| 4.2.2.3), possibly utilizing the [LITERAL+] extension. | ||||
| See also section 5.1 for discussions about error recovery. | See also section 5.1 for discussions about error recovery. | |||
| Note: MULTIAPPEND can be used together with UIDPLUS extension in a way | Note: MULTIAPPEND can be used together with the UIDPLUS extension in a way | |||
| similar to what was described in section 4.2.1. [MULTIAPPEND] | similar to what was described in section 4.2.1. [MULTIAPPEND] | |||
| extends syntax of APPENDUID response code to allow for multiple | extends the syntax of the APPENDUID response code to allow for multiple | |||
| message UIDs in the second parameter. | message UIDs in the second parameter. | |||
| Example: | Example: | |||
| An example below demonstrates the use of MULTIAPPEND together with | An example below demonstrates the use of MULTIAPPEND together with | |||
| UIDPLUS (synchronization points where the client waits for confirmations | UIDPLUS (synchronization points where the client waits for confirmations | |||
| from the server are marked with "<--->"): | from the server are marked with "<--->"): | |||
| C: A003 APPEND Jan-2002 (\Seen $MDNSent) "31-May-2002 05:26:59 -0600" {310} | C: A003 APPEND Jan-2002 (\Seen $MDNSent) "31-May-2002 05:26:59 -0600" {310} | |||
| <---> | <---> | |||
| S: + Ready for literal data | S: + Ready for literal data | |||
| skipping to change at line 506 ¶ | skipping to change at line 552 ¶ | |||
| C: Date: Mon, 7 Feb 1994 22:43:04 -0800 (PST) | C: Date: Mon, 7 Feb 1994 22:43:04 -0800 (PST) | |||
| C: From: Joe Mooch <mooch@OWaTaGu.siam.EDU> | C: From: Joe Mooch <mooch@OWaTaGu.siam.EDU> | |||
| C: Subject: Re: afternoon meeting | C: Subject: Re: afternoon meeting | |||
| C: To: foobar@blurdybloop.com | C: To: foobar@blurdybloop.com | |||
| C: Message-Id: <a0434793874930@OWaTaGu.siam.EDU> | C: Message-Id: <a0434793874930@OWaTaGu.siam.EDU> | |||
| C: MIME-Version: 1.0 | C: MIME-Version: 1.0 | |||
| C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | |||
| C: | C: | |||
| C: 3:30 is fine with me. | C: 3:30 is fine with me. | |||
| C: | C: | |||
| S: A003 OK APPEND [APPENDUID 1022843275 77712,77713] completed | S: A003 OK [APPENDUID 1022843275 77712,77713] completed | |||
| The upload takes 3 round trips. | The upload takes 3 round trips. | |||
| Example: | Example: | |||
| The example above was modified for the case when the server supports | The example above was modified for the case when the server supports | |||
| MULTIAPPEND, LITERAL+ and UIDPLUS. The upload takes only 1 round trip. | MULTIAPPEND, LITERAL+ and UIDPLUS. The upload takes only 1 round trip. | |||
| C: A003 APPEND Jan-2002 (\Seen $MDNSent) "31-May-2002 05:26:59 -0600" {310+} | C: A003 APPEND Jan-2002 (\Seen $MDNSent) "31-May-2002 05:26:59 -0600" {310+} | |||
| C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) | C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST) | |||
| C: From: Fred Foobar <foobar@Blurdybloop.COM> | C: From: Fred Foobar <foobar@Blurdybloop.COM> | |||
| skipping to change at line 535 ¶ | skipping to change at line 581 ¶ | |||
| C: Date: Mon, 7 Feb 1994 22:43:04 -0800 (PST) | C: Date: Mon, 7 Feb 1994 22:43:04 -0800 (PST) | |||
| C: From: Joe Mooch <mooch@OWaTaGu.siam.EDU> | C: From: Joe Mooch <mooch@OWaTaGu.siam.EDU> | |||
| C: Subject: Re: afternoon meeting | C: Subject: Re: afternoon meeting | |||
| C: To: foobar@blurdybloop.com | C: To: foobar@blurdybloop.com | |||
| C: Message-Id: <a0434793874930@OWaTaGu.siam.EDU> | C: Message-Id: <a0434793874930@OWaTaGu.siam.EDU> | |||
| C: MIME-Version: 1.0 | C: MIME-Version: 1.0 | |||
| C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII | |||
| C: | C: | |||
| C: 3:30 is fine with me. | C: 3:30 is fine with me. | |||
| C: | C: | |||
| S: A003 OK APPEND [APPENDUID 1022843275 77712,77713] completed | S: A003 OK [APPENDUID 1022843275 77712,77713] completed | |||
| 4.2.3. Replaying local flag changes | 4.2.3. Replaying local flag changes | |||
| The disconnected client uses STORE command to synchronize local flag state | The disconnected client uses STORE command to synchronize local flag state | |||
| with the server. The disconnected client SHOULD use +FLAGS.SILENT or -FLAGS.SILENT | with the server. The disconnected client SHOULD use +FLAGS.SILENT or -FLAGS.SILENT | |||
| in order to set or unset flags modified by the user while offline. FLAGS | in order to set or unset flags modified by the user while offline. The FLAGS | |||
| form must not be used, as there is a risk that this will overwrite flags | form MUST NOT be used, as there is a risk that this will overwrite flags | |||
| on the server that has been changed by some other client. | on the server that has been changed by some other client. | |||
| Example: | Example: | |||
| For the message with UID 15, the disconnected client stores the following | For the message with UID 15, the disconnected client stores the following | |||
| flags \Seen and $Highest. The flags were modified on the server by some other | flags \Seen and $Highest. The flags were modified on the server by some other | |||
| client: \Seen, \Answered and $Highest. | client: \Seen, \Answered and $Highest. | |||
| While offline the user requested to remove $Highest flags and to add \Deleted. | While offline the user requested to remove $Highest flags and to add \Deleted. | |||
| The flag synchronization sequence for the message should look like: | The flag synchronization sequence for the message should look like: | |||
| C: A001 UID STORE 15 +FLAGS.SILENT (\Deleted) | C: A001 UID STORE 15 +FLAGS.SILENT (\Deleted) | |||
| skipping to change at line 584 ¶ | skipping to change at line 630 ¶ | |||
| issues: | issues: | |||
| C: A003 UID STORE 15 -FLAGS.SILENT ($Personal $Work $Spam) | C: A003 UID STORE 15 -FLAGS.SILENT ($Personal $Work $Spam) | |||
| S: A003 STORE completed | S: A003 STORE completed | |||
| 4.2.4. Processing mailbox compression (EXPUNGE) requests | 4.2.4. Processing mailbox compression (EXPUNGE) requests | |||
| A naive disconnected client implementation that supports compressing a mailbox | A naive disconnected client implementation that supports compressing a mailbox | |||
| while offline may decide to issue an EXPUNGE command to the server in order | while offline may decide to issue an EXPUNGE command to the server in order | |||
| to expunge messages marked \Deleted. The problem with this command during | to expunge messages marked \Deleted. The problem with this command during | |||
| synchronization is that it permanently erases all messages with \Deleted flag set, | synchronization is that it permanently erases all messages with the \Deleted flag set, | |||
| i.e. even those messages that were marked as \Deleted on the server while the user | i.e. even those messages that were marked as \Deleted on the server while the user | |||
| was offline. Doing so might lead the user to an unpleasant surprise. | was offline. Doing this might result in an unpleasant surprise for the user. | |||
| Fortunately [UIDPLUS] extension can help in this case as well. The extension | Fortunately the [UIDPLUS] extension can help in this case as well. The extension | |||
| introduces UID EXPUNGE command, that, unlike EXPUNGE, takes a UID set parameter, | introduces UID EXPUNGE command, that, unlike EXPUNGE, takes a UID set parameter, | |||
| that lists UIDs of all messages that can be expunged. When processing this command | that lists UIDs of all messages that can be expunged. When processing this command | |||
| server erases only messages with \Deleted flag listed in the UID list. Thus, | the server erases only messages with \Deleted flag listed in the UID list. Thus, | |||
| a message not listed in the UID set will not be expunged even if it has \Deleted | messages not listed in the UID set will not be expunged even if they have the \Deleted | |||
| flag set. | flag set. | |||
| Example: While offline 3 messages with UIDs 7, 27 and 65 were marked \Deleted | Example: While offline 3 messages with UIDs 7, 27 and 65 were marked \Deleted | |||
| when the user requested to compress the open mailbox. Another client marked | when the user requested to compress the open mailbox. Another client marked | |||
| a message \Deleted on the server (UID 34). During synchronization the | a message \Deleted on the server (UID 34). During synchronization the | |||
| disconnected client issues: | disconnected client issues: | |||
| C: A001 UID EXPUNGE 7,27,65 | C: A001 UID EXPUNGE 7,27,65 | |||
| S: * ... EXPUNGE | S: * ... EXPUNGE | |||
| S: * ... EXPUNGE | S: * ... EXPUNGE | |||
| skipping to change at line 619 ¶ | skipping to change at line 665 ¶ | |||
| Before: | Before: | |||
| C: B001 UID SEARCH DELETED | C: B001 UID SEARCH DELETED | |||
| S: * SEARCH 65 34 27 7 | S: * SEARCH 65 34 27 7 | |||
| S: B001 UID SEARCH completed | S: B001 UID SEARCH completed | |||
| After: | After: | |||
| C: B002 UID SEARCH DELETED | C: B002 UID SEARCH DELETED | |||
| S: * SEARCH 34 | S: * SEARCH 34 | |||
| S: B002 UID SEARCH completed | S: B002 UID SEARCH completed | |||
| In the absence of [UIDPLUS] extension the following sequence of command can be | In the absence of the [UIDPLUS] extension the following sequence of command can be | |||
| used as an approximation. Note, that when this sequence is performed, there is a | used as an approximation. Note: It's possible for another client to mark additional | |||
| possibility that another client marks additional messages as deleted and these | messages as deleted while this sequence is being performed. In this case, these | |||
| messages will be expunged as well. | additional messages will be expunged as well. | |||
| 1). Find all messages marked \Deleted on the server: | 1). Find all messages marked \Deleted on the server: | |||
| C: A001 UID SEARCH DELETED | C: A001 UID SEARCH DELETED | |||
| S: * SEARCH 65 34 27 7 | S: * SEARCH 65 34 27 7 | |||
| S: A001 UID SEARCH completed | S: A001 UID SEARCH completed | |||
| 2). Find all messages that must not be erased (for the previous example | 2). Find all messages that must not be erased (for the previous example | |||
| the list will consist of the message with UID 34) | the list will consist of the message with UID 34) | |||
| skipping to change at line 755 ¶ | skipping to change at line 801 ¶ | |||
| (FLAGS BODYSTRUCTURE INTERNALDATE RFC822.SIZE) | (FLAGS BODYSTRUCTURE INTERNALDATE RFC822.SIZE) | |||
| ... | ... | |||
| ... | ... | |||
| C: A0FF UID fetch <lastseenuid+901>:<uidnext> | C: A0FF UID fetch <lastseenuid+901>:<uidnext> | |||
| (FLAGS BODYSTRUCTURE INTERNALDATE RFC822.SIZE) | (FLAGS BODYSTRUCTURE INTERNALDATE RFC822.SIZE) | |||
| Note, that without issuing a SEARCH command it is not possible to | Note, that without issuing a SEARCH command it is not possible to | |||
| determine how many messages will fall into a subrange, as UIDs are | determine how many messages will fall into a subrange, as UIDs are | |||
| not necessarily contiguous. | not necessarily contiguous. | |||
| The second FETCH command will result in nil or more untagged fetch | Note #2: The client SHOULD ignore any unsolicited EXPUNGE responses | |||
| received during the first FETCH command. EXPUNGE responses contain | ||||
| message numbers which are useless to a client that doesn't have | ||||
| the message-number-to-UID translation table. | ||||
| The second FETCH command will result in zero or more untagged fetch | ||||
| responses. Each response will have a corresponding UID FETCH data item. | responses. Each response will have a corresponding UID FETCH data item. | |||
| All messages that didn't have a matching untagged FETCH response | All messages that didn't have a matching untagged FETCH response | |||
| MUST be removed from the local cache. | MUST be removed from the local cache. | |||
| For example, if the <lastseenuid> had a value 15000 and the local cache | For example, if the <lastseenuid> had a value 15000 and the local cache | |||
| contained 3 messages with the UIDs 12, 777 and 14999 respectively, than | contained 3 messages with the UIDs 12, 777 and 14999 respectively, than | |||
| after receiving the following responses from the server: | after receiving the following responses from the server: | |||
| S: * 1 FETCH (UID 12 FLAGS (\Seen)) | S: * 1 FETCH (UID 12 FLAGS (\Seen)) | |||
| S: * 2 FETCH (UID 777 FLAGS (\Answered \Deleted)) | S: * 2 FETCH (UID 777 FLAGS (\Answered \Deleted)) | |||
| the client must remove the message with UID 14999 from its local cache. | the client must remove the message with UID 14999 from its local cache. | |||
| Note #2: If the client is not interested in flag changes (i.e. the client | Note #3: If the client is not interested in flag changes (i.e. the client | |||
| only wants to know which old messages are still on the server), the second | only wants to know which old messages are still on the server), the second | |||
| FETCH command can be substituted with: | FETCH command can be substituted with: | |||
| tag2 UID SEARCH UID 1:<lastseenuid> | tag2 UID SEARCH UID 1:<lastseenuid> | |||
| This command will generate less traffic. However an implementor should be | This command will generate less traffic. However an implementor should be | |||
| aware that in order to build the mapping table from message numbers to UIDs | aware that in order to build the mapping table from message numbers to UIDs | |||
| the output of the SEARCH command MUST be sorted first, because there is | the output of the SEARCH command MUST be sorted first, because there is | |||
| no requirement for a server to return UIDs in SEARCH response in any | no requirement for a server to return UIDs in SEARCH response in any | |||
| particular order. | particular order. | |||
| 4.3.2. Searching for "interesting" messages. | 4.3.2. Searching for "interesting" messages. | |||
| This step is either performed entirely on the client (from the information received | This step is either performed entirely on the client (from the information received | |||
| in step 4.3.1), after performing additional searches on the server or both. | in step 4.3.1), entirely on the server or some combination of both. | |||
| The decision on what is an "interesting" message is up to the client software | The decision on what is an "interesting" message is up to the client software | |||
| and the human. One easy criterion that should probably be implemented in any | and the human. One easy criterion that should probably be implemented in any | |||
| client is whether the message is "too big" for automatic retrieval, where "too big" | client is whether the message is "too big" for automatic retrieval, where "too big" | |||
| is a parameter defined in the client's configuration. | is a parameter defined in the client's configuration. | |||
| Another commonly used criteria is the age of a message. For example, the client | Another commonly used criterion is the age of a message. For example, the client | |||
| may choose to download only messages received in the last week (in this case, <date> | may choose to download only messages received in the last week (in this case, <date> | |||
| would be today's date minus 7 days): | would be today's date minus 7 days): | |||
| tag3 UID SEARCH UID <uidset> SINCE <date> | tag3 UID SEARCH UID <uidset> SINCE <date> | |||
| Keep in mind that a date search disregards time and timezone. | Keep in mind that a date search disregards time and timezone. | |||
| The client can avoid doing this search if it specified INTERNALDATE in <descriptors> | The client can avoid doing this search if it specified INTERNALDATE in <descriptors> | |||
| on step 4.3.1. If the client did, it can perform the search itself. | on step 4.3.1. If the client did, it can perform the local search on its message cache. | |||
| At this step the client also decides what kind of information about a particular | At this step the client also decides what kind of information about a particular | |||
| message to fetch from the server. In particular, even for a message that is considered | message to fetch from the server. In particular, even for a message that is considered | |||
| to be "too big" the client MAY choose to fetch some part(s) of it. For example, | to be "too big" the client MAY choose to fetch some part(s) of it. For example, | |||
| if the message is a multipart/mixed containing a text part and a MPEG attachment, | if the message is a multipart/mixed containing a text part and a MPEG attachment, | |||
| there is no reason for the client not to fetch the text part. The decision of which | there is no reason for the client not to fetch the text part. The decision of which | |||
| part should or should not be fetched can be based on the information received in | part should or should not be fetched can be based on the information received in | |||
| BODYSTRUCTURE FETCH response data item (i.e. if BODYSTRUCTURE was included in | the BODYSTRUCTURE FETCH response data item (i.e. if BODYSTRUCTURE was included in | |||
| <descriptors> on step 4.3.1). | <descriptors> on step 4.3.1). | |||
| 4.3.3. Populating cache with "interesting" messages. | 4.3.3. Populating cache with "interesting" messages. | |||
| Once the client found out which messages are "interesting", the client | Once the client has found out which messages are "interesting", it | |||
| can start issuing appropriate FETCH commands for "interesting" messages or | can start issuing appropriate FETCH commands for "interesting" messages or | |||
| bodyparts thereof. | parts thereof. | |||
| It is important to note that fetching a message into the disconnected | It is important to note that fetching a message into the disconnected | |||
| client's local cache does NOT imply that the human has (or even will) | client's local cache does NOT imply that the human has (or even will) | |||
| read the message. Thus, the synchronization program for a | read the message. Thus, the synchronization program for a | |||
| disconnected client should always be careful to use the .PEEK | disconnected client should always be careful to use the .PEEK | |||
| variants of the FETCH data items that implicitly set the \Seen flag. | variants of the FETCH data items that implicitly set the \Seen flag. | |||
| Once the last descriptor has arrived and the last FETCH command has | Once the last descriptor has arrived and the last FETCH command has | |||
| been issued, the client simply needs to process the incoming fetch | been issued, the client simply needs to process the incoming fetch | |||
| items, using them to update the local message cache. | items, using them to update the local message cache. | |||
| skipping to change at line 834 ¶ | skipping to change at line 885 ¶ | |||
| In order to avoid deadlock problems, the client must give processing | In order to avoid deadlock problems, the client must give processing | |||
| of received messages priority over issuing new FETCH commands during | of received messages priority over issuing new FETCH commands during | |||
| this synchronization process. This may necessitate temporary local | this synchronization process. This may necessitate temporary local | |||
| queuing of FETCH requests that cannot be issued without causing a | queuing of FETCH requests that cannot be issued without causing a | |||
| deadlock. In order to achieve the best use of the "expensive" network | deadlock. In order to achieve the best use of the "expensive" network | |||
| connection, the client will almost certainly need to pay careful | connection, the client will almost certainly need to pay careful | |||
| attention to any flow-control information that it can obtain from the | attention to any flow-control information that it can obtain from the | |||
| underlying transport connection (usually a TCP connection). | underlying transport connection (usually a TCP connection). | |||
| Note: The requirement stated in the previous paragraph might result in | Note: The requirement stated in the previous paragraph might result in | |||
| unpleasant user's experience, if followed blindly. For example, the | an unpleasant user experience, if followed blindly. For example, the | |||
| user might be unwilling to wait for the client to finish synchronization | user might be unwilling to wait for the client to finish synchronization | |||
| before starting to process user's requests. A smart disconnected client | before starting to process the user's requests. A smart disconnected client | |||
| should allow the user to perform requested operations in between IMAP | should allow the user to perform requested operations in between IMAP | |||
| commands which are part of the synchronization process. See also the | commands which are part of the synchronization process. See also the | |||
| Note #1 in section 4.3.1. | Note #1 in section 4.3.1. | |||
| Example: After fetching a message BODYSTRUCTURE the client discovers | Example: After fetching a message BODYSTRUCTURE the client discovers | |||
| a complex MIME message. Than it decides to fetch MIME headers | a complex MIME message. Than it decides to fetch MIME headers | |||
| of the nested MIME messages and some body parts. | of the nested MIME messages and some body parts. | |||
| C: A011 UID fetch 11 (BODYSTRUCTURE) | C: A011 UID fetch 11 (BODYSTRUCTURE) | |||
| S: ... | S: ... | |||
| skipping to change at line 863 ¶ | skipping to change at line 914 ¶ | |||
| S: ... | S: ... | |||
| C: A013 UID fetch 11 (BODY[1.1] BODY[1.2]) | C: A013 UID fetch 11 (BODY[1.1] BODY[1.2]) | |||
| S: ... | S: ... | |||
| C: A014 UID fetch 11 (BODY[3] BODY[4] BODY[5] BODY[6] BODY[7] BODY[8] | C: A014 UID fetch 11 (BODY[3] BODY[4] BODY[5] BODY[6] BODY[7] BODY[8] | |||
| BODY[9] BODY[10] BODY[11] BODY[13] BODY[14] BODY[15] BODY[16] | BODY[9] BODY[10] BODY[11] BODY[13] BODY[14] BODY[15] BODY[16] | |||
| BODY[21]) | BODY[21]) | |||
| S: ... | S: ... | |||
| 4.3.4. User initiated synchronization | 4.3.4. User initiated synchronization | |||
| After the client finished the main synchronization that was described in | After the client has finished the main synchronization process as described in | |||
| 4.3.1-4.3.3 the user may optionally request additional synchronization steps | 4.3.1-4.3.3, the user may optionally request additional synchronization steps | |||
| while the client is still online. This is not any different from the process | while the client is still online. This is not any different from the process | |||
| described in 4.3.2 and 4.3.3. | described in 4.3.2 and 4.3.3. | |||
| Typical examples are: | Typical examples are: | |||
| 1) fetch all messages selected in UI. | 1) fetch all messages selected in UI. | |||
| 2) fetch all messages marked as \Flagged on the server. | 2) fetch all messages marked as \Flagged on the server. | |||
| 4.4. Special case: descriptor-only synchronization | 4.4. Special case: descriptor-only synchronization | |||
| For some mailboxes, fetching the descriptors might be the entire | For some mailboxes, fetching the descriptors might be the entire | |||
| synchronization step. Practical experience with IMAP has shown that | synchronization step. Practical experience with IMAP has shown that | |||
| a certain class of mailboxes (e.g., "archival" mailboxes) are used | a certain class of mailboxes (e.g., "archival" mailboxes) are used | |||
| primarily for long-term storage of important messages that the human | primarily for long-term storage of important messages that the human | |||
| wants to have instantly available on demand but does not want | wants to have instantly available on demand but does not want | |||
| cluttering up the disconnected client's cache at any other time. | cluttering up the disconnected client's cache at any other time. | |||
| Messages in this kind of mailbox would be fetched exclusively by | Messages in this kind of mailbox would be fetched exclusively by | |||
| explicit actions queued by the local MUA. Thus, the only | explicit actions queued by the local MUA. Thus, the only | |||
| synchronization that is necessary for a mailbox of this kind is | synchronization desirable on this kind of mailbox is fetching enough | |||
| fetching the descriptor information that the human will use to | descriptor information for the user to be able to identify messages | |||
| identify messages that should be explicitly fetched. | for subsequent download. | |||
| Special mailboxes that receive traffic from a high volume, low | Special mailboxes that receive messages from a high volume, low | |||
| priority mailing list might also be in this category, at least when | priority mailing list might also be in this category, at least when | |||
| the human is in a hurry. | the human is in a hurry. | |||
| 4.5. Special case: fast new-only synchronization | 4.5. Special case: fast new-only synchronization | |||
| In some cases the human might be in such a hurry that s/he doesn't | In some cases the human might be in such a hurry that s/he doesn't | |||
| care about changes to old messages, just about new messages. In this | care about changes to old messages, just about new messages. In this | |||
| case, the client can skip the UID FETCH command that obtains the | case, the client can skip the UID FETCH command that obtains the | |||
| flags and UIDs for old messages (1:<lastseenuid>). | flags and UIDs for old messages (1:<lastseenuid>). | |||
| skipping to change at line 909 ¶ | skipping to change at line 960 ¶ | |||
| In some cases the human may know (for whatever reason) that s/he | In some cases the human may know (for whatever reason) that s/he | |||
| always wants to fetch any new messages in a particular mailbox, | always wants to fetch any new messages in a particular mailbox, | |||
| unconditionally. In this case, the client can just fetch the | unconditionally. In this case, the client can just fetch the | |||
| messages themselves, rather than just the descriptors, by using a | messages themselves, rather than just the descriptors, by using a | |||
| command like: | command like: | |||
| tag1 UID FETCH <lastseenuid+1>:* (FLAGS BODY.PEEK[]) | tag1 UID FETCH <lastseenuid+1>:* (FLAGS BODY.PEEK[]) | |||
| Note, that this example ignores the fact that the messages can | Note, that this example ignores the fact that the messages can | |||
| be arbitrary long. The disconnected client MUST always check | be arbitrary long. The disconnected client MUST always check | |||
| for message size before downloading, unless explicitly told otherwise. | for message size before downloading, unless explicitly told otherwise. | |||
| A good behaving client should use instead something like the following: | A well behaved client should use instead something like the following: | |||
| 1) Issue "tag1 UID FETCH <lastseenuid+1>:* (FLAGS RFC822.SIZE)" | 1) Issue "tag1 UID FETCH <lastseenuid+1>:* (FLAGS RFC822.SIZE)" | |||
| 2) From the message sizes returned in step 1 construct UID set | 2) From the message sizes returned in step 1 construct UID set | |||
| <required_messages> | <required_messages> | |||
| 3) Issue "tag2 UID FETCH <required_messages> (BODY.PEEK[])" | 3) Issue "tag2 UID FETCH <required_messages> (BODY.PEEK[])" | |||
| or | or | |||
| 1) Issue "tag1 UID FETCH <lastseenuid+1>:* (FLAGS)" | 1) Issue "tag1 UID FETCH <lastseenuid+1>:* (FLAGS)" | |||
| 2) Construct UID set <old_uids> from the responses of 1) | 2) Construct UID set <old_uids> from the responses of 1) | |||
| 3) Issue "tag2 SEARCH UID <old_uids> SMALLER <message_limit>" | 3) Issue "tag2 SEARCH UID <old_uids> SMALLER <message_limit>" | |||
| Construct UID set <required_messages> from the result of | Construct UID set <required_messages> from the result of | |||
| the SEARCH command. | the SEARCH command. | |||
| 4) Issue "tag3 UID FETCH <required_messages> (BODY.PEEK[])" | 4) Issue "tag3 UID FETCH <required_messages> (BODY.PEEK[])" | |||
| or | or | |||
| 1) Issue "tag1 UID FETCH <lastseenuid+1>:* (FLAGS BODY.PEEK[]<0.<length>>)", | 1) Issue "tag1 UID FETCH <lastseenuid+1>:* (FLAGS BODY.PEEK[]<0.<length>>)", | |||
| where <length> should be replaced with the maximal message size | where <length> should be replaced with the maximal message size | |||
| the client is willing to download. | the client is willing to download. | |||
| Note, that in response to such command the server will return | Note: In response to such a command, the server will only return | |||
| only part of a message which is longer than <length>, and will return | partial data if the message is longer than <length>. It will return | |||
| the full message, for any message equal or shorter than <length>. | the full message data for any message whose size is smaller than or | |||
| The truncated message, returned in the former case, might not be | equal to <length>. In the former case, the client will not be able | |||
| very useful for parsing on the client, so the client should include | to extract the full [MIME] structure of the message from the truncated | |||
| BODYSTRUCTURE in the UID FETCH command as well. | data, so the client should include BODYSTRUCTURE in the UID FETCH | |||
| command as well. | ||||
| 5. Implementation considerations | 5. Implementation considerations | |||
| Below are listed some common implementation pitfalls that should be | Below are listed some common implementation pitfalls that should be | |||
| considered when implementing a disconnected client. | considered when implementing a disconnected client. | |||
| 1) Implementing fake UIDs on the client. | 1) Implementing fake UIDs on the client. | |||
| A message scheduled to be uploaded has no UID, as UIDs are selected by | A message scheduled to be uploaded has no UID, as UIDs are selected by | |||
| the server. The client may implement fake UIDs internally in order to | the server. The client may implement fake UIDs internally in order to | |||
| reference not yet uploaded messages in further operations. For example, | reference not yet uploaded messages in further operations. For example, | |||
| message was scheduled to be uploaded and later marked deleted or copied | a message could be scheduled to be uploaded, but subsequently marked as deleted or copied | |||
| to another mailbox). However, the client MUST NOT under any circumstances | to another mailbox). Here the client MUST NOT under any circumstances | |||
| sent these fake UIDs to the server. Also, client implementors should | sent these fake UIDs to the server. Also, client implementors should | |||
| be reminded that according to [IMAP4] an UID is a 32bit unsigned integer | be reminded that according to [IMAP4] an UID is a 32bit unsigned integer | |||
| excluding 0. So, both 4294967295 and 2147483648 are valid UIDs and 0 and -1 | excluding 0. So, both 4294967295 and 2147483648 are valid UIDs and 0 and -1 | |||
| are both invalid. Existing disconnected mail clients are known to send | are both invalid. Some disconnected mail clients have been known to send | |||
| negative numbers (e.g. "-1") as message UIDs to servers during synchronization. | negative numbers (e.g. "-1") as message UIDs to servers during synchronization. | |||
| Example 1: The user starts composing a new message, edits it, saves it, | Example 1: The user starts composing a new message, edits it, saves it, | |||
| continues to edit and saves it again. | continues to edit and saves it again. | |||
| A disconnected client may record in its replay log (log of operations | A disconnected client may record in its replay log (log of operations | |||
| to be replayed on the server during synchronization) the sequence of | to be replayed on the server during synchronization) the sequence of | |||
| operations as shown below. For the purpose of this example we assume | operations as shown below. For the purpose of this example we assume | |||
| that all draft messages are stored in the mailbox called Drafts on an | that all draft messages are stored in the mailbox called Drafts on an | |||
| IMAP server. We will also use the following conventions: | IMAP server. We will also use the following conventions: | |||
| skipping to change at line 981 ¶ | skipping to change at line 1033 ¶ | |||
| ...final version of the message follows... | ...final version of the message follows... | |||
| 3). STORE <old_uid> +FLAGS (\Deleted) | 3). STORE <old_uid> +FLAGS (\Deleted) | |||
| Step 1 corresponds to the first attempt to save the draft message, | Step 1 corresponds to the first attempt to save the draft message, | |||
| step 2 corresponds to the second attempt to save the draft message | step 2 corresponds to the second attempt to save the draft message | |||
| and the step 3 deletes the first version of the draft message saved | and the step 3 deletes the first version of the draft message saved | |||
| in step 1. | in step 1. | |||
| A naive disconnected client may send the command in step 3 without | A naive disconnected client may send the command in step 3 without | |||
| replacing the fake client generated <old_uid> with the value returned | replacing the fake client generated <old_uid> with the value returned | |||
| by the server in step 1. A server will most likely reject such command, | by the server in step 1. A server will probably reject this command, | |||
| which will make the client believe that the synchronization sequence | which will make the client believe that the synchronization sequence | |||
| has failed. | has failed. | |||
| 2) Section 5.1 talks about common implementation errors related to error | 2) Section 5.1 talks about common implementation errors related to error | |||
| recovery during playback. | recovery during playback. | |||
| 3) Don't assume that the disconnected client is the only client used by | 3) Don't assume that the disconnected client is the only client used by | |||
| the user. | the user. | |||
| <<Is the example below is generic enough to be moved elsewhere?>> | <<Is the example below is generic enough to be moved elsewhere?>> | |||
| Example 2: Some clients may use the \Deleted flag as an indicator that | Example 2: Some clients may use the \Deleted flag as an indicator that | |||
| the message should not appear in the user's view. Usage of the \Deleted | the message should not appear in the user's view. Usage of the \Deleted | |||
| flag for this purpose is not safe, as other clients (e.g. online | flag for this purpose is not safe, as other clients (e.g. online | |||
| clients) might EXPUNGE the mailbox at any time. | clients) might EXPUNGE the mailbox at any time. | |||
| 4) Beware of "data" dependencies between synchronization operations. | 4) Beware of data dependencies between synchronization operations. | |||
| It might be very tempting for a client writer to perform some optimizations | It might be very tempting for a client writer to perform some | |||
| on playback log. Such optimizations might include removing redundant | optimizations on the playback log. Such optimizations might include | |||
| operations (see also optimization #2 in section 5.3), operation reordering, etc. | removing redundant operations (for example, see the optimization #2 | |||
| in section 5.3), or their reordering. | ||||
| It is not always safe to reorder or remove redundant operations during | It is not always safe to reorder or remove redundant operations during | |||
| synchronization, because some operations may have dependencies. So if | synchronization, because some operations may have dependencies. So if | |||
| in doubt, don't do that. The following example demonstrates this: | in doubt, don't do this. The following example demonstrates this: | |||
| Example 3: The user copies a message out of a mailbox and then deletes | Example 3: The user copies a message out of a mailbox and then deletes | |||
| the mailbox. | the mailbox. | |||
| C: A001 SELECT Old-Mail | C: A001 SELECT Old-Mail | |||
| S: ... | S: ... | |||
| C: A002 UID COPY 111 ToDo | C: A002 UID COPY 111 ToDo | |||
| S: A002 OK [COPYUID 1022843345 111 94] Copy completed | S: A002 OK [COPYUID 1022843345 111 94] Copy completed | |||
| ... | ... | |||
| C: A015 CLOSE | C: A015 CLOSE | |||
| S: A015 OK Completed | S: A015 OK Completed | |||
| C: A016 DELETE Old-Mail | C: A016 DELETE Old-Mail | |||
| S: A016 OK Mailbox deletion completed successfully | S: A016 OK Mailbox deletion completed successfully | |||
| If the client performs DELETE (tag A016) first and COPY (tag A002) second, | If the client performs DELETE (tag A016) first and COPY (tag A002) | |||
| than the COPY fails. | second, than the COPY fails. Also, the message that the user so | |||
| carefully copied into another mailbox, has been lost. | ||||
| 5.1. Error recovery during playback | 5.1. Error recovery during playback | |||
| Error recovery during synchronization is one of the trickiest parts | Error recovery during synchronization is one of the trickiest parts | |||
| to get right. Below, we will discuss certain error conditions | to get right. Below, we will discuss certain error conditions | |||
| and suggest possible choices to handle them: | and suggest possible choices to handle them: | |||
| 1). Lost connection to the server. | 1). Lost connection to the server. | |||
| The client MUST remember the current position in playback (replay) log and | The client MUST remember the current position in playback (replay) log and | |||
| replay it starting from the interrupted operation (the last command | replay it starting from the interrupted operation (the last command | |||
| issued by the client, but not acknowledged by the server) next time it is | issued by the client, but not acknowledged by the server) next time it | |||
| successfully connected to the same server. If the connection was lost while | successfully connects to the same server. If the connection was lost while | |||
| executing a non-idempotent IMAP command (see definition in Section 1), when | executing a non-idempotent IMAP command (see the definition in Section 1), when | |||
| reconnected the client MUST make sure that the interrupted command was | reconnected the client MUST make sure that the interrupted command was | |||
| indeed not executed. If it wasn't executed, the client must restart playback | indeed not executed. If it wasn't executed, the client must restart playback | |||
| from the interrupted command, otherwise from the following command. | from the interrupted command, otherwise from the following command. | |||
| When reconnected, care must be taken in order to properly reapply logical | When reconnected, care must be taken in order to properly reapply logical | |||
| operations that are represented by multiple IMAP commands, e.g. UID EXPUNGE | operations that are represented by multiple IMAP commands, e.g. UID EXPUNGE | |||
| emulation when UID EXPUNGE is not supported by the server (see section 4.2.4). | emulation when UID EXPUNGE is not supported by the server (see section 4.2.4). | |||
| Once the client detects that the connection to the server was lost, | Once the client detects that the connection to the server was lost, | |||
| it MUST stop replaying log. There are existing disconnected clients | it MUST stop replaying its log. There are existing disconnected clients | |||
| that, to the great annoyance of a user, will pop up an error dialog | that, to the great annoyance of users, pop up an error dialog | |||
| for each playback operation that has failed. | for each and every playback operation that fails. | |||
| 2). Copying/appending messages to a mailbox that doesn't exist. | 2). Copying/appending messages to a mailbox that doesn't exist. | |||
| (The server advertises this condition by sending the TRYCREATE response | ||||
| code in the tagged NO response to the APPEND or COPY command.) | ||||
| The user should be advised about the situation and be given | The user should be advised about the situation and be given | |||
| one of the following choices: | one of the following choices: | |||
| a). Try to recreate a mailbox; | a). Try to recreate a mailbox; | |||
| b). Copy/upload messages to another mailbox; | b). Copy/upload messages to another mailbox; | |||
| c). Skip copy/upload. | c). Skip copy/upload. | |||
| d). Abort replay. | d). Abort replay. | |||
| 3). Copying messages from, rename or get/change ACLs [ACL] on | 3). Copying messages from, rename or get/change ACLs [ACL] on | |||
| a mailbox that doesn't exist: | a mailbox that doesn't exist: | |||
| a). Skip operation | a). Skip operation | |||
| b). Abort replay | b). Abort replay | |||
| 4). Deleting mailbox or deleting/expunging a message that no longer exist. | 4). Deleting mailboxes or deleting/expunging messages that no longer exist. | |||
| This is actually is not an error and should be ignored by the client. | This is actually is not an error and should be ignored by the client. | |||
| 5). Message to perform operation on doesn't exist. | 5). Performing operations on messages that no longer exist. | |||
| a). Skip operation | a). Skip operation | |||
| b). Abort replay | b). Abort replay | |||
| In the case of changing flags on an expunged message the client should | In the case of changing flags on an expunged message the client should | |||
| silently ignore the error. | silently ignore the error. | |||
| Note 1: Several synchronization operations map to multiple IMAP commands | Note 1: Several synchronization operations map to multiple IMAP commands | |||
| (for example "move" described in 4.2.2). The client must guaranty | (for example "move" described in 4.2.2). The client must guarantee | |||
| atomicity of each such multistep operation. For example, | atomicity of each such multistep operation. For example, | |||
| when performing "move" between two mailboxes on the same server, | when performing a "move" between two mailboxes on the same server, | |||
| if the server is unable to copy messages, the client MUST NOT attempt to | if the server is unable to copy messages, the client MUST NOT attempt to | |||
| set the \Deleted flag on the messages being copied, all the more expunging | set the \Deleted flag on the messages being copied, let alone expunge | |||
| them. However the client MAY consider that move operation succeeded | them. However, the client MAY consider that move operation succeeded | |||
| even if the server was unable to set \Deleted flag on copied messages. | even if the server was unable to set the \Deleted flag on copied messages. | |||
| Note 2: Many synchronization operations have "data" dependencies. | Note 2: Many synchronization operations have data dependencies. | |||
| A failed operation must cause all dependent operations to fail as | A failed operation must cause all dependent operations to fail as | |||
| well. The client should check that and MUST NOT try to perform | well. The client should check that and MUST NOT try to perform | |||
| all dependent operations blindly (unless the user corrected the original | all dependent operations blindly (unless the user corrected the original | |||
| problem). For example, a message may be scheduled to be appended to | problem). For example, a message may be scheduled to be appended to | |||
| a mailbox on the server and later on the appended message may be copied | a mailbox on the server and later on the appended message may be copied | |||
| to another mailbox. If the APPEND operation fails, the client must not | to another mailbox. If the APPEND operation fails, the client must not | |||
| attempt to COPY the failed message later on. (See also Section 5, example 3). | attempt to COPY the failed message later on. (See also Section 5, example 3). | |||
| 5.2. Quality of implementation issues. | 5.2. Quality of implementation issues. | |||
| Below listed some quality of implementation issues for disconnected clients. | Below listed some quality of implementation issues for disconnected clients. | |||
| They will help to write a disconnected client that works correctly, performs | They will help to write a disconnected client that works correctly, performs | |||
| synchronization as quickly as possible (and thus can make the user | synchronization as quickly as possible (and thus can make the user | |||
| happier as well as save her some money) and minimizes the server load: | happier as well as save her some money) and minimizes the server load: | |||
| 1) Don't lose information. | 1) Don't lose information. | |||
| No matter how smart your client is other areas, if it looses information - | No matter how smart your client is in other areas, if it loses information | |||
| users will get very upset. | users will get very upset. | |||
| 2) Don't do work unless explicitly asked. Be flexible. Ask all questions | 2) Don't do work unless explicitly asked. Be flexible. Ask all questions | |||
| BEFORE starting synchronization, if possible. | BEFORE starting synchronization, if possible. | |||
| 3) Minimize traffic | 3) Minimize traffic | |||
| The client MUST NOT issue a command if the client already received | The client MUST NOT issue a command if the client already received | |||
| the required information from the server. | the required information from the server. | |||
| skipping to change at line 1130 ¶ | skipping to change at line 1186 ¶ | |||
| Round trips kill performance, especially on links with high latency. | Round trips kill performance, especially on links with high latency. | |||
| Sections 4.2.2.5 and 5.2 give some advices how to minimize number of | Sections 4.2.2.5 and 5.2 give some advices how to minimize number of | |||
| round trips. | round trips. | |||
| See also optimization #1 in Section 5.3. | See also optimization #1 in Section 5.3. | |||
| 5.3. Optimizations | 5.3. Optimizations | |||
| Some useful optimizations are described in this section. A disconnected | Some useful optimizations are described in this section. A disconnected | |||
| client that supports recommendations listed below will give the user | client that supports the recommendations listed below will give the user | |||
| a more pleasant experience. | a more pleasant experience. | |||
| 1) Initial OK or PREAUTH responses may contain CAPABILITY response code | 1) The initial OK or PREAUTH responses may contain the CAPABILITY response code | |||
| as described in section 7.1 of [IMAP4]. This response code gives | as described in section 7.1 of [IMAP4]. This response code gives | |||
| the same information as returned by the CAPABILITY command(*). | the same information as returned by the CAPABILITY command(*). | |||
| A disconnected client that pays attention to this response code can | A disconnected client that pays attention to this response code can | |||
| avoid sending CAPABILITY command and will save a round trip. | avoid sending CAPABILITY command and will save a round trip. | |||
| (*) - Note, that some servers report in the CAPABILITY response code | (*) - Note: Some servers report in the CAPABILITY response code | |||
| extensions that are only relevant in unauthenticated state or | extensions that are only relevant in unauthenticated state or | |||
| in all states. Such servers usually send another CAPABILITY | in all states. Such servers usually send another CAPABILITY | |||
| response code upon successful authentication using LOGIN or | response code upon successful authentication using LOGIN or | |||
| AUTHENTICATE command (that negotiates no security layer, see | AUTHENTICATE command (that negotiates no security layer, see | |||
| section 6.2.2 of [IMAP4]). The CAPABILITY response code | section 6.2.2 of [IMAP4]). The CAPABILITY response code | |||
| sent upon successful LOGIN/AUTHENTICATE might be different | sent upon successful LOGIN/AUTHENTICATE might be different | |||
| from the CAPABILITY response code in the initial OK response, | from the CAPABILITY response code in the initial OK response, | |||
| as extensions only relevant for unauthenticated state will not | as extensions only relevant for unauthenticated state will not | |||
| be advertised and some additional extensions available only | be advertised and some additional extensions available only | |||
| in authenticated and/or selected state will be. | in authenticated and/or selected state will be. | |||
| skipping to change at line 1198 ¶ | skipping to change at line 1254 ¶ | |||
| Several synchronization steps don't depend on each other and thus can | Several synchronization steps don't depend on each other and thus can | |||
| be performed in parallel. Because the server machine is usually more | be performed in parallel. Because the server machine is usually more | |||
| powerful than the client machine and can perform some operations in | powerful than the client machine and can perform some operations in | |||
| parallel, this may speed up the total time of synchronization. | parallel, this may speed up the total time of synchronization. | |||
| In order to achieve such parallelization the client will have to open | In order to achieve such parallelization the client will have to open | |||
| more than one connection to the same server. Client writers should not | more than one connection to the same server. Client writers should not | |||
| forget about non-trivial cost associated with establishing a TCP connection | forget about non-trivial cost associated with establishing a TCP connection | |||
| and performing an authentication. The disconnected client MUST NOT use | and performing an authentication. The disconnected client MUST NOT use | |||
| a connection per each mailbox. In most cases it is sufficient to have | one connection per mailbox. In most cases it is sufficient to have | |||
| two connections. | two connections. The disconnected client SHOULD avoid selecting the same | |||
| mailbox in more than one connection, see section 3.1.1 of the [RFC 2683] | ||||
| for more details. | ||||
| Any mailbox synchronization MUST start with checking of the UIDVALIDITY | Any mailbox synchronization MUST start with checking of the UIDVALIDITY | |||
| as described in section 4.1 of this document. The client MAY use STATUS | as described in section 4.1 of this document. The client MAY use STATUS | |||
| command to check UID Validity of a non selected mailbox. This is preferable | command to check UID Validity of a non selected mailbox. This is preferable | |||
| to opening many connections to the same server to perform synchronization | to opening many connections to the same server to perform synchronization | |||
| of multiple mailboxes simultaneously. As described in section 5.3.10 of | of multiple mailboxes simultaneously. As described in section 5.3.10 of | |||
| [IMAP4], this SHOULD NOT be used on the selected mailbox. | [IMAP4], this SHOULD NOT be used on the selected mailbox. | |||
| 6. IMAP extensions that may help | 6. IMAP extensions that may help | |||
| The following extensions can save traffic and/or number of round trips: | The following extensions can save traffic and/or number of round trips: | |||
| 1) The use of [UIDPLUS] is discussed in sections 4.1, 4.2.1, 4.2.2.1 and 4.2.4. | 1) The use of [UIDPLUS] is discussed in sections 4.1, 4.2.1, 4.2.2.1 and 4.2.4. | |||
| 2) The use of MULTIAPPEND and LITERAL+ extensions for uploading messages | 2) The use of the MULTIAPPEND and LITERAL+ extensions for uploading messages | |||
| is discussed in 4.2.2.5. | is discussed in 4.2.2.5. | |||
| 3) Use CONDSTORE extension (see section 6.1) for quick flag resynchronization. | 3) Use the CONDSTORE extension (see section 6.1) for quick flag resynchronization. | |||
| 6.1. CONDSTORE extension | 6.1. CONDSTORE extension | |||
| An advance disconnected mail client should use [CONDSTORE] extension | An advance disconnected mail client should use the [CONDSTORE] extension | |||
| when it is supported by the server. The client must cache the value from | when it is supported by the server. The client must cache the value from | |||
| HIGHESTMODSEQ OK response code received on mailbox opening and update | HIGHESTMODSEQ OK response code received on mailbox opening and update | |||
| it whenever the server sends MODSEQ FETCH data items. | it whenever the server sends MODSEQ FETCH data items. | |||
| If the client receives NOMODSEQ OK untagged response instead of | If the client receives NOMODSEQ OK untagged response instead of | |||
| HIGHESTMODSEQ, it MUST remove the last known HIGHESTMODSEQ value from its | HIGHESTMODSEQ, it MUST remove the last known HIGHESTMODSEQ value from its | |||
| cache and follow more general instructions in section 3. | cache and follow more general instructions in section 3. | |||
| When the client opens the mailbox for synchronization it first compares | When the client opens the mailbox for synchronization it first compares | |||
| UIDVALIDITY as described in step d)1) in section 3. If the cached | UIDVALIDITY as described in step d)1) in section 3. If the cached | |||
| skipping to change at line 1244 ¶ | skipping to change at line 1302 ¶ | |||
| by the server. If the cached HIGHESTMODSEQ value also matches the | by the server. If the cached HIGHESTMODSEQ value also matches the | |||
| one returned by the server, then the client MUST NOT fetch flags for | one returned by the server, then the client MUST NOT fetch flags for | |||
| cached messages, as they hasn't changed. If the value on the server | cached messages, as they hasn't changed. If the value on the server | |||
| is higher than the cached one, the client MAY use | is higher than the cached one, the client MAY use | |||
| "SEARCH MODSEQ <cached-value>" to find all messages with flags | "SEARCH MODSEQ <cached-value>" to find all messages with flags | |||
| changed since the last time the client was online and had the mailbox | changed since the last time the client was online and had the mailbox | |||
| opened. Alternatively the client MAY use | opened. Alternatively the client MAY use | |||
| "FETCH 1:* (FLAGS) (CHANGEDSINCE <cached-value>)". The latter operation | "FETCH 1:* (FLAGS) (CHANGEDSINCE <cached-value>)". The latter operation | |||
| combines searching for changed messages and fetching new information. | combines searching for changed messages and fetching new information. | |||
| In all cases the client still need to fetch information about new | In all cases the client still needs to fetch information about new | |||
| messages (if requested by the user) and discover which messages got | messages (if requested by the user), as well as discover which messages have been | |||
| expunged. | expunged. | |||
| Step d) ("Server-to-client synchronization") in section 4 in the presence | Step d) ("Server-to-client synchronization") in section 4 in the presence | |||
| of CONDSTORE extension is amended as follows: | of the CONDSTORE extension is amended as follows: | |||
| d) "Server-to-client synchronization" - for each mailbox that requires | d) "Server-to-client synchronization" - for each mailbox that requires | |||
| synchronization, do the following: | synchronization, do the following: | |||
| 1a) Check the mailbox UIDVALIDITY (see section 4.1 for more details). | 1a) Check the mailbox UIDVALIDITY (see section 4.1 for more details). | |||
| with SELECT/EXAMINE/STATUS. | with SELECT/EXAMINE/STATUS. | |||
| If UIDVALIDITY value returned by the server differs, | If the UIDVALIDITY value returned by the server differs, | |||
| the client MUST | the client MUST | |||
| * empty the local cache of that mailbox; | * empty the local cache of that mailbox; | |||
| * "forget" the cached HIGHESTMODSEQ value for the mailbox; | * "forget" the cached HIGHESTMODSEQ value for the mailbox; | |||
| * remove any pending "actions" which refer to UIDs in | * remove any pending "actions" which refer to UIDs in | |||
| that mailbox. Note, this doesn't affect actions performed on | that mailbox. Note, this doesn't affect actions performed on | |||
| client generated fake UIDs (see section 5); | client generated fake UIDs (see section 5); | |||
| * skip steps 1b and 2-II; | * skip steps 1b and 2-II; | |||
| 1b) Check the mailbox HIGHESTMODSEQ. If the cached value is the same | 1b) Check the mailbox HIGHESTMODSEQ. If the cached value is the same | |||
| skipping to change at line 1312 ¶ | skipping to change at line 1370 ¶ | |||
| or: | or: | |||
| C: A143 SEARCH MODSEQ 20010715194032001 | C: A143 SEARCH MODSEQ 20010715194032001 | |||
| S: * SEARCH 2 5 6 7 11 12 18 19 20 23 (MODSEQ 20010917162500) | S: * SEARCH 2 5 6 7 11 12 18 19 20 23 (MODSEQ 20010917162500) | |||
| S: A143 OK Search complete | S: A143 OK Search complete | |||
| 7. Security Considerations | 7. Security Considerations | |||
| It is believed that this document does not raise any new security concerns | It is believed that this document does not raise any new security concerns | |||
| that are not alread present in the base [IMAP] protocol, and these issues | that are not already present in the base [IMAP] protocol, and these issues | |||
| are discussed in [IMAP]. Additional security considerations may be found | are discussed in [IMAP]. Additional security considerations may be found | |||
| in different extensions mentioned in this document, in particular in | in different extensions mentioned in this document, in particular in | |||
| [UIDPLUS], [LITERAL+], [CONDSTORE], [MULTIAPPEND] and [UNSELECT]. | [UIDPLUS], [LITERAL+], [CONDSTORE], [MULTIAPPEND] and [UNSELECT]. | |||
| Implementors are also reminded about importance of thorough testing. | Implementors are also reminded about the importance of thorough testing. | |||
| 8. References | 8. References | |||
| 8.1. Normative References | 8.1. Normative References | |||
| [KEYWORDS] Bradner, "Key words for use in RFCs to Indicate | [KEYWORDS] Bradner, "Key words for use in RFCs to Indicate | |||
| Requirement Levels", RFC 2119, Harvard University, March 1997. | Requirement Levels", RFC 2119, Harvard University, March 1997. | |||
| [IMAP4] Crispin, M., "Internet Message Access Protocol - Version | [IMAP4] Crispin, M., "Internet Message Access Protocol - Version | |||
| 4rev1", RFC 3501, University of Washington, March 2003. | 4rev1", RFC 3501, University of Washington, March 2003. | |||
| skipping to change at line 1355 ¶ | skipping to change at line 1413 ¶ | |||
| [RFC 2683] Leiba, B., "IMAP4 Implementation Recommendations", RFC 2683, | [RFC 2683] Leiba, B., "IMAP4 Implementation Recommendations", RFC 2683, | |||
| September 1999. | September 1999. | |||
| 8.2. Informative References | 8.2. Informative References | |||
| [ACL] Myers, J., "IMAP4 ACL Extension", RFC 2086, January 1997. | [ACL] Myers, J., "IMAP4 ACL Extension", RFC 2086, January 1997. | |||
| and | and | |||
| Melnikov, A., "IMAP4 ACL Extension", draft-ietf-imapext-acl-XX.txt, | Melnikov, A., "IMAP4 ACL Extension", draft-ietf-imapext-acl-XX.txt, | |||
| Work in Progress. | Work in Progress. | |||
| [IMAP-MODEL] Crispin, M. "Distributed Electronic Mail Models in | ||||
| IMAP4", RFC 1733, University of Washington, December 1994. | ||||
| 9. Acknowledgment | 9. Acknowledgment | |||
| This document is based on the draft-ietf-imap-disc-01.txt written | This document is based on the draft-ietf-imap-disc-01.txt written | |||
| by Rob Austein in November 1994. | by Rob Austein in November 1994. | |||
| The editor appreciate comments posted by Mark Crispin to the IMAP mailing | The editor appreciate comments posted by Mark Crispin to the IMAP mailing | |||
| list and the comments/corrections/ideas received from Cyrus Daboo, | list and the comments/corrections/ideas received from Grant Baillie, | |||
| John G. Myers, Chris Newman and Timo Sirainen. | Cyrus Daboo, John G. Myers, Chris Newman and Timo Sirainen. | |||
| The editor would also like to thank the developers of Netscape Messenger | The editor would also like to thank the developers of Netscape Messenger | |||
| and Mozilla mail clients for providing examples of disconnected mail clients | and Mozilla mail clients for providing examples of disconnected mail clients | |||
| that served as a base for many recommendations in this document. | that served as a base for many recommendations in this document. | |||
| 10. Editor's Address | 10. Editor's Address | |||
| Alexey Melnikov | Alexey Melnikov | |||
| mailto: alexey.melnikov@isode.com | mailto: alexey.melnikov@isode.com | |||
| End of changes. 91 change blocks. | ||||
| 133 lines changed or deleted | 194 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ | ||||