RFC 8508

IMAP REPLACE Extension

πŸ“… published January 2019, from ietf

RFC 8508: IMAP REPLACE Extension (part 1 of 2) πŸ’–

  • Number and title: RFC 8508, IMAP REPLACE Extension πŸŽ€
  • Author: S. Brandt, from Verizon ✨
  • Category: Standards Track, which means it's an official Internet Standards Track document πŸ”₯
  • Date: January 2019 🌸
  • ISSN: 2070-1721
  • Obsoletes / Updates: this header doesn't list either one, so there's nothing it obsoletes or updates πŸ¦‹

Abstract

okay so this doc defines an IMAP extension that lets you replace an existing message in a message store with a brand-new one πŸ’Œ message replacement is super common for clients that auto-save drafts or notes while you're typing, so it's lowkey essential πŸ“

Status of This Memo

this is an Internet Standards Track document 🌈

it's a product of the Internet Engineering Task Force (IETF). it represents the consensus of the IETF community, it got public review, and the Internet Engineering Steering Group (IESG) approved it for publication 🫢 for more on Internet Standards, check Section 2 of RFC 7841.

for info on the current status, any errata, and how to give feedback, go to https://www.rfc-editor.org/info/rfc8508 πŸ’…

Copyright (c) 2019 IETF Trust and the persons identified as the document authors. All rights reserved. πŸ”’

this doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the publication date. please read these carefully, because they spell out your rights and restrictions for this document πŸ“œ any Code Components pulled out of this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as the Simplified BSD License describes πŸ’œ

Table of Contents

1.  Overview  . . . . . . . . . . . . . . . . . . . . . . . . . .   2
2.  Conventions Used in This Document . . . . . . . . . . . . . .   3
3.  REPLACE and UID REPLACE . . . . . . . . . . . . . . . . . . .   3
  3.1.  Advertising Support for REPLACE . . . . . . . . . . . . .   3
  3.2.  REPLACE Command . . . . . . . . . . . . . . . . . . . . .   3
  3.3.  UID REPLACE Command . . . . . . . . . . . . . . . . . . .   4
  3.4.  Semantics of REPLACE and UID REPLACE  . . . . . . . . . .   5
  3.5.  IMAP State Diagram Impacts  . . . . . . . . . . . . . . .   6
4.  Interaction with Other Extensions . . . . . . . . . . . . . .   6
  4.1.  ACL . . . . . . . . . . . . . . . . . . . . . . . . . . .   6
  4.2.  CATENATE  . . . . . . . . . . . . . . . . . . . . . . . .   6
  4.3.  UIDPLUS . . . . . . . . . . . . . . . . . . . . . . . . .   8
  4.4.  IMAP Events in Sieve  . . . . . . . . . . . . . . . . . .   8
  4.5.  CONDSTORE/QRESYNC . . . . . . . . . . . . . . . . . . . .   8
  4.6.  OBJECTID  . . . . . . . . . . . . . . . . . . . . . . . .   8
  4.7.  MULTIAPPEND . . . . . . . . . . . . . . . . . . . . . . .   8
5.  Formal Syntax . . . . . . . . . . . . . . . . . . . . . . . .   9
6.  Security Considerations . . . . . . . . . . . . . . . . . . .   9
7.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .   9
8.  References  . . . . . . . . . . . . . . . . . . . . . . . . .   9
  8.1.  Normative References  . . . . . . . . . . . . . . . . . .   9
  8.2.  Informative References  . . . . . . . . . . . . . . . . .  10
Acknowledgements  . . . . . . . . . . . . . . . . . . . . . . . .  11
Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  11

1. Overview ✨

okay bestie, this doc adds an IMAP ([RFC3501]) extension for swapping an existing message out for a new one πŸ¦‹ it does that by adding a brand-new REPLACE command and by extending the Unique Identifier (UID) command so it accepts UID REPLACE πŸ’«

here's the tea: base IMAP has no replace function at all 😭 so clients have been stuck doing three separate commands, one after another: APPEND, STORE, and EXPUNGE. pipelining those three is not recommended, because if any single command fails, the rest should not run, otherwise the original version of the message could get lost πŸ’€

that non-atomic mess causes real drama. interruptions can leave messages in half-done states that other clients can see and act on πŸ™ˆ they can also strand older revisions, so the user has to manually clean up a pile of copies of the same message just to stop wasting quota πŸ—‘οΈ and the old sequence can even fail on APPEND because you're over quota, even though the STORE/EXPUNGE that comes after would've freed up enough room for the new revision 😀 finally, server efficiencies may be possible with one logical message replacement operation compared to the APPEND/STORE/EXPUNGE sequence πŸš€

in its simplest form, REPLACE is a single-command wrapper around APPEND, STORE +flags \DELETED, and UID EXPUNGE for one message πŸŽ€ the difference is that it skips the quota implications and the intermediate states that come with the three-command sequence πŸ’… server devs are encouraged to make REPLACE atomic, since that simplifies error handling, minimizes operational concerns, and reduces potential security problems ✨ for systems where that isn't possible, the communication with the requesting client has to make sure nobody gets confused about the message store state 🫢

a server MUST NOT generate a response code for the STORE +flags \DELETED portion of the sequence. and servers that support the REPLACE command MUST NOT infer any inheritance of content, flags, or annotations from the message being replaced. no guessing, periodt πŸ™…β€β™€οΈ

2. Conventions Used in This Document πŸ“š

the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here 🧠

formal syntax is defined by [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. REPLACE and UID REPLACE πŸ”

3.1. Advertising Support for REPLACE πŸ“£

servers that implement the REPLACE extension return "REPLACE" as one of the supported capabilities in the CAPABILITY command response 🌟

3.2. REPLACE Command πŸŽ€

here's the rundown on the arguments, responses, and results:

Arguments:  message sequence number
            mailbox name
            OPTIONAL flag parenthesized list
            OPTIONAL date/time string
            message literal

Responses: no specific responses for this command
Result:     OK - replace completed
            NO - replace error; can't remove specified message
                 or can't add new message content
            BAD - command unknown or arguments invalid

and here's an example, the vibe is totally "happy new year" πŸŽ†

C: A003 REPLACE 4 Drafts (\Seen \Draft) {312}
S: + Ready for literal data
C: Date: Thu, 1 Jan 2015 00:05:00 -0500 (EST)
C: From: Fritz Schmidt <fritz.ze@example.org>
C: Subject: happy new year !!
C: To: miss.mitzy@example.org
C: Message-Id: <B238822388-0100000@example.org>
C: MIME-Version: 1.0
C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
C:
C: Just saw the best fireworks show. Wish you were here.
C:
S: * OK [APPENDUID 1 2000] Replacement Message ready
S: * 5 EXISTS
S: * 4 EXPUNGE
S: A003 OK Replace completed

3.3. UID REPLACE Command πŸ¦‹

this one extends the first form of the UID command (see Section 6.4.8 of [RFC3501]) so that the REPLACE command from above is a valid argument πŸ’– this version uses a UID instead of a sequence number as its first parameter πŸ”‘

example time 🧚

C: A004 UID REPLACE 2000 Drafts (\Seen \Draft) {350}
S: + Ready for literal data
C: Date: Thu, 1 Jan 2015 00:06:00 -0500 (EST)
C: From: Fritz Schmidt <fritz.ze@example.org>
C: Subject: happy new year !!
C: To: miss.mitzy@example.org
C: Message-Id: <B238822389-0100000@example.org>
C: MIME-Version: 1.0
C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
C:
C: Just saw the best fireworks show. Wish you were here.
C: Hopefully next year you can join us.
C:
S: * OK [APPENDUID 1 2001] Replacement Message ready
S: * 5 EXISTS
S: * 4 EXPUNGE
S: A004 OK Replace completed

3.4. Semantics of REPLACE and UID REPLACE 🧩

both REPLACE and UID REPLACE take five arguments: a message identifier, a named mailbox, an optional parenthesized flag list, an optional message date/time string, and a message literal ✨ the message literal gets appended to the named mailbox, and the message the identifier points to gets removed from the selected mailbox 🫧 to the client, all of that looks like one single action. it has the same effect as this sequence:

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

in that sequence, the quota implications of APPEND get evaluated alongside the pending EXPUNGE, so only the net quota consumption counts πŸ’° and the EXPUNGE part only applies to the specified message, not to every message flagged as "\Deleted" 🎯

even though REPLACE has the same effect as those steps, the semantics aren't identical πŸ™ƒ like MOVE [RFC6851], the intermediate states never happen and the response codes are different 🌈 specifically, the response codes for APPEND and EXPUNGE get returned, but the ones for the STORE operation MUST NOT be generated πŸ™…β€β™€οΈ

when an error happens while processing REPLACE or UID REPLACE, the server MUST NOT leave the selected mailbox in an inconsistent state. and any untagged EXPUNGE response MUST NOT be sent until all the actions are successfully completed πŸ›‘

it's super common for the named mailbox to match the selected mailbox when you're replacing a draft, but the REPLACE extension intentionally does not require the two to be the same 🌸 for example, you can use REPLACE to swap a message in the \Drafts special-use mailbox (see Section 2 of [RFC6154]) with a message in the \Sent special-use mailbox after the message gets submitted πŸ“€

because REPLACE is so similar to APPEND, any extension that affects APPEND affects REPLACE the same way ✨ response codes like TRYCREATE (see Section 6.3.11 of [RFC3501]), plus the ones defined by extensions, get sent as appropriate πŸ’« check Section 4 for more on how REPLACE plays with other IMAP extensions 🧚

3.5. IMAP State Diagram Impacts πŸ—ΊοΈ

here's the twist: unlike APPEND, which is valid in the authenticated state, the REPLACE and UID REPLACE commands MUST only be valid in the selected state πŸ” that difference from APPEND is necessary because REPLACE operates on message sequence numbers πŸ”’ on top of that, the REPLACE extension intentionally follows the UID command convention from Section 6.4.8 of [RFC3501], so the UID variant of the command doesn't support use from the authenticated state either πŸ™…β€β™€οΈ

4. Interaction with Other Extensions 🫢

this section explains how REPLACE interacts with some other IMAP extensions πŸ’œ

4.1. ACL πŸ”‘

the Access Control List (ACL) rights [RFC4314] required for UID REPLACE are the union of the ACL rights required for UID STORE and UID EXPUNGE in the current mailbox, plus APPEND in the target mailbox πŸ’– so you need all three sets to slay this one πŸ‘‘

4.2. CATENATE ✨

bestie, if your server does both REPLACE and CATENATE [RFC4469], it MUST support the extra append-data and resp-text-code elements from Section 5 ("Formal Syntax") of [RFC4469] alongside the REPLACE command πŸ’…. Put those two together and REPLACE gets seriously efficient at message editing πŸ”₯.

Example time πŸŽ€:

User composes message and attaches photo
----------------------------------------
C: A010 APPEND Drafts (\Seen \Draft) {1201534}
S: + Ready for literal data
C: Date: Thu, 1 Jan 2015 00:10:00 -0500 (EST)
C: From: Fritz Schmidt <fritz.ze@example.org>
C: Message-ID: <B238822388-0100003@example.org>
C: MIME-Version: 1.0
C: Content-Type: multipart/mixed;
C:         boundary="------------030305060306060609050804"
C:
C: --------------030305060306060609050804
C: Content-Type: text/plain; charset=utf-8; format=flowed
C: Content-Transfer-Encoding: 7bit
C:
C: Here is picture from the fireworks
C:
C: Yours...
C: Fritz
C:
C: --------------030305060306060609050804
C: Content-Type: image/jpeg;
C:         name="Fireworks.jpg"
C: Content-Transfer-Encoding: base64
C: Content-Disposition: attachment;
C:         filename="Fireworks.jpg"
C:
  <large base64 encoded part goes here>
C:
C: --------------030305060306060609050804--
S: A010 OK [APPENDUID 1 3002] APPEND complete

User completes message with To: and Subject: fields
---------------------------------------------------
C: A011 UID REPLACE 3002 Drafts CATENATE (TEXT {71}
S: + Ready for literal data
C: To: Mitzy <miss.mitzy@example.org>
C: Subject: My view of the fireworks
C:  URL "/Drafts/;UID=3002")
S: * OK [APPENDUID 1 3003] Replacement Message ready
S: * 5 EXISTS
S: * 4 EXPUNGE
S: A011 OK REPLACE completed

4.3. UIDPLUS πŸ¦‹

Servers that do both REPLACE and UIDPLUS [RFC4315] SHOULD send APPENDUID in response to a UID REPLACE command 🫢. More details are in Section 3 of [RFC4315]. Servers doing REPLACE and UIDPLUS are also advised to send the APPENDUID response code in an untagged OK before they send the EXPUNGE or replaced responses. Sending APPENDUID in the tagged OK, like the UIDPLUS spec describes, means the client gets EXPUNGE for a message first and APPENDUID for the new one afterwards 😭. That order is honestly a mess to process, so untagged is the move ✨.

4.4. IMAP Events in Sieve 🧚

REPLACE works with IMAP events in Sieve [RFC6785] the same way APPEND does πŸ’œ. So REPLACE can cause a Sieve script to run with imap.cause set to "APPEND". The intermediate state STORE +FLAGS.SILENT \DELETED is never exposed by REPLACE, so no action will be taken that results in an imap.cause of FLAG πŸ™ˆ.

4.5. CONDSTORE/QRESYNC 🌸

Servers doing both REPLACE and CONDSTORE/QRESYNC [RFC7162] MUST treat the message being replaced as if it were removed with a UID EXPUNGE command πŸ’€. Sections 3.2.9 and 3.2.10 of [RFC7162] are especially relevant here πŸ“.

4.6. OBJECTID 🌈

Servers doing both REPLACE and OBJECTID [RFC8474] MUST return different EMAILIDs for the replaced message and the replacing message πŸ‘‘. There's one exception: the case in Section 5 ("EMAILID Identifier for Identical Messages") of [RFC8474], where the server detects that both messages have identical immutable content 🫢.

4.7. MULTIAPPEND ⭐

REPLACE has no interaction with MULTIAPPEND [RFC3502] at all πŸ™Œ. This document also doesn't describe a way to replace multiple messages at once, so don't look for it here 🫠.

5. Formal Syntax πŸ“œ

The syntax below is written in Augmented Backus-Naur Form (ABNF) as specified in [RFC5234]. [RFC3501] defines the non-terminals "capability", "command-select", "mailbox", "seq-number", and "uid". [RFC4466] defines the non-terminal "append-message".

Unless noted otherwise, all alphabetic characters are case insensitive. Uppercase or lowercase letters are only used to define token strings for editorial clarity πŸ’–. Implementations MUST accept these strings in a case-insensitive way ✨.

capability     =/ "REPLACE"

command-select =/ replace
replace        = "REPLACE" SP seq-number SP mailbox append-message
uid            =/ "UID" SP replace

6. Security Considerations πŸ”

This document is believed to add no security problems beyond those that may already exist with the base IMAP specification πŸ•΅οΈβ€β™€οΈ. Now here's the plot twist: the REPLACE command may actually prevent some potential security problems, because it avoids the intermediate message states that an attacker could possibly exploit 😱πŸ”₯.

7. IANA Considerations πŸ—‚οΈ

IANA has added REPLACE to the "IMAP Capabilities" registry at https://www.iana.org/assignments/imap-capabilities πŸŽ€.

8. References πŸ“š

8.1. Normative References

8.2. Informative References

Acknowledgements 🫢

Huge thanks to the IMAPEXT participants πŸ™. Special shoutouts go to Arnt Gulbrandsen, Alexey Melnikov, Chris Newman, and Bron Gondwana for their specific contributions 🌟.

Author's Address πŸ’Œ

Stuart Brandt
Verizon
22001 Loudoun County Parkway
Ashburn, VA  20147
United States of America

Email: stujenerin@aol.com
πŸ“¦ where this page comes from