RFC 6851

Internet Message Access Protocol (IMAP) - MOVE Extension

πŸ“… published January 2013, from ietf

RFC 6851: Internet Message Access Protocol (IMAP) - MOVE Extension πŸ¦‹

okay bestie, so this one is RFC 6851 and it's a Standards Track doc, which means it's the real deal πŸ’… It came out in January 2013 and the authors are A. Gulbrandsen and N. Freed (Ed.), both at Oracle. It's published under ISSN 2070-1721. The title block doesn't list any obsoletes or updates, so this doc isn't replacing or changing any other RFC. Iconic! 🌸

Abstract

this extension adds two new commands, MOVE and UID MOVE, so you can move messages from one mailbox to another in one go ✨

Status of This Memo

this is an Internet Standards Track document πŸŽ€

it's a product of the Internet Engineering Task Force (IETF), and it reflects the consensus of the IETF community. it got public review and was approved for publication by the Internet Engineering Steering Group (IESG). if you want more on Internet Standards, check Section 2 of RFC 5741 🧚

info about the current status of this doc, any errata, and how to send feedback is at http://www.rfc-editor.org/info/rfc6851 πŸ’œ

Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved. 🌈

this document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they're in effect on the date it was published. please actually read these, bestie, because they explain your rights and restrictions for this doc 🫢

if you pull Code Components out of this document, they have to include the Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions. they come with no warranty, same as the Simplified BSD License says πŸ’…


1. Introduction ✨

okay so this doc defines an IMAP [RFC3501] extension that makes it easier to move messages from one mailbox to another. it does this by adding a brand new MOVE command and by extending the UID command so it can do UID MOVE πŸ¦‹

here's the tea: the base IMAP spec doesn't have a move function at all 😭 so clients have been stuck doing a combo of COPY, STORE, and EXPUNGE to get this super common job done.

implementors have been pointing out problems with that approach for ages. moving a message isn't atomic, so if something interrupts it, messages can get left in intermediate states πŸ’€ and since multiple clients can be poking at the same mailboxes at once, clients can see those intermediate states even when nothing goes wrong. also, if the source mailbox has other messages flagged for deletion, that third step can end up expunging more than just the messages you moved πŸ™ˆ on top of that, some servers with certain back-end message stores have efficient ways to move messages that don't involve actually copying the data, and the COPY/STORE/EXPUNGE process usually can't take advantage of that. main character energy for servers, but not for the old method πŸ‘‘

the MOVE extension is there in any IMAP implementation that returns "MOVE" as one of its supported capabilities when the client sends the CAPABILITY command 🌸

2. Conventions Used in This Document

okay, the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this doc are to be read as described in [RFC2119] πŸ’–

formal syntax is written in ABNF [RFC5234] 🧚

example lines that start with "C:" are sent by the client, and the ones that start with "S:" are sent by the server 🫢

3. MOVE and UID MOVE πŸŽ€

3.1. MOVE Command

the arguments are a sequence set and a mailbox name πŸ’…

Arguments: sequence set
           mailbox name

there are no specific responses for this command πŸ™ˆ

the results are:

Result: OK - move completed

        NO - move error: can't move those messages or to that name

        BAD - command unknown or arguments invalid

3.2. UID MOVE Command

this extends the first form of the UID command (see [RFC3501], Section 6.4.8) so that the MOVE command from above is a valid argument too πŸ¦‹

3.3. Semantics of MOVE and UID MOVE

okay so the MOVE command takes two arguments: a message set (sequence numbers for MOVE, UIDs for UID MOVE) and a named mailbox. every message in the set gets moved, not copied, from the selected (source) mailbox to the named (target) mailbox ✨

this means a new message gets created in the target mailbox with a new UID, the original gets removed from the source mailbox, and to the client it looks like one single action 🌈 for each message, the effect is the same as this sequence:

  1. [UID] COPY
  2. [UID] STORE +FLAGS.SILENT \DELETED
  3. UID EXPUNGE

the effect of MOVE matches those steps, but the semantics aren't identical πŸ™ˆ the intermediate states those steps produce just don't happen, and the response codes are different. yes, the COPY and EXPUNGE response codes still get returned, but response codes for a STORE MUST NOT be generated, and the \DELETED flag MUST NOT be set for any message. no flag drama, bestie πŸ’…

because a MOVE applies to a whole set, it could fail partway through. no matter whether the command succeeds in moving the whole set, each individual message SHOULD either be moved or left unaffected 🫢 the server MUST leave each message in a state where it's in at least one of the source or target mailboxes, so no message can get lost or orphaned 😭 the server SHOULD NOT leave any message in both mailboxes, because a partial failure shouldn't end with a bunch of duplicate messages πŸ’€ this still holds even if the server sends a tagged NO response to the command.

since MOVE is so similar to COPY, any extension that affects COPY affects MOVE in the same way 🧚 response codes like TRYCREATE (see [RFC3501], Section 6.4.7), along with the ones defined by extensions, get sent when they're appropriate. see Section 4 for more on how MOVE plays with other IMAP extensions 🌸

here's an example:

C: a UID MOVE 42:69 foo
S: * OK [COPYUID 432432 42:69 1202:1229]
S: * 22 EXPUNGE
S: (more expunges)
S: a OK Done

the server might send unrelated EXPUNGE responses too, if some messages happened to get expunged at the same time. totally normal IMAP behaviour πŸ¦‹

implementers need to read [RFC4315] to understand what UID EXPUNGE does, though they don't need a full implementation of [RFC4315] πŸ’–

moving a message to the currently selected mailbox (so the source and target are the same) is allowed when copying the message to the currently selected mailbox is allowed ✨

the server may send EXPUNGE (or VANISHED) responses before the tagged response, so the client can't safely send more commands that use message sequence number arguments while the server is processing MOVE or UID MOVE πŸ™ˆ

both MOVE and UID MOVE can be pipelined with other commands, but you have to be careful about it 😭 both commands change sequence numbers and also allow unrelated EXPUNGE responses. renumbering of other messages in the source mailbox after any EXPUNGE response can be super surprising, so it's unsafe to pipeline any command that depends on message sequence numbers after a MOVE or UID MOVE. same goes for MOVE with a command that might cause renumbering: they can't be pipelined together πŸ’€ check [RFC3501], Section 5.5 for more on the ambiguities and the handling rules for both clients and servers πŸ‘‘

4. Interaction with Other Extensions 🌈

this section covers how MOVE interacts with some other IMAP extensions 🫢

4.1. RFC 2087, QUOTA

the QUOTA extension (defined by [RFC2087]) may interact with MOVE on some servers, in the sense that a MOVE command might succeed where COPY would cause a quota overrun 🧚

4.2. RFC 4314, Access Control List (ACL)

the ACL rights [RFC4314] needed for MOVE and UID MOVE are the union of the ACL rights needed for UID STORE, UID COPY, and UID EXPUNGE πŸ’…

4.3. RFC 4315, UIDPLUS

servers that support UIDPLUS [RFC4315] SHOULD send COPYUID in response to a UID MOVE command. for more info, see Section 3 of [RFC4315] ✨

servers implementing UIDPLUS are also advised to send the COPYUID response code in an untagged OK before they send EXPUNGE or moved responses. (sending COPYUID in the tagged OK, like the UIDPLUS spec describes, means clients first get an EXPUNGE for a message and then COPYUID for that same message. that sequence can be unnecessarily hard to process usefully πŸ™ˆ)

4.4. RFC 5162, QRESYNC

the QRESYNC extension [RFC5162] says the server SHOULD send VANISHED rather than EXPUNGE in response to the UID EXPUNGE command πŸ¦‹ the same requirement applies to MOVE, so a QRESYNC-enabled client needs to handle both VANISHED and EXPUNGE responses to a UID MOVE command πŸ’–

if the server can store modification sequences for the selected mailbox, it MUST increment the per-mailbox mod-sequence if at least one message was permanently moved because of the MOVE/UID MOVE command 🌸 for each permanently removed message, the server MUST remember the incremented mod-sequence and the corresponding UID. if at least one message was moved, the server MUST send the updated per-mailbox modification sequence using the HIGHESTMODSEQ response code (defined in [RFC4551]) in the tagged or untagged OK response πŸ‘‘

when one or more messages move to a target mailbox, and the server can store modification sequences for that mailbox, the server MUST generate and assign new modification sequence numbers to the moved messages. those numbers MUST be higher than the highest modification sequence of the messages that were originally in the mailbox ✨

4.5. IMAP Events in Sieve

MOVE applies to IMAP events in Sieve [RFC6785] the same way COPY does 🧚 so a MOVE can cause a Sieve script to run with imap.cause set to "COPY". since MOVE doesn't change any flags, a MOVE command won't cause a script to run with imap.cause set to "FLAG" πŸ’…

5. Formal Syntax πŸ’œ

the syntax below uses the Augmented Backus-Naur Form (ABNF) notation from [RFC5234] 🫢 [RFC3501] defines the non-terminals "capability", "command-select", "sequence-set", and "mailbox".

unless noted otherwise, all alphabetic characters are case insensitive. using upper or lower case for token strings is only for editorial clarity 🌈 implementations MUST accept these strings in a case-insensitive way πŸŽ€

capability     =/ "MOVE"

command-select =/ move
move           = "MOVE" SP sequence-set SP mailbox
uid            = "UID" SP (copy / fetch / search / store / move)

6. Security Considerations ✨

okay bestie, security time πŸ”’ MOVE doesn't add any new capabilities to IMAP, so the security impact is pretty limited 🫢 BUT the transactional semantics of MOVE can interact with specific implementations in ways that could have unexpected consequences 😭 For example, moving messages between mailboxes under the quota root may require temporarily suspending quota checking.

another area to watch is how it plays with antispam, antivirus, and other security scanning and auditing mechanisms πŸ›‘οΈ different mailboxes can have different security policies, and those can interact with MOVE in complex ways. scanning with updated rules may also be required when messages are moved, even when the underlying policy hasn't changed. so be careful πŸ’€

the real plot twist: MOVE actually fixes a problem with the base spec πŸŽ€ client authors currently have to devise and implement complicated algorithms to handle partial failures of the STORE/COPY/EXPUNGE trio. if those algorithms are incomplete or implemented improperly, messages can get lost. MOVE takes that headache away, which is so iconic of it πŸ‘‘

7. IANA Considerations 🌸

the IANA has added MOVE to the "IMAP 4 Capabilities" registry, which lives at http://www.iana.org/assignments/imap4-capabilities πŸ“‹ registry entries are very important, no cap 🧚


8. Acknowledgments πŸ•―οΈ

this document is dedicated to the memory of Mark Crispin, the inventor of the IMAP protocol πŸ’œ he also wrote the IMAP protocol specification [RFC3501] and contributed to many other email specifications in the IETF. he's literally the reason any of this exists, so respect 🫑

an extension like this has been proposed many times, by many people 🌈 this document is based on several of those proposals, most recently the one by Witold Krecicki ✨ thank you so much to Witold, Benoit Claise, Adrien W. de Croy, Stephen Farrell, Bron Gondwana, Dan Karp, Christian Ketterer, Murray Kucherawy, Jan Kundrat, Barry Leiba, Alexey Melnikov, Kathleen Moriarty, Zoltan Ordogh, Pete Resnick, Timo Sirainen, Michael Slusarz, and others who gave valuable comments πŸ«ΆπŸŽ€


9. References πŸ“š

9.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC3501]  Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - VERSION
           4rev1", RFC 3501, March 2003.

[RFC4314]  Melnikov, A., "IMAP4 Access Control List (ACL) Extension",
           RFC 4314, December 2005.

[RFC4315]  Crispin, M., "Internet Message Access Protocol (IMAP) -
           UIDPLUS extension", RFC 4315, December 2005.

[RFC4551]  Melnikov, A. and S. Hole, "IMAP Extension for Conditional
           STORE Operation or Quick Flag Changes Resynchronization",
           RFC 4551, June 2006.

[RFC5162]  Melnikov, A., Cridland, D., and C. Wilson, "IMAP4
           Extensions for Quick Mailbox Resynchronization", RFC 5162,
           March 2008.

[RFC5234]  Crocker, D. and P. Overell, "Augmented BNF for Syntax
           Specifications: ABNF", STD 68, RFC 5234, January 2008.

9.2. Informative References

[RFC2087]  Myers, J., "IMAP4 QUOTA extension", RFC 2087,
           January 1997.

[RFC6785]  Leiba, B., "Support for Internet Message Access Protocol
           (IMAP) Events in Sieve", RFC 6785, November 2012.

Authors' Addresses πŸ’Œ

Arnt Gulbrandsen
Schweppermannstr. 8
D-81671 Muenchen
Germany

Fax:   +49 89 4502 9758
EMail: arnt@gulbrandsen.priv.no


Ned Freed (editor)
Oracle
800 Royal Oaks
Monrovia, CA  91016-6347
USA

EMail: ned+ietf@mrochek.com

and that's a wrap on MOVE, bestie πŸŒˆπŸ’– you made it through the whole spec πŸ‘‘

πŸ“¦ where this page comes from