RFC 9051
Internet Message Access Protocol (IMAP) - Version 4rev2
Internet Message Access Protocol (IMAP) - Version 4rev2 ๐
Hiii bestie, okay so this is RFC 9051 and it's the big IMAP upgrade. ๐ฆ Here's the title block tea:
- Number: RFC 9051 โจ
- Title: Internet Message Access Protocol (IMAP) - Version 4rev2
- Editors and authors: A. Melnikov, Ed. (Isode Ltd) and B. Leiba, Ed. (Futurewei Technologies). They're the main characters here ๐
- Stream: Internet Engineering Task Force (IETF) ๐
- Category: Standards Track
- ISSN: 2070-1721
- Date: August 2021
- Obsoletes: RFC 3501 (so yes, it's replacing the old IMAP4rev1 ๐ )
Abstract โจ
okay so the Internet Message Access Protocol Version 4rev2 (IMAP4rev2) lets a client get at and mess with electronic mail messages sitting on a server ๐ฌ. IMAP4rev2 lets you handle mailboxes (remote message folders) in a way that's functionally equivalent to local folders, which is so iconic ๐. It also lets an offline client resynchronize with the server, so no more out-of-sync chaos ๐ซถ.
IMAP4rev2 has operations for creating, deleting, and renaming mailboxes ๐ง, checking for new messages, removing messages permanently, setting and clearing flags, parsing per RFCs 5322, 2045, and 2231, searching, and selectively fetching message attributes, texts, and portions of them. Messages are accessed by numbers, and those numbers are either message sequence numbers or unique identifiers. Very precise, very obsessed ๐.
IMAP4rev2 does not specify a way to post mail. That job goes to a mail submission protocol, like the one in RFC 6409. Not its lane, not its problem ๐ .
Status of This Memo โจ
This is an Internet Standards Track document ๐.
This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community, and it got public review and was approved for publication by the Internet Engineering Steering Group (IESG). More info on Internet Standards is in Section 2 of RFC 7841 ๐.
Info about the current status of this document, any errata, and how to give feedback is at https://www.rfc-editor.org/info/rfc9051 ๐.
Copyright Notice ๐
Copyright (c) 2021 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 (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, because they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they are provided without warranty as described in the Simplified BSD License.
This document may contain material from IETF Documents or IETF Contributions published or made publicly available before November 10, 2008. The person(s) controlling the copyright in some of this material may not have granted the IETF Trust the right to allow modifications of such material outside the IETF Standards Process. Without an adequate license from the person(s) controlling the copyright in such materials, this document may not be modified outside the IETF Standards Process, and derivative works of it may not be created outside the IETF Standards Process, except to format it for publication as an RFC or to translate it into languages other than English ๐ธ.
Table of Contents ๐
1. How to Read This Document
1.1. Organization of This Document
1.2. Conventions Used in This Document
1.3. Special Notes to Implementors
2. Protocol Overview
2.1. Link Level
2.2. Commands and Responses
2.2.1. Client Protocol Sender and Server Protocol Receiver
2.2.2. Server Protocol Sender and Client Protocol Receiver
2.3. Message Attributes
2.3.1. Message Numbers
2.3.2. Flags Message Attribute
2.3.3. Internal Date Message Attribute
2.3.4. RFC822.SIZE Message Attribute
2.3.5. Envelope Structure Message Attribute
2.3.6. Body Structure Message Attribute
2.4. Message Texts
3. State and Flow Diagram
3.1. Not Authenticated State
3.2. Authenticated State
3.3. Selected State
3.4. Logout State
4. Data Formats
4.1. Atom
4.1.1. Sequence Set and UID Set
4.2. Number
4.3. String
4.3.1. 8-Bit and Binary Strings
4.4. Parenthesized List
4.5. NIL
5. Operational Considerations
5.1. Mailbox Naming
5.1.1. Mailbox Hierarchy Naming
5.1.2. Namespaces
5.2. Mailbox Size and Message Status Updates
5.3. Response When No Command in Progress
5.4. Autologout Timer
5.5. Multiple Commands in Progress (Command Pipelining)
6. Client Commands
6.1. Client Commands - Any State
6.1.1. CAPABILITY Command
6.1.2. NOOP Command
6.1.3. LOGOUT Command
6.2. Client Commands - Not Authenticated State
6.2.1. STARTTLS Command
6.2.2. AUTHENTICATE Command
6.2.3. LOGIN Command
6.3. Client Commands - Authenticated State
6.3.1. ENABLE Command
6.3.2. SELECT Command
6.3.3. EXAMINE Command
6.3.4. CREATE Command
6.3.5. DELETE Command
6.3.6. RENAME Command
6.3.7. SUBSCRIBE Command
6.3.8. UNSUBSCRIBE Command
6.3.9. LIST Command
6.3.10. NAMESPACE Command
6.3.11. STATUS Command
6.3.12. APPEND Command
6.3.13. IDLE Command
6.4. Client Commands - Selected State
6.4.1. CLOSE Command
6.4.2. UNSELECT Command
6.4.3. EXPUNGE Command
6.4.4. SEARCH Command
6.4.5. FETCH Command
6.4.6. STORE Command
6.4.7. COPY Command
6.4.8. MOVE Command
6.4.9. UID Command
6.5. Client Commands - Experimental/Expansion
7. Server Responses
7.1. Server Responses - Generic Status Responses
7.1.1. OK Response
7.1.2. NO Response
7.1.3. BAD Response
7.1.4. PREAUTH Response
7.1.5. BYE Response
7.2. Server Responses - Server Status
7.2.1. ENABLED Response
7.2.2. CAPABILITY Response
7.3. Server Responses - Mailbox Status
7.3.1. LIST Response
7.3.2. NAMESPACE Response
7.3.3. STATUS Response
7.3.4. ESEARCH Response
7.3.5. FLAGS Response
7.4. Server Responses - Mailbox Size
7.4.1. EXISTS Response
7.5. Server Responses - Message Status
7.5.1. EXPUNGE Response
7.5.2. FETCH Response
7.6. Server Responses - Command Continuation Request
8. Sample IMAP4rev2 Connection
9. Formal Syntax
10. Author's Note
11. Security Considerations
11.1. TLS-Related Security Considerations
11.2. STARTTLS Command versus Use of Implicit TLS Port
11.3. Client Handling of Unsolicited Responses Not Suitable for
the Current Connection State
11.4. COPYUID and APPENDUID Response Codes
11.5. LIST Command and Other Users' Namespace
11.6. Use of MD5
11.7. Other Security Considerations
12. IANA Considerations
12.1. Updates to IMAP Capabilities Registry
12.2. GSSAPI/SASL Service Name
12.3. LIST Selection Options, LIST Return Options, and LIST
Extended Data Items
12.4. IMAP Mailbox Name Attributes and IMAP Response Codes
13. References
13.1. Normative References
13.2. Informative References
13.2.1. Related Protocols
13.2.2. Historical Aspects of IMAP and Related Protocols
Appendix A. Backward Compatibility with IMAP4rev1
A.1. Mailbox International Naming Convention for Compatibility
with IMAP4rev1
Appendix B. Backward Compatibility with BINARY Extension
Appendix C. Backward Compatibility with LIST-EXTENDED Extension
Appendix D. 63-Bit Body Part and Message Sizes
Appendix E. Changes from RFC 3501 / IMAP4rev1
Appendix F. Other Recommended IMAP Extensions
Acknowledgements
Index
Authors' Addresses
1. How to Read This Document ๐
1.1. Organization of This Document ๐๏ธ
okay so this document is written from the point of view of the implementor of an IMAP4rev2 client or server ๐ ๏ธ. Apart from the protocol overview in Section 2, it is not optimized for someone who's just trying to understand how the protocol works. The stuff in Sections 3, 4, and 5 gives the general context and definitions that IMAP4rev2 runs on โจ.
Sections 6, 7, and 9 cover the IMAP commands, responses, and syntax. They're so intertwined that it's almost impossible to understand any one of them on its own ๐. So, bestie, do not try to figure out command syntax from the command section alone. Go to "Formal Syntax" (Section 9) instead ๐ .
1.2. Conventions Used in This Document ๐
"Conventions" are basic principles or procedures, and the document's conventions are noted in this section ๐.
In examples, "C:" and "S:" mark lines sent by the client and server, respectively. Each line includes the terminating CRLF, so keep that in mind ๐ฆ.
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 ๐ฅ.
The word "can" (not "may") is used to refer to a possible circumstance or situation, as opposed to an optional facility of the protocol ๐.
"User" is used to refer to a human user, whereas "client" refers to the software being run by the user ๐ง.
"Connection" refers to the entire sequence of client/server interaction, from the initial establishment of the network connection until its termination ๐ธ.
"Session" refers to the sequence of client/server interaction from the time a mailbox is selected (SELECT or EXAMINE command) until the time that selection ends. That happens when SELECT or EXAMINE selects another mailbox, on a CLOSE command, on an UNSELECT command, or on connection termination โญ.
The term "Implicit TLS" refers to the automatic negotiation of TLS whenever a TCP connection is made on a particular TCP port that's used exclusively by that server for TLS connections ๐. The term is meant to contrast with the STARTTLS command in IMAP, which the client and server use to explicitly negotiate TLS on an already-established cleartext TCP connection ๐ซถ.
Characters are 8-bit UTF-8 (of which 7-bit US-ASCII is a subset), unless otherwise specified. Other character sets are indicated using a "CHARSET", as described in [MIME-IMT] and defined in [CHARSET]. CHARSETs have important extra semantics beyond defining a character set, so check those documents for more detail ๐.
There are several protocol conventions in IMAP ๐. These refer to aspects of the specification that aren't strictly part of the IMAP protocol but reflect generally accepted practice. Implementations need to be aware of these conventions and avoid conflicts, whether or not they implement the convention. For example, "&" may not be used as a hierarchy delimiter, since it conflicts with the Mailbox International Naming Convention, and other uses of "&" in mailbox names are impacted as well ๐.
1.3. Special Notes to Implementors โจ
Okay bestie, implementers of IMAP are strongly encouraged to read the IMAP implementation recommendations document [IMAP-IMPLEMENTATION] alongside this one ๐ It helps you understand the intricacies of this protocol and how to build a product that actually plays nice with everyone else ๐ซถ
IMAP4rev2 is designed to be upwards compatible from the IMAP4rev1 [RFC3501], IMAP2 [IMAP2], and unpublished IMAP2bis [IMAP2BIS] protocols ๐ธ It's largely compatible with the IMAP4rev1 protocol in RFC 3501 and the IMAP4 protocol in [RFC1730]. The exception is some facilities added in [RFC1730] and [RFC3501] that turned out to be problematic, so they were later removed or replaced by better alternatives ๐ As IMAP4rev2 evolved, some aspects of the earlier protocols became obsolete. The obsolete commands, responses, and data formats that an IMAP4rev2 implementation can run into when working with an earlier implementation are described in Appendices A and E and [IMAP-OBSOLETE]. IMAP4rev2 supports 63-bit body parts and message sizes ๐ช IMAP4rev2 compatibility with the BINARY and LIST-EXTENDED IMAP extensions is covered in Appendices B and C, respectively.
Other compatibility issues with IMAP2bis, the most common variant of the earlier protocol, are discussed in [IMAP-COMPAT] ๐ A full discussion of compatibility issues with the rare (and presumed extinct) variants of [IMAP2] is in [IMAP-HISTORICAL]. Honestly, that one is primarily of historical interest ๐ฆ
IMAP was originally developed for the older [RFC822] standard, so the RFC822.SIZE fetch item incorporates "RFC822" in its name ๐ง "RFC822" is meant to be read as a reference to the updated [RFC5322] standard.
IMAP4rev2 does not specify a way to post mail. That job belongs to a mail submission protocol, such as the one specified in [RFC6409] ๐ฌ
2. Protocol Overview โจ
2.1. Link Level
The IMAP4rev2 protocol assumes a reliable data stream, like the one TCP provides ๐ When TCP is used, an IMAP4rev2 server listens on port 143 (cleartext port) or port 993 (Implicit TLS port).
2.2. Commands and Responses
An IMAP4rev2 connection is made up of three things: establishing a client/server network connection, an initial greeting from the server, and then client/server interactions ๐ Each of those interactions is a client command, server data, and a server completion result response.
Everything the client and server send is in the form of lines, meaning strings that end with a CRLF ๐ The protocol receiver of an IMAP4rev2 client or server is reading either a line, or a sequence of octets with a known count followed by a line.
2.2.1. Client Protocol Sender and Server Protocol Receiver
The client command begins an operation โจ Each client command is prefixed with an identifier called a "tag." It's typically a short alphanumeric string, like A0001, A0002, and so on. The client generates a different tag for each command. More formally: the client SHOULD generate a unique tag for every command, but a server MUST accept tag reuse ๐ซถ
Clients MUST follow the syntax outlined in this specification strictly ๐ โโ๏ธ It's a syntax error to send a command with missing or extraneous spaces or arguments.
There are two cases where a line from the client doesn't represent a complete command ๐งฉ In one case, a command argument is quoted with an octet count (see the description of literal in Section 4.3). In the other case, the command arguments need server feedback (see the AUTHENTICATE command in Section 6.2.2). In either case, the server sends a command continuation request response if it's ready for the octets (if that's appropriate) and the rest of the command. This response is prefixed with the token "+".
Note: If, instead, the server detected an error in the command, it sends a BAD completion response with a tag matching the command (as described below) to reject the command and prevent the client from sending any more of it. It's also possible for the server to send a completion response for some other command (if multiple commands are in progress) or untagged data ๐ธ In either case, the command continuation request is still pending. The client takes the appropriate action for the response and reads another response from the server. In all cases, the client MUST send a complete command (including receiving all command continuation request responses and sending command continuations for the command) before initiating a new command. No skipping ahead, bestie ๐
The protocol receiver of an IMAP4rev2 server reads a command line from the client, parses the command and its arguments, and then transmits server data and a server command completion result response ๐ฆ
2.2.2. Server Protocol Sender and Client Protocol Receiver
Data the server sends to the client, along with status responses that don't indicate command completion, are prefixed with the token "*" and are called untagged responses ๐
Server data MAY be sent as a result of a client command, or it MAY be sent unilaterally by the server ๐ง There's no syntactic difference between server data that resulted from a specific command and server data that was sent unilaterally.
The server completion result response tells you whether the operation succeeded or failed ๐ It's tagged with the same tag as the client command that began the operation. So if more than one command is in progress, the tag in a server completion response tells you which command it applies to. There are three possible server completion responses: OK (success), NO (failure), or BAD (a protocol error, like an unrecognized command or a command syntax error) ๐
Servers SHOULD strictly enforce the syntax outlined in this specification ๐ Any client command with a protocol syntax error, including (but not limited to) missing or extraneous spaces or arguments, SHOULD be rejected, and the client gets a BAD server completion response.
The protocol receiver of an IMAP4rev2 client reads a response line from the server. It then takes action based on the first token of the response, which can be a tag, a "*", or a "+" ๐ฅ
A client MUST be prepared to accept any server response at all times, including server data that wasn't requested ๐ญ Server data SHOULD be remembered (cached), so the client can reference its remembered copy instead of sending a command to the server to request the data. For certain server data, the data MUST be remembered, as specified elsewhere in this document ๐
This topic gets a deeper dive in "Server Responses" (see Section 7) ๐ง
2.3. Message Attributes
Besides the message text, each message has several attributes attached to it โจ These attributes can be retrieved one at a time, or together with other attributes or message texts.
2.3.1. Message Numbers
Messages in IMAP4rev2 are accessed by one of two numbers: the Unique Identifier (UID) or the message sequence number ๐ฆ
2.3.1.1. Unique Identifier (UID) Message Attribute ๐
okay so a UID is an unsigned, non-zero 32-bit value that gets handed to every message ๐. Paired with the unique identifier validity value (more on that below), it becomes a 64-bit value that MUST NOT point at any other message in the mailbox, or in any later mailbox with the same name, forever ๐. UIDs are assigned in strictly ascending order. Every time a new message lands, it gets a higher UID than everything already sitting in the mailbox ๐. Unlike message sequence numbers, UIDs don't have to be contiguous, so gaps are totally fine ๐
The UID of a message MUST NOT change during the session and SHOULD NOT change between sessions ๐. If UIDs do change between sessions, that MUST be detectable through the UIDVALIDITY mechanism we'll get to shortly ๐จ. Persistent UIDs are required so a client can resync its state from a previous session with the server. That's super important for disconnected or offline access clients [IMAP-MODEL], and it's discussed further in [IMAP-DISC] ๐ง
Every mailbox has two 32-bit unsigned non-zero values that help with UID handling: UIDNEXT (the next unique identifier value) and UIDVALIDITY (the unique identifier validity value) ๐
UIDNEXT is the predicted value that will be given to the next new message in the mailbox โจ. Unless UIDVALIDITY also changes, UIDNEXT MUST have two characteristics. First, UIDNEXT MUST NOT change unless new messages are added to the mailbox. Second, UIDNEXT MUST change whenever new messages are added, even if those messages get expunged right after ๐
Note: UIDNEXT is there so a client can tell whether any messages have been delivered since the last time it checked. It is NOT a guarantee that any particular message will have that UID ๐. All a client can assume, when it grabs UIDNEXT, is that messages arriving after that moment will have a UID greater than or equal to that value.
The UIDVALIDITY value gets sent in a UIDVALIDITY response code inside an OK untagged response when a mailbox is selected ๐ฌ. If UIDs from an earlier session fail to persist into this one, UIDVALIDITY MUST be greater than the value used in the earlier session ๐. A solid choice is a 32-bit representation of the current date and time when the value gets assigned. That keeps it unique and always increasing โฐ. Another option is a global counter that goes up every time a mailbox is created ๐ข
Note: Ideally, UIDs SHOULD persist at all times ๐ฅน. The spec admits that failing to persist can be unavoidable on some server setups, but it really encourages message store techniques that avoid the problem. For example:
- UIDs MUST be strictly ascending in the mailbox at all times. If the physical message store gets reordered by a non-IMAP agent, the UIDs in the mailbox MUST be regenerated, because the old ones are no longer strictly ascending after the reorder ๐
- If the message store has no mechanism to store UIDs, it must regenerate them at each session, and each session must have a unique UIDVALIDITY value. Heads up, this can be super disruptive to client message caching ๐ญ
- If a mailbox is deleted or renamed and a new mailbox with the same name is created later, the server must either keep track of the UIDs from the previous instance of the mailbox or assign a new UIDVALIDITY value to the new instance ๐๏ธ
- The combination of mailbox name, UIDVALIDITY, and UID MUST refer to a single, immutable (or expunged) message on that server forever ๐. In particular, the internal date, RFC822.SIZE, envelope, body structure, and message texts (all
BODY[...]fetch data items) MUST never change. This doesn't cover message numbers, and it doesn't cover attributes that can be set by a STORE command (such asFLAGS) ๐ซถ. When a message is expunged, its UID MUST NOT be reused under the same UIDVALIDITY value ๐ซ
2.3.1.2. Message Sequence Number Message Attribute ๐ข
A message sequence number is a relative position from 1 up to the number of messages in the mailbox ๐. This position MUST be ordered by ascending UIDs. When a new message is added, it gets a message sequence number that is 1 higher than the number of messages in the mailbox before it arrived ๐ฑ
Message sequence numbers can get reassigned during the session, and that's the tea โ. For example, when a message is permanently removed (expunged), the sequence number of every message after it goes down by one, and the mailbox's message count goes down too ๐. Similarly, a new message can end up with a sequence number that some other message held before an expunge ๐ฆ
Sequence numbers aren't just for positions, either. You can do math with them ๐งฎ. For example, if an untagged "11 EXISTS" comes in and an untagged "8 EXISTS" came in earlier, that means three new messages arrived, with sequence numbers 9, 10, and 11 ๐. Another example: if message 287 in a 523-message mailbox has UID 12345, then there are exactly 286 messages with lesser UIDs and 236 messages with greater UIDs ๐คฏ
2.3.2. Flags Message Attribute ๐ฉ
A message has a list of zero or more named tokens attached to it, called "flags" ๐ท๏ธ. A flag gets set by being added to that list and gets cleared by being removed. There are two types of flags in IMAP4rev2: system flags and keywords. A flag of either type can be permanent or session-only ๐
A system flag is a predefined flag name in this specification that begins with \. Some system flags (\Deleted and \Seen) have special semantics that get explained elsewhere in this document ๐. The system flags defined right now are:
\Seen Message has been read
\Answered Message has been answered
\Flagged Message is "flagged" for urgent/special attention
\Deleted Message is "deleted" for removal by later EXPUNGE
\Draft Message has not completed composition (marked as a
draft).
\Recent This flag was in use in IMAP4rev1 and is now
deprecated.
A keyword is defined by the server implementation, and keywords don't start with \ ๐. Servers MAY let the client define new keywords in the mailbox (check out the PERMANENTFLAGS response code description for more on that) ๐ช. A few keywords that start with $ are also defined in this specification ๐
This document defines several keywords that weren't originally in [RFC3501] but that client implementations found useful โจ. Server implementations SHOULD support these (allowed in SEARCH, and allowed and preserved in APPEND, COPY, and MOVE commands) ๐ซถ
$Forwarded Message has been forwarded to another email address by being embedded within, or attached to a new message. An email client sets this keyword when it successfully forwards the message to another email address. The usual use is to show a different (or additional) icon for a forwarded message ๐. Once set, the flag SHOULD NOT be cleared ๐.
$MDNSent Message Disposition Notification [RFC8098] was generated and sent for this message. See [RFC3503] for more details on how this keyword is used and for requirements on clients and servers ๐จ.
$Junk The user (or a delivery agent on behalf of the user) may choose to mark a message as definitely containing junk ($Junk; see also the related keyword $NotJunk). The $Junk keyword can be used to mark, group, or hide undesirable messages (and such messages might be moved or deleted later). See [IMAP-KEYWORDS-REG] for more information ๐๏ธ.
$NotJunk The user (or a delivery agent on behalf of the user) may choose to mark a message as definitely not containing junk ($NotJunk; see also the related keyword $Junk). The $NotJunk keyword can be used to mark, group, or show messages that the user wants to see. See [IMAP-KEYWORDS-REG] for more information ๐.
$Phishing The $Phishing keyword can be used by a delivery agent to mark a message as highly likely to be a phishing email. A message that a delivery agent determines to be a phishing email should also be considered a junk email and have the appropriate junk filtering applied, including setting the $Junk flag and placing the message in the \Junk special-use mailbox (see Section 7.3.1), if available ๐ฃ.
If both the $Phishing flag and the $Junk flag are set, the user agent should display an additional warning message to the user. Additionally, the user agent might display a warning, such as something of the form, "This message may be trying to steal your personal information," when the user clicks on any hyperlinks within the message ๐จ.
The requirement for both $Phishing and $Junk to be set before a user agent displays a warning is for better backwards compatibility with existing clients that understand the $Junk flag but not the $Phishing flag. This is so that when an unextended client removes the $Junk flag, an extended client will also show the correct state ๐ง . See [IMAP-KEYWORDS-REG] for more information.
$Junk and $NotJunk are mutually exclusive. If more than one of these is set for a message, the client MUST treat it as if none are set, and it SHOULD unset both of them on the IMAP server ๐
โโ๏ธ.
Other registered keywords can be found in the "IMAP and JMAP Keywords" registry [IMAP-KEYWORDS-REG]. New keywords SHOULD be registered in this registry using the procedure specified in [RFC5788] ๐.
A flag can be permanent or session-only on a per-flag basis ๐ฆ. Permanent flags are the ones the client can add or remove from the message flags permanently, which means concurrent and subsequent sessions will see any change to them. Changes to session flags are valid only in that session โณ.
2.3.3. Internal Date Message Attribute ๐
The Internal Date message attribute is the internal date and time of the message on the server ๐ฐ๏ธ. It is NOT the date and time in the [RFC5322] header. It's the date and time that reflects when the message was received. For messages delivered via [SMTP], it's the date and time of final delivery as defined by [SMTP] ๐ฌ. For messages created by the IMAP4rev2 COPY or MOVE command, the value SHOULD be the same as the Internal Date attribute of the source message ๐. For messages created by the IMAP4rev2 APPEND command, the value SHOULD be the date and time specified in the APPEND command description โ๏ธ. All other cases are implementation defined ๐
2.3.4. RFC822.SIZE Message Attribute โจ
okay so RFC822.SIZE is the number of octets in the message when it's written in [RFC5322] format ๐ฌ. This size SHOULD match what you get back from a FETCH BODY[] command ๐
. If the server stores the message in some other format, it has to work out the size itself, and it often saves that number so it doesn't have to recalculate every time ๐ง
2.3.5. Envelope Structure Message Attribute ๐
an envelope structure is a parsed version of the [RFC5322] header of the message ๐ Quick heads-up: the IMAP envelope structure is NOT the same thing as an [SMTP] envelope, so don't mix them up ๐
2.3.6. Body Structure Message Attribute ๐ธ
a body structure is a parsed version of the [MIME-IMB] body structure information of the message ๐ฆ
2.4. Message Texts ๐
ngl this one is so useful. Besides grabbing the whole [RFC5322] text of a message, IMAP4rev2 lets you fetch just pieces of it ๐ You can get the [RFC5322] message header, the [RFC5322] message body, a [MIME-IMB] body part, or a [MIME-IMB] header. Main character energy, picking only what you need โจ
3. State and Flow Diagram ๐บ๏ธ
Once the client and server connect, an IMAP4rev2 connection is in one of four states ๐ The starting state is shown in the server greeting. Most commands only work in certain states, so it's giving "right place, right time." If the client tries a command in a state that doesn't fit, that's a protocol error ๐ญ The server will reply with a BAD or NO (depending on how the server is built) as the command completion result ๐
3.1. Not Authenticated State ๐
in the not authenticated state, the client MUST supply authentication credentials before most commands are allowed ๐ซถ You end up here when a connection starts, unless it was already pre-authenticated.
3.2. Authenticated State ๐
in the authenticated state, the client is logged in and MUST select a mailbox before any commands that affect messages will work ๐ You get here when a pre-authenticated connection starts, when good credentials are provided, after a mailbox selection error, or after a successful CLOSE or UNSELECT command.
3.3. Selected State ๐
in the selected state, a mailbox has been picked to access ๐ You land here once a mailbox is successfully selected.
3.4. Logout State ๐
in the logout state, the connection is getting shut down ๐ญ This can happen because the client asked for it with the LOGOUT command, or because either the client or the server decided to do it on its own.
If the client asks to log out, the server MUST send an untagged BYE response and a tagged OK response to the LOGOUT command before it closes the connection ๐ And the client MUST read that tagged OK response to the LOGOUT command before the client closes the connection. Both sides need to say goodbye properly ๐ฅบ
A server SHOULD NOT close the connection on its own without first sending an untagged BYE response that gives the reason ๐ โโ๏ธ A client SHOULD NOT close the connection on its own either. Instead it SHOULD send a LOGOUT command ๐ If the server notices the client closed the connection unilaterally, the server MAY skip the untagged BYE response and just close its own side ๐
Here's the state diagram, and yes it's giving spaghetti but it's iconic ๐
+----------------------+
|connection established|
+----------------------+
||
\/
+--------------------------------------+
| server greeting |
+--------------------------------------+
|| (1) || (2) || (3)
\/ || ||
+-----------------+ || ||
|Not Authenticated| || ||
+-----------------+ || ||
|| (7) || (4) || ||
|| \/ \/ ||
|| +----------------+ ||
|| | Authenticated |<=++ ||
|| +----------------+ || ||
|| || (7) || (5) || (6) ||
|| || \/ || ||
|| || +--------+ || ||
|| || |Selected|==++ ||
|| || +--------+ ||
|| || || (7) ||
\/ \/ \/ \/
+--------------------------------------+
| Logout |
+--------------------------------------+
||
\/
+-------------------------------+
|both sides close the connection|
+-------------------------------+
Legend for the diagram above, bestie ๐๏ธ:
Legend for the above diagram:
(1) connection without pre-authentication (OK greeting)
(2) pre-authenticated connection (PREAUTH greeting)
(3) rejected connection (BYE greeting)
(4) successful LOGIN or AUTHENTICATE command
(5) successful SELECT or EXAMINE command
(6) CLOSE or UNSELECT command, unsolicited CLOSED response code, or
failed SELECT or EXAMINE command
(7) LOGOUT command, server shutdown, or connection closed
4. Data Formats ๐
IMAP4rev2 uses textual commands and responses ๐ฌ Data can show up in a few forms: atom, number, string, parenthesized list, or NIL. A single data item can take more than one form, though. For example, a data item that uses "astring" syntax can be an atom or a string, so it's lowkey flexible ๐ฆ
4.1. Atom โ๏ธ
an atom is one or more non-special characters ๐ธ
4.1.1. Sequence Set and UID Set ๐ข
you can point at a bunch of messages with a sequence set, which holds either message sequence numbers or unique identifiers ๐งธ Check Section 9 for the details. A sequence set can have ranges like 5:50, a list of specific sequence numbers, or a mix of both. It can use the special symbol * to mean the highest sequence number in the mailbox. A sequence set NEVER holds unique identifiers, though ๐
โโ๏ธ
A "UID set" is basically the same idea, but it uses unique identifiers instead of message sequence numbers. It is not allowed to contain the * symbol ๐
4.2. Number ๐
a number is one or more digit characters that stand for a numeric value ๐ฅ
4.3. String ๐งต
a string comes in one of three forms: synchronizing literal, non-synchronizing literal, or quoted string ๐ The synchronizing literal is the general form, and it has no limits on which characters it can hold โจ The non-synchronizing literal is also the general form, but it has a length cap ๐ The quoted string is the shortcut that skips the literal processing overhead, but it can't hold every character ๐
When the difference between synchronizing and non-synchronizing literals doesn't matter, this document just says "literal" ๐
A synchronizing literal is zero or more octets (CR and LF included) with a prefix that has the octet count in the form of an open brace ({), the number of octets, a close brace (}), and then a CRLF ๐ง When the server sends a synchronizing literal to the client, the octet data comes right after the CRLF ๐ When the client sends one to the server, the client MUST wait to receive a command continuation request (more on that later in this document) before it sends the octet data and the rest of the command โณ
The non-synchronizing literal is a different flavor of synchronizing literal, and the client can use it anywhere a synchronizing literal is allowed ๐ซถ The non-synchronizing literal form MUST NOT be sent from server to client ๐ซ You can tell them apart because the non-synchronizing literal has a plus (+) between the octet count and the closing brace (}) โจ The server doesn't send a command continuation request back for a non-synchronizing literal, and clients don't have to wait before sending its octets ๐โโ๏ธ Unless an IMAP extension says otherwise, non-synchronizing literals MUST NOT be larger than 4096 octets ๐ Any literal bigger than 4096 bytes MUST be sent as a synchronizing literal ๐ฅ (The non-synchronizing literals in this document are the same as the ones defined by the LITERAL- extension from [RFC7888]. Read that document for how to handle invalid non-synchronizing literals longer than 4096 octets, and for how they interact with other IMAP extensions ๐)
A quoted string is zero or more Unicode characters, excluding CR and LF, encoded in UTF-8, wrapped in double quotes (<">) at each end ๐
The empty string can be written three ways: as "" (a quoted string with zero characters between the double quotes), as {0} followed by a CRLF (a synchronizing literal with an octet count of 0), or as {0+} followed by a CRLF (a non-synchronizing literal with an octet count of 0) ๐ซง
Note: Even if the octet count is 0, a client transmitting a synchronizing literal MUST wait to receive a command continuation request. ๐
4.3.1. 8-Bit and Binary Strings ๐
8-bit textual and binary mail is supported through a [MIME-IMB] content transfer encoding ๐จ IMAP4rev2 implementations MAY transmit 8-bit or multi-octet characters in literals, but they SHOULD only do that when the [CHARSET] is identified ๐
IMAP4rev2 is compatible with [I18N-HDRS] ๐ค So the identified charset for header-field values with 8-bit content is UTF-8 [UTF-8]. IMAP4rev2 implementations MUST accept [UTF-8] text in quoted-strings, and they MAY transmit it too, as long as the string doesn't contain NUL, CR, or LF ๐ญ This is a difference from IMAP4rev1 implementations, so keep that in mind ๐
A BINARY content transfer encoding is defined, but unencoded binary strings are NOT permitted, unless they come back in a <literal8> in response to a BINARY.PEEK[<section-binary>]<<partial>> or BINARY[<section-binary>]<<partial>> FETCH data item ๐
โโ๏ธ A "binary string" is any string with NUL characters. A string with an excessive number of CTL characters MAY also be considered binary ๐ซฃ Unless it's returned in response to a BINARY.PEEK[...]/BINARY[...] FETCH, client and server implementations MUST encode binary data into a textual form, such as base64, before transmitting it ๐
4.4. Parenthesized List ๐งบ
data structures are shown as a "parenthesized list": a sequence of data items, separated by spaces, and wrapped in parentheses at each end ๐ A parenthesized list can contain other parenthesized lists, using multiple levels of parentheses to show nesting ๐ช
The empty list is written as (), which is a parenthesized list with no members ๐ซง
4.5. NIL โจ
okay so NIL is the special form that means "this thing just isn't there" ๐ซฅ It's for data items that show up as a string or a parenthesized list. It is NOT the same as "" (the empty string) or () (the empty list), which are both there, just empty ๐
Note: NIL is never used for any data item that takes the form of an atom ๐ซ For example, a mailbox name of"NIL"is a mailbox named NIL, as opposed to a mailbox name that doesn't exist. That's because mailbox usesastringsyntax, which is an atom or a string. Flip it around, and an addr-name of NIL is a non-existent personal name, because addr-name usesnstringsyntax, which is NIL or a string, but never an atom ๐คฏ
Examples time ๐
The following LIST response:
* LIST () "/" NIL
is equivalent to:
* LIST () "/" "NIL"
as LIST response ABNF is using astring for mailbox name. Iconic, right? ๐ง
However, the following response:
* FETCH 1 (BODY[1] NIL)
is NOT equivalent to:
* FETCH 1 (BODY[1] "NIL")
The former means the body part is absent ๐ป, while the latter means it contains a string with the three characters "NIL". Not the same vibe at all ๐
5. Operational Considerations ๐ธ
okay bestie, these are the rules we need to follow so that every IMAP4rev2 implementation actually plays nicely with the others ๐ซถ
5.1. Mailbox Naming ๐ฌ
In IMAP4rev2, mailbox names are encoded in Net-Unicode [NET-UNICODE] (this is different from IMAP4rev1, so pay attention ๐). Client implementations MAY try to create Net-Unicode mailbox names, and they MUST interpret any 8-bit mailbox names returned by LIST as [NET-UNICODE]. Server implementations MUST prohibit the creation of 8-bit mailbox names that don't comply with Net-Unicode. Servers MAY accept a denormalized UTF-8 mailbox name, but they have to convert it to Unicode Normalization Form C (NFC) (as per Net-Unicode requirements) before creating the mailbox โจ Servers that choose to accept those denormalized UTF-8 names MUST accept them in every IMAP command that has a mailbox name parameter. Like, SELECT <name> MUST open the same mailbox that CREATE <name> made, even if <name> is a denormalized UTF-8 mailbox name. No excuses ๐
The case-insensitive mailbox name INBOX is a special name reserved to mean "the primary mailbox for this user on this server" ๐ฅ (Heads up: this special name might not exist on some servers for some users, for example if the user has no access to a personal namespace.) The interpretation of all other names is implementation dependent ๐คทโโ๏ธ
This specification takes NO position on case sensitivity in non-INBOX mailbox names. Some servers are fully case sensitive in the ASCII range, some preserve the case of a newly created name but are otherwise case insensitive, and others coerce names to one particular case ๐ Client implementations must be able to interact with any of these. Bestie, that's the whole job ๐ญ
There are certain client considerations when creating a new mailbox name:
- Any character that is one of the atom-specials (see "Formal Syntax" in Section 9) will require that the mailbox name be represented as a quoted string or literal ๐
- CTL and other non-graphic characters are difficult to show in a user interface and are best avoided ๐ Servers MAY refuse to create mailbox names containing Unicode CTL characters.
- Although the list-wildcard characters ("%" and "*") are valid in a mailbox name, it is difficult to use such mailbox names with the LIST command because of the conflict with wildcard interpretation ๐
- Usually, a character (determined by the server implementation) is reserved to delimit levels of hierarchy ๐ณ
- Two characters, "#" and "&", have meanings by convention and should be avoided except when used in that convention. See Section 5.1.2.1 and Appendix A.1, respectively ๐ฆ
5.1.1. Mailbox Hierarchy Naming ๐ฟ
If you want to export hierarchical mailbox names, mailbox names MUST be left-to-right hierarchical, using a single ASCII character to separate levels of hierarchy. The same hierarchy separator character is used for all levels of hierarchy within a single name. One separator, all the way down ๐ง
5.1.2. Namespaces ๐๏ธ
Personal Namespace: A namespace that the server considers within the personal scope of the authenticated user on a particular connection. Typically, only the authenticated user has access to mailboxes in their Personal Namespace ๐ It's the part of the namespace that belongs to the user and is set aside for mailboxes. If an INBOX exists for a user, it MUST appear within the user's Personal Namespace. In the typical case, there SHOULD be only one Personal Namespace per user on a server.
Other Users' Namespace: A namespace that consists of mailboxes from the Personal Namespaces of other users. To access mailboxes in the Other Users' Namespace, the currently authenticated user MUST be explicitly granted access rights. For example, it's super common for a manager to grant their admin support staff access to their mailbox ๐ผ In the typical case, there SHOULD be only one Other Users' Namespace per user on a server.
Shared Namespace: A namespace that consists of mailboxes that are meant to be shared amongst users and do NOT exist within a user's Personal Namespace ๐ค
The namespaces a server uses MAY differ on a per-user basis ๐
5.1.2.1. Historic Mailbox Namespace Naming Convention ๐
By convention, the first hierarchical element of any mailbox name that begins with "#" identifies the "namespace" of the rest of the name. This makes it possible to tell apart different types of mailbox stores, each of which has its own namespaces ๐
For example, implementations that offer access to USENET newsgroups MAY use the "#news" namespace to keep the USENET newsgroup namespace separate from other mailboxes. So the comp.mail.misc newsgroup would have a mailbox name of "#news.comp.mail.misc", and the name "comp.mail.misc" can refer to a different object (e.g., a user's private mailbox) ๐๏ธ
Namespaces that include the "#" character are not IMAP URL [IMAP-URL] friendly and need the "#" character to be written as %23 inside URLs ๐ฌ Because of that, server implementors MAY instead consider using namespace prefixes that don't contain the "#" character.
5.1.2.2. Common Namespace Models ๐๏ธ
The previous version of this protocol did not define a default server namespace, so two common namespace models have evolved ๐ฑ
The "Personal Mailbox" model is where the default namespace presented consists of only the user's personal mailboxes. To reach shared mailboxes, the user has to use an escape mechanism to get to another namespace ๐ช
The "Complete Hierarchy" model is where the default namespace presented includes the user's personal mailboxes along with any other mailboxes they have access to ๐
5.2. Mailbox Size and Message Status Updates ๐
At any time, a server can send data that the client didn't ask for ๐ Sometimes this behavior is required by this specification and/or extensions. For example, other agents besides the server may add messages to the mailbox (like new message delivery), change the flags of messages in the mailbox (like simultaneous access to the same mailbox by multiple agents), or even remove messages from the mailbox. A server MUST send mailbox size updates automatically if a mailbox size change is observed while processing a command. A server SHOULD send message flag updates automatically, without the client having to request them explicitly ๐ฅ
There are special rules for server notification of a client about the removal of messages, to prevent synchronization errors. See the description of the EXPUNGE response (Section 7.5.1) for more detail ๐ In particular, it is NOT permitted to send an EXISTS response that would reduce the number of messages in the mailbox. Only the EXPUNGE response can do that ๐ โโ๏ธ
Whatever a client decides about remembering data from the server, a client implementation MUST remember mailbox size updates. It MUST NOT assume that any command after the initial mailbox selection will return the size of the mailbox ๐ง
5.3. Response When No Command in Progress โณ
Server implementations are allowed to send an untagged response (except for EXPUNGE) while no command is in progress ๐ฆ Server implementations that send such responses MUST deal with flow control considerations. Specifically, they MUST either (1) verify that the size of the data does not exceed the underlying transport's available window size or (2) use non-blocking writes ๐
5.4. Autologout Timer โฐ
If a server has an inactivity autologout timer that applies to sessions after authentication, the duration of that timer MUST be at least 30 minutes. Any command the client sends during that interval resets the autologout timer ๐ซง
Note that this specification doesn't put any restrictions on an autologout timer used before successful client authentication ๐ In particular, servers are allowed to use a shortened pre-authentication timer to protect themselves from Denial-of-Service attacks ๐ก๏ธ
5.5. Multiple Commands in Progress (Command Pipelining) โจ
Okay so, the client is allowed to fire off another command without waiting for the completion result of the one before it ๐. That's the vibe, but it's subject to ambiguity rules and to flow control on the underlying data stream. The server gets the same freedom: it can start working on another command before it finishes the current one, still subject to those ambiguity rules. BUT, and this is a big but, any command continuation request responses and command continuations MUST be negotiated before any subsequent command is initiated ๐ซถ.
The exception is when an ambiguity would happen because one command would change the results of other commands. If the server spots a possible ambiguity, it MUST execute commands to completion in the order the client gave them ๐.
The most obvious example of ambiguity is when one command would affect the results of another. Like, a FETCH that sets \Seen flags, followed by a SEARCH UNSEEN command. Literally the same messages are involved, so the order matters ๐.
Now the non-obvious one, and this is where it gets spicy ๐ถ๏ธ. Commands that are allowed to get an untagged EXPUNGE response (so, anything other than FETCH, STORE, and SEARCH) can cause trouble, because an untagged EXPUNGE response can invalidate sequence numbers in a later command. FETCH, STORE, and SEARCH are fine, though, because servers are prohibited from sending EXPUNGE responses while any of those commands are in progress. So if the client sends any command other than FETCH, STORE, or SEARCH, it MUST wait for the completion result response before sending a command that uses message sequence numbers ๐.
Note: EXPUNGE responses are permitted while UID FETCH, UID STORE, and UID SEARCH are in progress. If the client sends a UID command, it MUST wait for a completion result response before sending a command that uses message sequence numbers (this may include UID SEARCH). Any message sequence numbers in an argument to UID SEARCH are associated with messages prior to the effect of any untagged EXPUNGE responses returned by the UID SEARCH.
Here are the non-waiting sequences that are INVALID (no cap, these are a no-go ๐ โโ๏ธ):
FETCH + NOOP + STORE
STORE + COPY + FETCH
COPY + COPY
And these are the valid non-waiting sequences, the ones you can actually use โจ:
FETCH + STORE + SEARCH + NOOP
STORE + COPY + EXPUNGE
UID SEARCH + UID SEARCH is giving "it depends" ๐คทโโ๏ธ. It may be valid or invalid as a non-waiting command sequence, depending on whether or not the second UID SEARCH contains message sequence numbers.
Last thing: using a SEARCH result variable (see Section 6.4.4.1) creates a direct dependency between two commands, so they're basically linked. For more considerations about pipelining dependent commands like that, check Section 6.4.4.2 ๐ง.
6. Client Commands ๐
Okay this is where the actual commands live ๐ . They're organised by the state in which each one is allowed. Commands that are allowed in multiple states get listed under the minimum permitted state. So anything valid in both authenticated and selected states shows up in the authenticated state commands ๐ธ.
The arguments of each command, the ones marked "Arguments:" in the descriptions below, are described by what they do, not by their syntax. The precise syntax lives in "Formal Syntax" (Section 9) ๐ฆ.
Some commands make specific server responses come back. Those are marked "Responses:" below. For what those responses mean, look in "Responses" (Section 7), and for their exact syntax, look in "Formal Syntax" (Section 9) ๐. Server data can show up as a result of ANY command, so commands that don't specifically need server data say "no specific responses for this command" instead of "none". Iconic honesty ๐ญ.
The "Result:" line refers to the possible tagged status responses to a command, plus any special meaning those status responses have ๐.
A connection's state only changes through successful commands that are documented as changing state. A rejected command (BAD response) NEVER changes the state of the connection or the selected mailbox, so that's a hard no ๐ โโ๏ธ. A failed command (NO response) usually doesn't change the state either, with the exception of SELECT and EXAMINE ๐.
6.1. Client Commands - Any State ๐
The following commands are valid in any state: CAPABILITY, NOOP, and LOGOUT. Main character commands, always available โญ.
6.1.1. CAPABILITY Command ๐
Arguments: none
Responses: REQUIRED untagged response: CAPABILITY
Result: OK - capability completed
BAD - arguments invalid
The CAPABILITY command asks the server for a list of its capabilities (extensions and/or changes to how the server behaves). The server MUST send a single untagged CAPABILITY response that includes "IMAP4rev2" as one of the listed capabilities, and it has to do that before the (tagged) OK response ๐ง.
A capability name that starts with "AUTH=" means the server supports that particular authentication mechanism, as defined in the Simple Authentication and Security Layer (SASL) [SASL]. All of those names are, by definition, part of this specification ๐.
Other capability names refer to extensions, revisions, or amendments to this specification. The CAPABILITY response in Section 7.2.2 has more info on those. If the IMAP4rev1 capability isn't advertised, then no capabilities beyond the base IMAP4rev2 set in this specification are enabled unless the client explicitly does something to invoke them. If BOTH IMAP4rev1 and IMAP4rev2 capabilities are advertised, then no capabilities beyond the base IMAP4rev1 set specified in [RFC3501] are enabled unless the client explicitly invokes them ๐ฆ.
Client and server implementations MUST implement the STARTTLS (Section 6.2.1) and LOGINDISABLED capabilities on cleartext ports. Client and server implementations MUST ALSO implement the AUTH=PLAIN capability (described in [PLAIN]) on both cleartext and Implicit TLS ports. Go read the Security Considerations (Section 11) for the important stuff, seriously ๐ฅ.
Unless otherwise specified, all registered extensions to IMAP4rev1 are also valid extensions to IMAP4rev2 โจ.
Example:
C: abcd CAPABILITY
S: * CAPABILITY IMAP4rev2 STARTTLS AUTH=GSSAPI
LOGINDISABLED
S: abcd OK CAPABILITY completed
C: efgh STARTTLS
S: efgh OK STARTTLS completed
<TLS negotiation, further commands are under TLS layer>
C: ijkl CAPABILITY
S: * CAPABILITY IMAP4rev2 AUTH=GSSAPI AUTH=PLAIN
S: ijkl OK CAPABILITY completed
6.1.2. NOOP Command ๐
Arguments: none
Responses: no specific responses for this command (but see below)
Result: OK - noop completed
BAD - command unknown or arguments invalid
The NOOP command always succeeds. It does nothing. Iconic energy ๐ .
Since any command can return a status update as untagged data, NOOP can be used as a periodic poll for new messages or message status updates during a period of inactivity (the IDLE command; see Section 6.3.13) should be used instead of NOOP if real-time updates to mailbox state are desirable). NOOP can also be used to reset any inactivity autologout timer on the server โฐ.
Example:
C: a002 NOOP
S: a002 OK NOOP completed
. . .
C: a047 NOOP
S: * 22 EXPUNGE
S: * 23 EXISTS
S: * 14 FETCH (UID 1305 FLAGS (\Seen \Deleted))
S: a047 OK NOOP completed
6.1.3. LOGOUT Command ๐
Arguments: none
Responses: REQUIRED untagged response: BYE
Result: OK - logout completed
BAD - command unknown or arguments invalid
The LOGOUT command tells the server the client is done with the connection ๐งโโ๏ธ. The server MUST send a BYE untagged response before the (tagged) OK response, and then close the network connection.
Example:
C: A023 LOGOUT
S: * BYE IMAP4rev2 Server logging out
S: A023 OK LOGOUT completed
(Server and client then close the connection)
6.2. Client Commands - Not Authenticated State ๐
In the not authenticated state, the AUTHENTICATE or LOGIN command establishes authentication and moves you into the authenticated state ๐ช. AUTHENTICATE is the general-purpose option, covering a whole bunch of authentication techniques, privacy protection, and integrity checking. LOGIN uses a regular user name and plaintext password pair, and it has NO way to establish privacy protection or integrity checking, so it's the least fancy option ๐ซฃ.
The STARTTLS command is another way to set up session privacy protection and integrity checking. It does NOT, by itself, establish authentication or move you into the authenticated state ๐.
Server implementations MAY allow access to certain mailboxes without establishing authentication. This can be done with the ANONYMOUS [SASL] authenticator described in [ANONYMOUS]. An older convention is a LOGIN command using the userid "anonymous". In that case a password is required, although the server may choose to accept any password. The restrictions on anonymous users are implementation dependent ๐ธ.
Once you've authenticated (including as anonymous), it is not possible to re-enter the not authenticated state. No going back, bestie ๐.
In addition to the universal commands (CAPABILITY, NOOP, and LOGOUT), these commands are valid in the not authenticated state: STARTTLS, AUTHENTICATE, and LOGIN. Read the Security Considerations (Section 11) for important information about these commands ๐ฅ.
6.2.1. STARTTLS Command โจ
- Arguments: none
- Responses: no specific response for this command
- Result:
OK - starttls completed, begin TLS negotiation
NO - TLS negotiation can't be initiated, due to server
configuration error
BAD - STARTTLS received after a successful TLS
negotiation or arguments invalid
Okay so, STARTTLS only works on cleartext ports ๐ง. The server MUST always respond with a tagged BAD response when it gets the STARTTLS command on an Implicit TLS port. That's a hard no, bestie ๐.
The TLS [TLS-1.3] negotiation kicks off right after the CRLF at the end of the server's tagged OK response. Once the client sends STARTTLS, it MUST NOT issue any more commands until it sees a server response and the TLS negotiation is finished. Lowkey, this part is so important ๐ .
Some older server implementations messed up their STARTTLS processing and are known to have a STARTTLS plaintext command injection vulnerability [CERT-555316] ๐. To avoid that, server implementations MUST do one of the following if any data shows up in the same TCP buffer after the CRLF that starts the STARTTLS command:
- Extra data from the TCP buffer is interpreted as the beginning of the TLS handshake. (If the data is in cleartext, this will result in the TLS handshake failing.)
- Extra data from the TCP buffer is thrown away.
Option one is the friendlier one for clients that pipeline the start of the STARTTLS command with TLS handshake data ๐ซถ.
After a successful TLS negotiation, the server stays in the non-authenticated state, even if the client supplies credentials during the TLS negotiation. That doesn't block an authentication mechanism like EXTERNAL (defined in [SASL]) from using the client identity that came out of the TLS negotiation โจ.
Once TLS has started, the client MUST discard cached information about server capabilities and SHOULD reissue the CAPABILITY command. This is needed to protect against active attacks that change the capabilities list before STARTTLS ๐ก๏ธ. The server MAY advertise different capabilities. In particular, after a successful STARTTLS command it SHOULD NOT advertise the STARTTLS capability ๐ธ.
Example:
C: a001 CAPABILITY
S: * CAPABILITY IMAP4rev2 STARTTLS LOGINDISABLED
S: a001 OK CAPABILITY completed
C: a002 STARTTLS
S: a002 OK Begin TLS negotiation now
<TLS negotiation, further commands are under TLS layer>
C: a003 CAPABILITY
S: * CAPABILITY IMAP4rev2 AUTH=PLAIN
S: a003 OK CAPABILITY completed
C: a004 AUTHENTICATE PLAIN dGVzdAB0ZXN0AHRlc3Q=
S: a004 OK Success (tls protection)
6.2.2. AUTHENTICATE Command โจ
Arguments: SASL authentication mechanism name
OPTIONAL initial response
Responses: continuation data can be requested
Result: OK - authenticate completed, now in authenticated
state
NO - authenticate failure: unsupported authentication
mechanism, credentials rejected
BAD - command unknown or arguments invalid,
authentication exchange canceled
okay so AUTHENTICATE is the command where the client basically goes "hey, I wanna log in with THIS [SASL] authentication mechanism" ๐ If the server supports that mechanism, it runs a whole authentication exchange to authenticate and identify the client. It MAY also negotiate an OPTIONAL security layer for everything that comes after ๐ซถ If the requested mechanism isn't supported, the server SHOULD reject the AUTHENTICATE command by sending a tagged NO response. Not the vibe ๐
The AUTHENTICATE command supports the optional "initial response" feature defined in Section 4 of [SASL] โจ The client doesn't need to use it. If a SASL mechanism supports "initial response" but the client doesn't specify one, the server handles it as specified in Section 3 of [SASL].
The service name specified by this protocol's profile of [SASL] is "imap" ๐
The authentication exchange is a back-and-forth of server challenges and client responses, and they're specific to whichever mechanism you picked ๐ฌ A server challenge is a command continuation request response with the + token, followed by a base64-encoded (see Section 4 of [RFC4648]) string. The client response is a single line holding a base64-encoded string. If the client wants to bail on the exchange, it sends a line that's just *. If the server gets that, or gets an invalid base64 string (like characters outside the base64 alphabet or a non-terminal =), it MUST reject the AUTHENTICATE command by sending a tagged BAD response. Big no-no zone ๐
โโ๏ธ
As with any other client response, the initial response MUST be encoded as base64 ๐
It also MUST be transmitted outside of a quoted string or literal. To send a zero-length initial response, the client MUST send a single pad character (=). That's how it says "the response is here, it's just empty" ๐ง
When decoding the base64 data in the initial response, decoding errors MUST be treated like they would be for any normal SASL client response, which means a tagged BAD response ๐ญ The server should also check for any characters that aren't in the base64 alphabet, plus any base64 sequence that has the pad character ('=') somewhere other than the end of the string. So =AAA and AAA=BBB are both a no-go ๐
If the client sends an initial response with a SASL mechanism that doesn't support one, the server MUST reject the command with a tagged BAD response ๐ซ
If a security layer gets negotiated through the [SASL] authentication exchange, it kicks in right after the CRLF that wraps up the exchange on the client side, and the CRLF of the tagged OK response on the server side ๐
While client and server implementations MUST implement the AUTHENTICATE command itself, they're NOT required to implement any authentication mechanisms other than PLAIN, which is described in [PLAIN] ๐ Also, an authentication mechanism doesn't have to support any security layers at all.
Note: a server implementation MUST implement a configuration in which it does NOT permit any plaintext password mechanisms, unless the STARTTLS command has been negotiated, TLS has been negotiated on an Implicit TLS port, or some other mechanism that protects the session from password snooping has been provided. Server sites SHOULD NOT use any configuration that permits a plaintext password mechanism without such a protection mechanism against password snooping. Client and server implementations SHOULD implement additional [SASL] mechanisms that do not use plaintext passwords, such as the GSSAPI mechanism described in [RFC4752], the SCRAM-SHA-256/SCRAM-SHA-256-PLUS [SCRAM-SHA-256] mechanisms, and/or the EXTERNAL [SASL] mechanism for mutual TLS authentication. (Note that the SASL framework allows for the creation of SASL mechanisms that support 2-factor authentication (2FA); however, none are fully ready to be recommended by this document.)
Plaintext passwords are a whole security nightmare, so please, bestie, don't set up your server to allow them unless something is protecting the session ๐
Servers and clients can support multiple authentication mechanisms ๐ฆ The server SHOULD list its supported authentication mechanisms in the response to the CAPABILITY command so the client knows which ones to pick from.
A server MAY include a CAPABILITY response code in the tagged OK response of a successful AUTHENTICATE command, so it can send capabilities automatically โจ It's unnecessary for the client to send a separate CAPABILITY command if it already recognizes those automatic capabilities. This should only be done if a security layer wasn't negotiated by the AUTHENTICATE command, because the tagged OK response from an AUTHENTICATE command isn't protected by encryption or integrity checking. [SASL] requires the client to re-issue a CAPABILITY command in this case. The server MAY advertise different capabilities after a successful AUTHENTICATE command ๐
If an AUTHENTICATE command fails with a NO response, the client MAY try another authentication mechanism by issuing another AUTHENTICATE command ๐ It MAY also attempt to authenticate using the LOGIN command (see Section 6.2.3 for more detail). In other words, the client MAY request authentication types in decreasing order of preference, with the LOGIN command as a last resort ๐ซ
The authorization identity passed from the client to the server during the authentication exchange gets interpreted by the server as the user name whose privileges the client is requesting ๐
Example:
S: * OK [CAPABILITY IMAP4rev2 STARTTLS AUTH=GSSAPI]
Capabilities
C: A001 AUTHENTICATE GSSAPI
S: +
C: YIIB+wYJKoZIhvcSAQICAQBuggHqMIIB5qADAgEFoQMCAQ6iBw
MFACAAAACjggEmYYIBIjCCAR6gAwIBBaESGxB1Lndhc2hpbmd0
b24uZWR1oi0wK6ADAgEDoSQwIhsEaW1hcBsac2hpdmFtcy5jYW
Mud2FzaGluZ3Rvbi5lZHWjgdMwgdCgAwIBAaEDAgEDooHDBIHA
cS1GSa5b+fXnPZNmXB9SjL8Ollj2SKyb+3S0iXMljen/jNkpJX
AleKTz6BQPzj8duz8EtoOuNfKgweViyn/9B9bccy1uuAE2HI0y
C/PHXNNU9ZrBziJ8Lm0tTNc98kUpjXnHZhsMcz5Mx2GR6dGknb
I0iaGcRerMUsWOuBmKKKRmVMMdR9T3EZdpqsBd7jZCNMWotjhi
vd5zovQlFqQ2Wjc2+y46vKP/iXxWIuQJuDiisyXF0Y8+5GTpAL
pHDc1/pIGmMIGjoAMCAQGigZsEgZg2on5mSuxoDHEA1w9bcW9n
FdFxDKpdrQhVGVRDIzcCMCTzvUboqb5KjY1NJKJsfjRQiBYBdE
NKfzK+g5DlV8nrw81uOcP8NOQCLR5XkoMHC0Dr/80ziQzbNqhx
O6652Npft0LQwJvenwDI13YxpwOdMXzkWZN/XrEqOWp6GCgXTB
vCyLWLlWnbaUkZdEYbKHBPjd8t/1x5Yg==
S: + YGgGCSqGSIb3EgECAgIAb1kwV6ADAgEFoQMCAQ+iSzBJoAMC
AQGiQgRAtHTEuOP2BXb9sBYFR4SJlDZxmg39IxmRBOhXRKdDA0
uHTCOT9Bq3OsUTXUlk0CsFLoa8j+gvGDlgHuqzWHPSQg==
C:
S: + YDMGCSqGSIb3EgECAgIBAAD/////6jcyG4GE3KkTzBeBiVHe
ceP2CWY0SR0fAQAgAAQEBAQ=
C: YDMGCSqGSIb3EgECAgIBAAD/////3LQBHXTpFfZgrejpLlLImP
wkhbfa2QteAQAgAG1yYwE=
S: A001 OK GSSAPI authentication successful
Now the next one, the initial response example ๐
S: * OK [CAPABILITY IMAP4rev2 STARTTLS AUTH=GSSAPI
LOGINDISABLED] Server ready
C: A01 STARTTLS
S: A01 OK STARTTLS completed
<TLS negotiation, further commands are under TLS layer>
C: A02 CAPABILITY
S: * CAPABILITY IMAP4rev2 AUTH=GSSAPI AUTH=PLAIN
S: A02 OK CAPABILITY completed
C: A03 AUTHENTICATE PLAIN dGVzdAB0ZXN0AHRlc3Q=
S: A03 OK Success (tls protection)
Because the initial response is optional, the negotiation that skips it is still totally valid, and the server MUST support it ๐ซถ Here it is:
... client connects to server and negotiates a TLS
protection layer ...
C: C01 CAPABILITY
S: * CAPABILITY IMAP4rev2 AUTH=PLAIN
S: C01 OK Completed
C: A01 AUTHENTICATE PLAIN
S: +
C: dGVzdAB0ZXN0AHRlc3Q=
S: A01 OK Success (tls protection)
Heads up, in the example above there's a space after the server's "+" ๐
Last one, using SASL EXTERNAL under a TLS protection layer with an empty initial response ๐ฆ
... client connects to server and negotiates a TLS
protection layer ...
C: C01 CAPABILITY
S: * CAPABILITY IMAP4rev2 AUTH=PLAIN AUTH=EXTERNAL
S: C01 OK Completed
C: A01 AUTHENTICATE EXTERNAL =
S: A01 OK Success (tls protection)
Note: The line breaks within server challenges and client responses are for editorial clarity and are not in real authenticators.
6.2.3. LOGIN Command ๐
Arguments: user name
password
Responses: no specific responses for this command
Result: OK - login completed, now in authenticated state
NO - login failure: user name or password rejected
BAD - command unknown or arguments invalid
The LOGIN command identifies the client to the server and carries the plaintext password for this user ๐ฌ The LOGIN command SHOULD NOT be used except as a last resort (after attempting and failing to authenticate with AUTHENTICATE one or more times), and it is recommended that client implementations have a way to turn off any automatic use of the LOGIN command. Last resort energy only, periodt ๐
A server MAY include a CAPABILITY response code in the tagged OK response to a successful LOGIN command, so it can send capabilities automatically โจ It's unnecessary for a client to send a separate CAPABILITY command if it recognizes these automatic capabilities.
Example:
C: a001 LOGIN SMITH SESAME
S: a001 OK LOGIN completed
Note: Use of the LOGIN command over an insecure network (such as the Internet) is a security risk, because anyone monitoring network traffic can obtain plaintext passwords. For that reason, clients MUST NOT use LOGIN on unsecure networks. ๐จ
Unless the client is accessing IMAP service on an Implicit TLS port [RFC8314], the STARTTLS command has been negotiated, or some other mechanism that protects the session from password snooping has been provided, a server implementation MUST implement a configuration in which it advertises the LOGINDISABLED capability and does NOT permit the LOGIN command ๐ โโ๏ธ Server sites SHOULD NOT use any configuration that permits the LOGIN command without such a protection mechanism against password snooping. A client implementation MUST NOT send a LOGIN command if the LOGINDISABLED capability is advertised. Respect the LOGINDISABLED ๐ซถ
6.3. Client Commands - Authenticated State ๐ธ
In the authenticated state, commands that manipulate mailboxes as atomic entities are permitted โจ Of those, SELECT and EXAMINE will select a mailbox for access and move you into the selected state ๐ง
In addition to the universal commands (CAPABILITY, NOOP, and LOGOUT), these commands are valid in the authenticated state: ENABLE, SELECT, EXAMINE, NAMESPACE, CREATE, DELETE, RENAME, SUBSCRIBE, UNSUBSCRIBE, LIST, STATUS, APPEND, and IDLE ๐
6.3.1. ENABLE Command โจ
Arguments: capability names
Responses: no specific responses for this command
Result:
- OK - Relevant capabilities enabled
- BAD - No arguments, or syntax error in an argument
Okay so, a lot of IMAP extensions let the server send special unsolicited responses, right? But the server can't send those until it knows the client actually speaks that extension, otherwise the client would get data it can't parse ๐ญ. The one exception is response codes (see Section 7.1) tucked inside tagged or untagged OK/NO/BAD responses, since those are always allowed ๐ .
So ENABLE is the client's way of saying "hey, I support these" ๐ซถ. It's designed so the client can send one simple constant string listing the extensions it knows, and the server turns on the shared subset that both of them support. Iconic, right? ๐ฆ
The ENABLE command takes a list of capability names and asks the server to switch those extensions on. Once something is enabled with ENABLE, it stays on until the IMAP connection closes. For each argument, the server does the following:
- If the argument is not an extension known to the server, the server MUST ignore the argument.
- If the argument is an extension known to the server, and it is not specifically permitted to be enabled using ENABLE, the server MUST ignore the argument. (Note that knowing about an extension doesn't necessarily imply supporting that extension. ๐)
- If the argument is an extension that is supported by the server and that needs to be enabled, the server MUST enable the extension for the duration of the connection. Note that once an extension is enabled, there is no way to disable it. No take-backs, bestie ๐.
If the ENABLE command is successful, the server MUST send an untagged ENABLED response (Section 7.2.1), which includes all enabled extensions as specified above. The ENABLED response is sent even if no extensions were enabled, so you'll always get one back โจ.
Clients SHOULD only include extensions that need to be enabled by the server. For example, a client can enable IMAP4rev2-specific behavior when both IMAP4rev1 and IMAP4rev2 are advertised in the CAPABILITY response. Future RFCs may add to this list ๐.
The ENABLE command is only valid in the authenticated state, before any mailbox is selected. Clients MUST NOT issue ENABLE once they SELECT/EXAMINE a mailbox. Servers don't have to check whether a mailbox was selected or previously selected during the connection, though ๐.
The ENABLE command can be issued multiple times in a session, and it's additive. So "ENABLE a b", followed by "ENABLE c", is the same as one single command "ENABLE a b c" ๐ง. When multiple ENABLE commands are issued, each corresponding ENABLED response SHOULD only contain extensions enabled by that particular ENABLE command. So for the example above, the ENABLED response to "ENABLE c" should not contain "a" or "b" ๐.
There are no limitations on pipelining ENABLE. For example, you can send ENABLE and then immediately SELECT, or send a LOGIN immediately followed by ENABLE ๐.
The server MUST NOT change the CAPABILITY list as a result of executing ENABLE. That means a CAPABILITY command issued right after an ENABLE command MUST list the same capabilities as a CAPABILITY command issued before the ENABLE command. Here's how that plays out. Note that "X-GOOD-IDEA" below is a fictitious extension capability that can be ENABLED ๐.
C: t1 CAPABILITY
S: * CAPABILITY IMAP4rev2 ID LITERAL+ X-GOOD-IDEA
S: t1 OK foo
C: t2 ENABLE CONDSTORE X-GOOD-IDEA
S: * ENABLED X-GOOD-IDEA
S: t2 OK foo
C: t3 CAPABILITY
S: * CAPABILITY IMAP4rev2 ID LITERAL+ X-GOOD-IDEA
S: t3 OK foo again
In the following example, the client enables the Conditional Store (CONDSTORE) extension [RFC7162] ๐:
C: a1 ENABLE CONDSTORE
S: * ENABLED CONDSTORE
S: a1 OK Conditional Store enabled
6.3.1.1. Note to Designers of Extensions That May Use the ENABLE Command
Extension designers, listen up ๐ฃ. You're discouraged from making extensions that require ENABLE, unless there's truly no good alternative design. Extensions that cause potentially incompatible behavior changes to deployed server responses (and therefore benefit from ENABLE) have a higher complexity cost than extensions that don't. So think twice before you go there ๐.
6.3.2. SELECT Command ๐
Arguments: mailbox name
Responses:
- REQUIRED untagged responses: FLAGS, EXISTS, LIST
- REQUIRED OK untagged responses: PERMANENTFLAGS, UIDNEXT, UIDVALIDITY
Result:
- OK - select completed, now in selected state
- NO - select failure, now in authenticated state: no such mailbox, can't access mailbox
- BAD - command unknown or arguments invalid
The SELECT command picks a mailbox so you can access the messages inside it ๐ฌ. Before the server returns an OK to the client, it MUST send the following untagged data. (The order of the individual responses doesn't matter, fr.) Heads up: earlier versions of this protocol, like the IMAP4rev1 version specified in [RFC2060], only required the FLAGS and EXISTS untagged responses and the UIDVALIDITY response code. So if your client needs to stay compatible with those older versions, you'll have to build default behavior for missing data, as discussed with each individual item ๐ฅน.
FLAGS Defined flags in the mailbox. See the description of the FLAGS response in Section 7.3.5 for more detail.
<n> EXISTS The number of messages in the mailbox. See the description of the EXISTS response in Section 7.4.1 for more detail.
LIST The server MUST return a LIST response with the mailbox name. The list of mailbox attributes MUST be accurate ๐ฏ. If the server allows denormalized UTF-8 mailbox names (see Section 5.1) and the supplied mailbox name differs from the normalized version, the server MUST return LIST with the OLDNAME extended data item. See Section 6.3.9.7 for more details.
OK [PERMANENTFLAGS (<list of flags>)] A list of message flags that the client can change permanently. If this is missing, the client should assume that all flags can be changed permanently.
OK [UIDNEXT <n>] The next unique identifier value. Refer to Section 2.3.1.1 for more information.
OK [UIDVALIDITY <n>] The unique identifier validity value. Refer to Section 2.3.1.1 for more information.
Only one mailbox can be selected at a time in a connection. If you want simultaneous access to multiple mailboxes, you need multiple connections ๐. The SELECT command automatically deselects any currently selected mailbox before it attempts the new selection. So if a mailbox is selected and a SELECT command that fails gets attempted, no mailbox is selected anymore ๐ฌ. When deselecting a selected mailbox, the server MUST return an untagged OK response with the "[CLOSED]" response code when the currently selected mailbox is closed (see Section 7.1).
If the client is permitted to modify the mailbox, the server SHOULD prefix the text of the tagged OK response with the "[READ-WRITE]" response code โ๏ธ.
If the client is not permitted to modify the mailbox but is permitted read access, the mailbox is selected as read-only, and the server MUST prefix the text of the tagged OK response to SELECT with the "[READ-ONLY]" response code ๐. Read-only access through SELECT differs from the EXAMINE command in that certain read-only mailboxes MAY permit the change of permanent state on a per-user (as opposed to global) basis. Netnews messages marked in a server-based .newsrc file are an example of that kind of per-user permanent state, which can be modified even with read-only mailboxes ๐๏ธ.
Example:
C: A142 SELECT INBOX
S: * 172 EXISTS
S: * OK [UIDVALIDITY 3857529045] UIDs valid
S: * OK [UIDNEXT 4392] Predicted next UID
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited
S: * LIST () "/" INBOX
S: A142 OK [READ-WRITE] SELECT completed
Example:
C: A142 SELECT INBOX
S: * 172 EXISTS
S: * OK [UIDVALIDITY 3857529045] UIDs valid
S: * OK [UIDNEXT 4392] Predicted next UID
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited
S: A142 OK [READ-WRITE] SELECT completed
[...some time later...]
C: A143 SELECT Drafts
S: * OK [CLOSED] Previous mailbox is now closed
S: * 5 EXISTS
S: * OK [UIDVALIDITY 9877410381] UIDs valid
S: * OK [UIDNEXT 102] Predicted next UID
S: * LIST () "/" Drafts
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S: * OK [PERMANENTFLAGS (\Deleted \Seen \Answered
\Flagged \Draft \*)] System flags and keywords allowed
S: A143 OK [READ-WRITE] SELECT completed
Note that IMAP4rev1-compliant servers can also send the untagged RECENT response that was deprecated in IMAP4rev2, e.g., "* 0 RECENT". Pure IMAP4rev2 clients are advised to ignore the untagged RECENT response ๐งน.
6.3.3. EXAMINE Command ๐
Arguments: mailbox name
Responses:
- REQUIRED untagged responses: FLAGS, EXISTS, LIST
- REQUIRED OK untagged responses: PERMANENTFLAGS, UIDNEXT, UIDVALIDITY
Result:
- OK - examine completed, now in selected state
- NO - examine failure, now in authenticated state: no such mailbox, can't access mailbox
- BAD - command unknown or arguments invalid
The EXAMINE command is identical to SELECT and returns the same output. The difference is that the selected mailbox is identified as read-only ๐. No changes to the permanent state of the mailbox are permitted, including per-user state. Hands off, no edits allowed ๐ โโ๏ธ.
The text of the tagged OK response to the EXAMINE command MUST begin with the "[READ-ONLY]" response code.
Example:
C: A932 EXAMINE blurdybloop
S: * 17 EXISTS
S: * OK [UIDVALIDITY 3857529045] UIDs valid
S: * OK [UIDNEXT 4392] Predicted next UID
S: * LIST () "/" blurdybloop
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S: * OK [PERMANENTFLAGS ()] No permanent flags permitted
S: A932 OK [READ-ONLY] EXAMINE completed
6.3.4. CREATE Command โจ
Arguments: mailbox name
Responses: OPTIONAL untagged response: LIST
Result: OK - create completed
NO - create failure: can't create mailbox with that
name
BAD - command unknown or arguments invalid
okay so CREATE is how you make a brand new mailbox ๐ฌ๐ You only get an OK back if a new mailbox with that name actually got made. Trying to create INBOX, or a name that already belongs to a mailbox, is an error, and any creation problem comes back as a tagged NO ๐ If a client sends a UTF-8 mailbox name that isn't a valid Net-Unicode name, the server MUST reject the creation or convert the name to Net-Unicode before making the mailbox. If the server does decide to normalize the name, it SHOULD send back an untagged LIST with an OLDNAME extended data item. The OLDNAME value is the name the client sent, and the name parameter is the normalized one ๐ง (Check Section 6.3.9.7 for the full details.)
Mailboxes created in one IMAP session MAY be announced to other IMAP sessions with an unsolicited LIST response ๐ฆ If the server automatically subscribes a mailbox when it gets created, then the unsolicited LIST response for each affected subscribed mailbox name MUST include the \Subscribed attribute. Main character energy for sure ๐
If the mailbox name ends with the server's hierarchy separator character (the one the server returned from LIST), that's the client saying "I plan to make names under this one." Servers that don't need that heads-up MUST ignore it. Either way, the name that actually gets created doesn't include the trailing hierarchy delimiter ๐ธ
If the hierarchy separator shows up somewhere in the middle of the name, the server SHOULD create any superior hierarchical names the CREATE command needs in order to finish successfully. So creating "foo/bar/zap" on a server where "/" is the separator SHOULD make foo/ and foo/bar/ if they don't already exist. It's giving nested folders ๐๏ธโจ
If a new mailbox gets the same name as one that was deleted, its unique identifiers MUST be greater than any unique identifiers used in the previous incarnation of the mailbox. The exception is when the new incarnation has a different unique identifier validity value. Check Section 6.4.9 for more on the UID command ๐ฅ
Example:
C: A003 CREATE owatagusiam/
S: A003 OK CREATE completed
C: A004 CREATE owatagusiam/blurdybloop
S: A004 OK CREATE completed
C: A005 CREATE NonNormalized
S: * LIST () "/" "Normalized" ("OLDNAME" ("NonNormalized"))
S: A005 OK CREATE completed
Okay the last example is a bit of a plot twist ๐ Picture "NonNormalized" as a non-NFC normalized Unicode name, and "Normalized" as its NFC version.
| Note: The interpretation of this example depends on whether "/"
| was returned as the hierarchy separator from LIST. If "/" is
| the hierarchy separator, a new level of hierarchy named
| "owatagusiam" with a member called "blurdybloop" is created.
| Otherwise, two mailboxes at the same hierarchy level are
| created.
6.3.5. DELETE Command ๐
Arguments: mailbox name
Responses: OPTIONAL untagged response: LIST
Result: OK - delete completed
NO - delete failure: can't delete mailbox with that
name
BAD - command unknown or arguments invalid
DELETE permanently removes the mailbox with the given name ๐ You only get a tagged OK when the mailbox is actually gone. Trying to delete INBOX, or a mailbox that doesn't exist, is an error.
The DELETE command MUST NOT remove inferior hierarchical names ๐ โโ๏ธ For example, if a mailbox "foo" has an inferior "foo.bar" (with "." as the hierarchy delimiter), removing "foo" MUST NOT remove "foo.bar". Deleting a name that has inferior hierarchical names AND the \Noselect mailbox name attribute is an error. (Look at the LIST response in Section 7.3.1 for more details.)
Deleting a name that has inferior hierarchical names is allowed as long as it doesn't have the \Noselect attribute. If the server won't let you delete the name while those inferiors exist, it SHOULD disallow the DELETE command with a tagged NO response, and that NO response SHOULD include the HASCHILDREN response code. Or the server MAY allow the DELETE and just set the \Noselect attribute on that name instead. Two valid vibes ๐
If the server returns an OK response, DELETE removes all the messages in that mailbox ๐ซถ
The highest-used unique identifier of the deleted mailbox MUST be preserved. That way, a new mailbox created with the same name won't reuse the old identifiers, unless the new incarnation has a different unique identifier validity value. See Section 6.4.9 for more on the UID command ๐ฆ
If the server decides to normalize the mailbox name, it SHOULD return an untagged LIST with the "\NonExistent" attribute and an OLDNAME extended data item. The OLDNAME value is the mailbox name the client supplied, and the name parameter is the normalized one. (Section 6.3.9.7 has the extra details.)
Mailboxes deleted in one IMAP session MAY be announced to other IMAP sessions with an unsolicited LIST response that includes the "\NonExistent" attribute ๐
Example:
C: A682 LIST "" *
S: * LIST () "/" blurdybloop
S: * LIST (\Noselect) "/" foo
S: * LIST () "/" foo/bar
S: A682 OK LIST completed
C: A683 DELETE blurdybloop
S: A683 OK DELETE completed
C: A684 DELETE foo
S: A684 NO Name "foo" has inferior hierarchical names
C: A685 DELETE foo/bar
S: A685 OK DELETE Completed
C: A686 LIST "" *
S: * LIST (\Noselect) "/" foo
S: A686 OK LIST completed
C: A687 DELETE foo
S: A687 OK DELETE Completed
Example:
C: A82 LIST "" *
S: * LIST () "." blurdybloop
S: * LIST () "." foo
S: * LIST () "." foo.bar
S: A82 OK LIST completed
C: A83 DELETE blurdybloop
S: A83 OK DELETE completed
C: A84 DELETE foo
S: A84 OK DELETE Completed
C: A85 LIST "" *
S: * LIST () "." foo.bar
S: A85 OK LIST completed
C: A86 LIST "" %
S: * LIST (\Noselect) "." foo
S: A86 OK LIST completed
6.3.6. RENAME Command ๐
Arguments: existing mailbox name
new mailbox name
Responses: OPTIONAL untagged response: LIST
Result: OK - rename completed
NO - rename failure: can't rename mailbox with that
name, can't rename to mailbox with that name
BAD - command unknown or arguments invalid
RENAME changes the name of a mailbox โจ You only get a tagged OK once the mailbox has actually been renamed. Renaming from a name that doesn't exist, or to a name that already exists, is an error. Any renaming problem comes back as a tagged NO ๐
If the name has inferior hierarchical names, those inferiors MUST also be renamed ๐ณ For example, renaming "foo" to "zap" will rename "foo/bar" (with "/" as the hierarchy delimiter) to "zap/bar".
If the server's hierarchy separator shows up in the new mailbox name, the server SHOULD create any superior hierarchical names the RENAME command needs in order to finish successfully. So renaming "foo/bar/zap" to "baz/rag/zowie" on a server where "/" is the separator in that namespace SHOULD create "baz/" and "baz/rag/" if they don't already exist ๐ง
The highest-used unique identifier of the old mailbox name MUST be preserved. That way a new mailbox created with the same name won't reuse the old identifiers, unless the new incarnation has a different unique identifier validity value. Check Section 6.4.9 for the UID command details ๐ฅ
Renaming INBOX is permitted and does NOT get a tagged BAD response. It has special behavior though: it moves all the messages in INBOX into a new mailbox with the given name, which leaves INBOX empty. If the server supports inferior hierarchical names of INBOX, those stay put when INBOX gets renamed. (Heads up: some servers disallow renaming INBOX with a tagged NO response, so clients need to handle that failure ๐)
If the server allows creating mailboxes with names that aren't valid Net-Unicode names, the server normalizes both the existing mailbox name parameter and the new mailbox name parameter. If the normalized version of either one differs from what was supplied, the server SHOULD return an untagged LIST response with an OLDNAME extended data item. The OLDNAME value is the existing mailbox name that was supplied, and the name parameter is the normalized new mailbox name (see Section 6.3.9.7). This lets the client match up the supplied name with the normalized one ๐ซถ
Mailboxes renamed in one IMAP session MAY be announced to other IMAP sessions with an unsolicited LIST response that has an OLDNAME extended data item.
In both of the cases above, if the server automatically subscribes a mailbox when it gets renamed, then the unsolicited LIST response for each affected subscribed mailbox name MUST include the \Subscribed attribute. No unsolicited LIST responses need to be sent for child mailboxes. When INBOX is successfully renamed, it's assumed a new INBOX gets created, so no unsolicited LIST responses need to be sent for INBOX in that case ๐
Examples:
C: A682 LIST "" *
S: * LIST () "/" blurdybloop
S: * LIST (\Noselect) "/" foo
S: * LIST () "/" foo/bar
S: A682 OK LIST completed
C: A683 RENAME blurdybloop sarasoop
S: A683 OK RENAME completed
C: A684 RENAME foo zowie
S: A684 OK RENAME Completed
C: A685 LIST "" *
S: * LIST () "/" sarasoop
S: * LIST (\Noselect) "/" zowie
S: * LIST () "/" zowie/bar
S: A685 OK LIST completed
C: Z432 LIST "" *
S: * LIST () "." INBOX
S: * LIST () "." INBOX.bar
S: Z432 OK LIST completed
C: Z433 RENAME INBOX old-mail
S: Z433 OK RENAME completed
C: Z434 LIST "" *
S: * LIST () "." INBOX
S: * LIST () "." INBOX.bar
S: * LIST () "." old-mail
S: Z434 OK LIST completed
Renaming a mailbox doesn't update the subscription info on the original name ๐ To keep subscriptions in sync, you can use this sequence of commands:
C: 1001 RENAME X Y
C: 1002 SUBSCRIBE Y
C: 1003 UNSUBSCRIBE X
Just a heads up: that sequence doesn't take care of updating the subscriptions for any child mailboxes of mailbox X ๐ธ
6.3.7. SUBSCRIBE Command ๐
okay bestie, this one is all about the subscribed list ๐ SUBSCRIBE adds a mailbox name to the server's "active" or "subscribed" set, the same set you see when you run LIST (SUBSCRIBED) ๐ฌ
Arguments: mailbox
Responses: no specific responses for this command
Result: OK - subscribe completed
NO - subscribe failure: can't subscribe to that name
BAD - command unknown or arguments invalid
if the subscription works, you get a tagged OK. if the mailbox is already subscribed, you also get a tagged OK, so no stress if you accidentally double-subscribe ๐ซถ
A server MAY validate the mailbox argument to SUBSCRIBE to check that it exists. โจ But it SHOULD NOT unilaterally remove an existing mailbox name from the subscription list, even if a mailbox by that name doesn't exist anymore ๐
๐ Note: this rule is there because a server site can totally choose to routinely remove a mailbox with a well-known name (like system-alerts) after its contents expire, with the plan of recreating it when new contents are ready. so the subscription should survive the gap.
Example:
C: A002 SUBSCRIBE #news.comp.mail.mime
S: A002 OK SUBSCRIBE completed
6.3.8. UNSUBSCRIBE Command ๐ฆ
UNSUBSCRIBE is the opposite energy ๐ธ it removes the specified mailbox name from that same "active" or "subscribed" set, the one LIST (SUBSCRIBED) shows you โจ
Arguments: mailbox name
Responses: no specific responses for this command
Result: OK - unsubscribe completed
NO - unsubscribe failure: can't unsubscribe that name
BAD - command unknown or arguments invalid
Same vibe as SUBSCRIBE: a tagged OK comes back if the unsubscription succeeds, and also if the mailbox wasn't subscribed in the first place ๐ง
Example:
C: A002 UNSUBSCRIBE #news.comp.mail.mime
S: A002 OK UNSUBSCRIBE completed
6.3.9. LIST Command โจ
Arguments (basic):
reference name
mailbox name with possible wildcards
Arguments (extended):
selection options (OPTIONAL)
reference name
mailbox patterns
return options (OPTIONAL)
Responses: untagged responses: LIST
Result: OK - list completed
NO - list failure: can't list that reference or
mailbox name
BAD - command unknown or arguments invalid
okay so the LIST command is how a client asks "what mailboxes do you have??" ๐ฆ The server answers with zero or more untagged LIST responses, each carrying the name attributes, the hierarchy delimiter, the name, and any possible extension information. If you want the full tea on the LIST response, check out Section 7.3.1 ๐
The LIST command SHOULD return its data quickly, without undue delay ๐โโ๏ธ๐จ bestie, it should not go to excess trouble to calculate the \Marked or \Unmarked status or do other processing. Like, if each name needs 1 second of processing, then a list of 1200 names would take 20 minutes!
๐ twenty minutes for a mailbox list?? nah. Keep it snappy.
The extended LIST command was originally introduced in [RFC5258] โจ and it gives you way more power than the original IMAP LIST command. The extended syntax gets used if one or more of these conditions is true:
- the first word after the command name begins with a parenthesis (
"LIST selection options"); - the second word after the command name begins with a parenthesis; and
- the LIST command has more than 2 parameters (
"LIST return options").
An empty ("" string) reference name argument means the mailbox name is interpreted as by SELECT ๐
The returned mailbox names MUST match the supplied mailbox name pattern(s), no exceptions, periodt ๐ซถ A non-empty reference name argument is the name of a mailbox or a level of mailbox hierarchy, and it tells you the context the mailbox name gets read in. Clients SHOULD use the empty reference argument ๐ธ
In the basic syntax only, an empty ("" string) mailbox name argument is a special request to return the hierarchy delimiter and the root name of the name given in the reference ๐ง The value returned as the root MAY be the empty string if the reference is non-rooted or is an empty string. In all cases, a hierarchy delimiter (or NIL if there is no hierarchy) is returned. This is so iconic, because a client can get the hierarchy delimiter (or find out that the mailbox names are flat) even when no mailboxes by that name exist right now ๐
In the extended syntax, any mailbox name arguments that are empty strings are ignored. Empty mailbox names have no special meaning when the extended syntax is used ๐
The reference and mailbox name arguments get interpreted into a canonical form that represents an unambiguous left-to-right hierarchy. The returned mailbox names will be in the interpreted form, which we call a "canonical LIST pattern": the canonical pattern the server builds internally from the reference and mailbox name arguments โจ
Note: The interpretation of the reference argument is implementation defined. It depends on whether the server implementation has a concept of the "current working directory" and leading "break out characters", which override the current working directory.
For example, on a server that exports a UNIX or NT file system, the reference argument contains the current working directory, and the mailbox name argument contains the name as interpreted in the current working directory.
If a server implementation has no concept of break out characters, the canonical form is normally the reference name appended with the mailbox name. Note that if the server implements the namespace convention (Section 5.1.2.1), "#" is a break out character and must be treated as such.
If the reference argument is not a level of mailbox hierarchy (that is, it is a \NoInferiors name), and/or the reference argument does not end with the hierarchy delimiter, it is interpreted as implementation dependent. For example, a reference of "foo/bar" and mailbox name of "rag/baz" could be interpreted as "foo/bar/rag/baz", "foo/barrag/baz", or "foo/rag/baz". A client SHOULD NOT use such a reference argument except at the explicit request of the user ๐
โโ๏ธ A hierarchical browser MUST NOT make any assumptions about server interpretation of the reference unless the reference is a level of mailbox hierarchy AND ends with the hierarchy delimiter. Don't guess, bestie ๐
Any part of the reference argument that is included in the interpreted form SHOULD prefix the interpreted form. It SHOULD also be in the same form as the reference name argument. This rule lets the client figure out whether the returned mailbox name is in the context of the reference argument or if something about the mailbox argument overrode the reference argument ๐ Without this rule, the client would need to know the server's naming semantics, including which characters are "breakouts" that override a naming context. Nobody wants that homework ๐ญ
Here are some examples of how references and mailbox names might be interpreted on a UNIX-based server:
+==============+==============+===================+
| Reference | Mailbox Name | Interpretation |
+==============+==============+===================+
| ~smith/Mail/ | foo.* | ~smith/Mail/foo.* |
+--------------+--------------+-------------------+
| archive/ | % | archive/% |
+--------------+--------------+-------------------+
| #news. | comp.mail.* | #news.comp.mail.* |
+--------------+--------------+-------------------+
| ~smith/Mail/ | /usr/doc/foo | /usr/doc/foo |
+--------------+--------------+-------------------+
| archive/ | ~fred/Mail/* | ~fred/Mail/* |
+--------------+--------------+-------------------+
Table 1
The first three examples above show interpretations in the context of the reference argument. Note that "~smith/Mail" SHOULD NOT be transformed into something like "/u2/users/smith/Mail", or the client would have no way of telling that the interpretation happened in the context of the reference ๐ซฃ
The character * is a wildcard and matches zero or more characters at this position ๐ The character % is similar to *, but it does not match a hierarchy delimiter. If the % wildcard is the last character of a mailbox name argument, matching levels of hierarchy are also returned. If those levels of hierarchy are not also selectable mailboxes, they come back with the \Noselect mailbox name attribute (see the description of the LIST response (Section 7.3.1) for more details) โจ
Any syntactically valid pattern that a server does not accept for any reason MUST be silently ignored, meaning it results in no LIST responses, and the LIST command still returns a tagged OK response ๐คซ
Selection options tell the server to limit the mailbox names that the LIST operation selects ๐ If selection options are used, the mailboxes returned are the ones that match both the list of canonical LIST patterns and the selection options. Unless a particular selection option provides special rules, the selection options are cumulative: a mailbox that matches the mailbox patterns is selected only if it also matches all of the selection options. (An example of a selection option with special rules is the RECURSIVEMATCH option.) ๐ง
Return options control what information is returned for each matched mailbox ๐ Return options MUST NOT cause the server to report information about additional mailbox names other than those that match the canonical LIST patterns and selection options. If no return options are specified, the client is only expecting information about mailbox attributes. The server MAY return other information about the matched mailboxes, and clients MUST be able to handle that situation ๐
Initial selection options and return options are defined in the following subsections, and new ones will also be defined in extensions ๐ Initial options defined in this document MUST be supported. Each non-initial option will be enabled by a capability string (one capability may enable multiple options), and a client MUST NOT send an option for which the server has not advertised support ๐ซ A server MUST respond to options it does not recognize with a BAD response. The client SHOULD NOT specify any option more than once; however, if the client does this, the server MUST act as if it received the option only once. The order in which options are specified by the client is not significant ๐
In general, each selection option except RECURSIVEMATCH will have a corresponding return option with the same name. The REMOTE selection option is an anomaly in this regard and does not have a corresponding return option. That is because it expands, rather than restricts, the set of mailboxes that are returned. Future extensions to this specification should keep this parallelism in mind and define a pair of corresponding selection and return options ๐ฆ
Server implementations are permitted to "hide" otherwise accessible mailboxes from the wildcard characters, by preventing certain characters or names from matching a wildcard in certain situations ๐ For example, a UNIX-based server might restrict the interpretation of * so that an initial / character does not match.
The special name INBOX is included in the output from LIST โจ๐ if INBOX is supported by this server for this user and if the uppercase string "INBOX" matches the interpreted reference and mailbox name arguments with wildcards as described above. The criteria for omitting INBOX is whether SELECT INBOX will return a failure. It is not relevant whether the user's real INBOX lives on this server or some other one ๐
6.3.9.1. LIST Selection Options ๐
okay so these are the selection options this spec defines, bestie ๐ง
SUBSCRIBED ๐ธ makes LIST show your subscribed names instead of all the existing mailboxes. That list is often a smaller slice of the real mailboxes, and it can even include names of mailboxes that don't exist ๐ Either way, the list MUST include exactly the mailbox names that match the canonical list pattern and are subscribed to.
This option also defines a mailbox attribute, "\Subscribed", which says a mailbox name is subscribed to. The "\Subscribed" attribute MUST be supported and MUST be accurately computed whenever the SUBSCRIBED selection option is specified.
Note that the SUBSCRIBED selection option implies the SUBSCRIBED return option (see below) ๐
REMOTE ๐ฆ makes LIST show remote mailboxes as well as local ones, as described in [RFC2193]. It's meant to replace the RLIST command and, together with the SUBSCRIBED selection option, the RLSUB command. Servers that don't support remote mailboxes can ignore this option ๐ซถ
This option defines a mailbox attribute, "\Remote", which says that a mailbox is a remote mailbox. The "\Remote" attribute MUST be accurately computed when the REMOTE option is specified.
REMOTE has no interaction with the other options. Its whole job is to tell the server to apply the other options, if any, to remote mailboxes too, on top of local ones. In particular, it doesn't interact with RECURSIVEMATCH (see below). A request for (REMOTE RECURSIVEMATCH) is invalid, because a request for (RECURSIVEMATCH) is also invalid ๐ A request for (REMOTE RECURSIVEMATCH SUBSCRIBED) is asking for all subscribed mailboxes, both local and remote โจ
RECURSIVEMATCH ๐ forces the server to return info about parent mailboxes that don't match the other selection options but do have some submailboxes that do. Info about the children comes back in the CHILDINFO extended data item, as described in Section 6.3.9.6.
- Note 1: In order for a parent mailbox to be returned, it still has to match the canonical LIST pattern.
- Note 2: When returning the CHILDINFO extended data item, it doesn't matter whether or not the submailbox matches the canonical LIST pattern. See also Example 9 in Section 6.3.9.8.
The RECURSIVEMATCH option MUST NOT occur as the only selection option (or only together with REMOTE), because it only makes sense alongside other selection options. The server MUST return a BAD tagged response in that case ๐
Even if RECURSIVEMATCH is specified, the client MUST still be able to handle a CHILDINFO extended data item that shows up when no submailboxes meet the selection criteria of the follow-up LIST command. Why? They can get deleted or renamed after the LIST response was sent but before the client gets to them ๐ญ
6.3.9.2. LIST Return Options ๐
These are the return options defined in this spec, periodt ๐
SUBSCRIBED ๐ makes LIST return the subscription state for every matching mailbox name. The "\Subscribed" attribute MUST be supported and MUST be accurately computed when the SUBSCRIBED return option is specified. Also, all other mailbox attributes MUST be accurately computed. (This is different from the obsolete LSUB command from [RFC3501], just so you know ๐) The above requirements don't override the requirement for LIST to return results quickly (see Section 6.3.9). Basically, servers need to compute results quickly and accurately. Server implementors might need to set up quick access indices to pull that off โก
CHILDREN ๐งธ requests mailbox child information, as originally proposed in [RFC3348]. More on that in Section 6.3.9.5, below.
STATUS ๐ requests a STATUS response for each matching mailbox.
This option takes STATUS data items as parameters. For each selectable mailbox that matches the list pattern and selection options, the server MUST return an untagged LIST response followed by an untagged STATUS response with the info requested in the STATUS return option, except in some cases described below.
If an attempted STATUS for a listed mailbox fails because the mailbox can't be selected, the STATUS response MUST NOT be returned, and the LIST response MUST include the \NoSelect attribute. That happens, for example, when the "l" Access Control List (ACL) right [RFC4314] is granted on the mailbox but the "r" right isn't, or when a race condition between LIST and STATUS changes the mailbox to \NoSelect. This means the server may have to buffer the LIST reply until it has successfully looked up the STATUS info it needs ๐ง
If the server runs into unexpected problems while looking up the STATUS info, it MAY drop the corresponding STATUS reply. In that situation, the LIST command still returns a tagged OK reply ๐ซง
For info about getting status on the currently selected mailbox, check the note in the STATUS command discussion in Section 6.3.11 โจ
6.3.9.3. General Principles for Returning LIST Responses ๐ฆ
This section lays out a few principles that server implementations of this document can use to decide whether a LIST response should be returned, plus how many responses there should be and what kind of info they can contain. Think of it as the vibe check for LIST replies ๐
- At most, one LIST response should be returned for each mailbox name that matches the canonical LIST pattern. Server implementors must not assume that clients will be able to put together mailbox attributes and other info that comes back across multiple LIST responses.
- There are only two reasons to include a matching mailbox name in the responses to the LIST command. (The server is allowed to send unsolicited responses at any time, and those aren't governed by this rule ๐ธ)
- A. The mailbox name also satisfies the selection criteria.
- B. The mailbox name doesn't satisfy the selection criteria, but it has at least one descendant mailbox name that does satisfy them and that doesn't match the canonical LIST pattern.
For more on this case, see the CHILDINFO extended data item described in Section 6.3.9.6. The CHILDINFO extended data item can only be returned when the RECURSIVEMATCH selection option is specified.
- Attributes returned in the same LIST response are treated additively. For example, this response:
S: * LIST (\Subscribed \NonExistent) "/" "Fruit/Peach"
means that the "Fruit/Peach" mailbox doesn't exist, but it is subscribed ๐
6.3.9.4. Additional LIST-Related Requirements on Clients ๐
All clients MUST treat a LIST attribute with a stronger meaning as implying any attribute that can be inferred from it. (See Section 7.3.1 for the list of currently defined attributes.) For example, the client must treat the presence of the \NoInferiors attribute as if the \HasNoChildren attribute was also sent by the server. Inference, bestie ๐ง
The following table summarizes the inference rules ๐
+====================+===================+
| returned attribute | implied attribute |
+====================+===================+
| \NoInferiors | \HasNoChildren |
+--------------------+-------------------+
| \NonExistent | \NoSelect |
+--------------------+-------------------+
Table 2
6.3.9.5. The CHILDREN Return Option ๐ณ
The CHILDREN return option is basically the client saying, "tell me whether mailboxes have child mailboxes." A server MAY provide it even if the option isn't specified ๐คทโโ๏ธ
Lots of IMAP clients show the user a hierarchical view of the mailboxes they can access. Showing the whole hierarchy right away is often less ideal, especially with a big pile of mailboxes, so it's usually nicer to show a collapsed outline list that the user can expand as needed. It's common to add a visual clue (like a ''+'') in the collapsed hierarchy to show that a mailbox has children. When someone clicks that clue, the list expands to show the child mailboxes ๐ช The CHILDREN return option lets a client efficiently find out whether a mailbox has children, without sending a LIST "" * or a LIST "" % for each mailbox name. It defines two new attributes that MUST be returned within a LIST response: \HasChildren and \HasNoChildren. These attributes MAY be returned in response to any LIST command, but the CHILDREN return option is how the client says it really wants this info. If the CHILDREN return option is present, the server MUST return these attributes even if computing them is expensive ๐ธ
\HasChildren ๐ท means the mailbox has child mailboxes. A server SHOULD NOT set this attribute if there are child mailboxes but the user has no permission to access any of them. In that case, \HasNoChildren SHOULD be used. In many cases, though, a server may not be able to efficiently figure out whether the user has access to any child mailbox. Even though the \HasChildren attribute must be correct at the time the mailbox is processed, a client must be ready for a mailbox marked \HasChildren with no child mailbox showing up in the LIST response. This might happen, for example, if another client deletes the child mailboxes or makes them inaccessible to the user (using access control) before the server can list them ๐
\HasNoChildren ๐ซง means the mailbox has NO child mailboxes that are accessible to the currently authenticated user.
It is an error for the server to return both \HasChildren and \HasNoChildren in the same LIST response ๐ซ
Note: the \HasNoChildren attribute should not be confused with the \NoInferiors attribute. \NoInferiors means no child mailboxes exist now and none can be created in the future. Different vibe entirely ๐
6.3.9.6. CHILDINFO Extended Data Item โจ
Okay bestie, the CHILDINFO extended data item is a total gatekeeper ๐
It MUST NOT be returned unless the client has specified the RECURSIVEMATCH selection option ๐
When CHILDINFO shows up in a LIST response, it tells you which selection criteria got that mailbox returned, and that the mailbox has at least one descendant mailbox matching those criteria ๐ณ
Note: Some servers let mailboxes exist without their parent existing ๐ซฃ For example, "Customers/ABC" can exist while "Customers" does not. Since CHILDINFO isn't allowed when the RECURSIVEMATCH selection option isn't specified, those servers SHOULD use the "\NonExistent \HasChildren" attribute pair to let the client know there's a descendant mailbox that matches the selection criteria. See Example 11 in Section 6.3.9.8.
The returned selection criteria is how the client can tell a solicited response from an unsolicited one. It also helps sort out solicited responses caused by multiple pipelined LIST commands that specify different criteria ๐งฉ
Servers SHOULD only return a non-matching mailbox name along with CHILDINFO if at least one matching child is not also being returned. In other words, servers SHOULD suppress redundant CHILDINFO responses ๐
Examples 8 and 10 in Section 6.3.9.8 show the difference between CHILDINFO and the \HasChildren attribute ๐ฆ
The following table summarizes the interaction between the "\NonExistent" attribute and CHILDINFO. The first column tells you whether the parent mailbox exists ๐
+========+===========+====================+=====================+
| Exists | Meets the | Has a child that | Returned IMAP4rev2/ |
| | selection | meets the | LIST-EXTENDED |
| | criteria | selection criteria | attributes and |
| | | | CHILDINFO |
+========+===========+====================+=====================+
| no | no | no | no LIST response |
| | | | returned |
+--------+-----------+--------------------+---------------------+
| yes | no | no | no LIST response |
| | | | returned |
+--------+-----------+--------------------+---------------------+
| no | yes | no | (\NonExistent |
| | | | <attr>) |
+--------+-----------+--------------------+---------------------+
| yes | yes | no | (<attr>) |
+--------+-----------+--------------------+---------------------+
| no | no | yes | (\NonExistent) + |
| | | | CHILDINFO |
+--------+-----------+--------------------+---------------------+
| yes | no | yes | () + CHILDINFO |
+--------+-----------+--------------------+---------------------+
| no | yes | yes | (\NonExistent |
| | | | <attr>) + CHILDINFO |
+--------+-----------+--------------------+---------------------+
| yes | yes | yes | (<attr>) + |
| | | | CHILDINFO |
+--------+-----------+--------------------+---------------------+
Table 3
Here <attr> means one or more attributes that match the selection criteria. For example, for the SUBSCRIBED option, <attr> is \Subscribed ๐ธ
6.3.9.7. OLDNAME Extended Data Item ๐
The OLDNAME extended data item gets included when a mailbox name is created (with the CREATE command), renamed (with the RENAME command), or deleted (with the DELETE command). (When a mailbox is deleted, the "\NonExistent" attribute is included too.) IMAP extensions can specify other conditions for when OLDNAME should be included ๐ง
If the server allows denormalized mailbox names (see Section 5.1) in SELECT/EXAMINE, CREATE, RENAME, or DELETE, it SHOULD return an unsolicited LIST response that includes the OLDNAME extended data item, whenever the supplied mailbox name differs from the resulting normalized mailbox name. From the client's point of view, this is indistinguishable from another user renaming or deleting the mailbox, as specified in the previous paragraph ๐
A deleted mailbox can be announced like this:
S: * LIST (\NonExistent) "." "INBOX.DeletedMailbox"
Example of a renamed mailbox:
S: * LIST () "/" "NewMailbox" ("OLDNAME" ("OldMailbox"))
6.3.9.8. LIST Command Examples ๐
This example shows some uses of the basic LIST command:
Example:
C: A101 LIST "" ""
S: * LIST (\Noselect) "/" ""
S: A101 OK LIST Completed
C: A102 LIST #news.comp.mail.misc ""
S: * LIST (\Noselect) "." #news.
S: A102 OK LIST Completed
C: A103 LIST /usr/staff/jones ""
S: * LIST (\Noselect) "/" /
S: A103 OK LIST Completed
C: A202 LIST ~/Mail/ %
S: * LIST (\Noselect) "/" ~/Mail/foo
S: * LIST () "/" ~/Mail/meetings
S: A202 OK LIST completed
Extended examples:
1: This first one shows the complete local hierarchy that the other examples will use. Let's set the scene ๐
C: A01 LIST "" "*"
S: * LIST (\Marked \NoInferiors) "/" "inbox"
S: * LIST () "/" "Fruit"
S: * LIST () "/" "Fruit/Apple"
S: * LIST () "/" "Fruit/Banana"
S: * LIST () "/" "Tofu"
S: * LIST () "/" "Vegetable"
S: * LIST () "/" "Vegetable/Broccoli"
S: * LIST () "/" "Vegetable/Corn"
S: A01 OK done
2: Next up, we look at the subscribed mailboxes. This is similar to, but not equivalent with, the now deprecated <LSUB "" "*"> (see [RFC3501] for more details on the LSUB command). Notice that the mailbox called "Fruit/Peach" is subscribed to, but it doesn't actually exist (maybe it was deleted while still subscribed ๐
). The "Fruit" mailbox isn't subscribed to, but it has two subscribed children. The "Vegetable" mailbox is subscribed and has two children, and one of them is subscribed as well ๐ฅฆ
C: A02 LIST (SUBSCRIBED) "" "*"
S: * LIST (\Marked \NoInferiors \Subscribed) "/" "inbox"
S: * LIST (\Subscribed) "/" "Fruit/Banana"
S: * LIST (\Subscribed \NonExistent) "/" "Fruit/Peach"
S: * LIST (\Subscribed) "/" "Vegetable"
S: * LIST (\Subscribed) "/" "Vegetable/Broccoli"
S: A02 OK done
3: This one shows the CHILDREN option in action โจ Without having to list the second level of the hierarchy, the client now knows which top-level mailboxes have submailboxes (children) and which don't. Also note that the server doesn't need to return the \HasNoChildren attribute for the inbox, because the \NoInferiors attribute already implies that and has a stronger meaning ๐
C: A03 LIST () "" "%" RETURN (CHILDREN)
S: * LIST (\Marked \NoInferiors) "/" "inbox"
S: * LIST (\HasChildren) "/" "Fruit"
S: * LIST (\HasNoChildren) "/" "Tofu"
S: * LIST (\HasChildren) "/" "Vegetable"
S: A03 OK done
4: Here we see more mailboxes that live on another server ๐ This is similar to the command <RLIST "" "%">.
C: A04 LIST (REMOTE) "" "%" RETURN (CHILDREN)
S: * LIST (\Marked \NoInferiors) "/" "inbox"
S: * LIST (\HasChildren) "/" "Fruit"
S: * LIST (\HasNoChildren) "/" "Tofu"
S: * LIST (\HasChildren) "/" "Vegetable"
S: * LIST (\Remote \HasNoChildren) "/" "Bread"
S: * LIST (\HasChildren \Remote) "/" "Meat"
S: A04 OK done
5: This next example also asks the server to include mailboxes on another server. The server returns info about all the subscribed mailboxes. It's similar to the command <RLSUB "" "*"> (see [RFC2193] for more details on RLSUB). We also get to see two selection options working together ๐ซถ
C: A05 LIST (REMOTE SUBSCRIBED) "" "*"
S: * LIST (\Marked \NoInferiors \Subscribed) "/" "inbox"
S: * LIST (\Subscribed) "/" "Fruit/Banana"
S: * LIST (\Subscribed \NonExistent) "/" "Fruit/Peach"
S: * LIST (\Subscribed) "/" "Vegetable"
S: * LIST (\Subscribed) "/" "Vegetable/Broccoli"
S: * LIST (\Remote \Subscribed) "/" "Bread"
S: A05 OK done
6: This one asks the server to include mailboxes on another server too ๐ This time, the server is asked to return subscription information for all the returned mailboxes, which is different from the example above.
Notice that the output of this command is not a superset of the output in the previous example, because it doesn't include a LIST response for the non-existent "Fruit/Peach" ๐
C: A06 LIST (REMOTE) "" "*" RETURN (SUBSCRIBED)
S: * LIST (\Marked \NoInferiors \Subscribed) "/" "inbox"
S: * LIST () "/" "Fruit"
S: * LIST () "/" "Fruit/Apple"
S: * LIST (\Subscribed) "/" "Fruit/Banana"
S: * LIST () "/" "Tofu"
S: * LIST (\Subscribed) "/" "Vegetable"
S: * LIST (\Subscribed) "/" "Vegetable/Broccoli"
S: * LIST () "/" "Vegetable/Corn"
S: * LIST (\Remote \Subscribed) "/" "Bread"
S: * LIST (\Remote) "/" "Meat"
S: A06 OK done
7: This one shows the difference between the \HasChildren attribute and the CHILDINFO extended data item ๐ง Let's assume there's the following hierarchy:
C: C01 LIST "" "*"
S: * LIST (\Marked \NoInferiors) "/" "inbox"
S: * LIST () "/" "Foo"
S: * LIST () "/" "Foo/Bar"
S: * LIST () "/" "Foo/Baz"
S: * LIST () "/" "Moo"
S: C01 OK done
If the client asks for RETURN (CHILDREN), it gets this:
C: CA3 LIST "" "%" RETURN (CHILDREN)
S: * LIST (\Marked \NoInferiors) "/" "inbox"
S: * LIST (\HasChildren) "/" "Foo"
S: * LIST (\HasNoChildren) "/" "Moo"
S: CA3 OK done
A) Let's also assume that the mailbox "Foo/Baz" is the only subscribed mailbox. Then we get this result:
C: C02 LIST (SUBSCRIBED) "" "*"
S: * LIST (\Subscribed) "/" "Foo/Baz"
S: C02 OK done
Now, if the client issues <LIST (SUBSCRIBED) "" "%">, the server returns no mailboxes, because the mailboxes "Moo", "Foo", and "Inbox" are NOT subscribed. However, if the client issues this:
C: C04 LIST (SUBSCRIBED RECURSIVEMATCH) "" "%"
S: * LIST () "/" "Foo" ("CHILDINFO" ("SUBSCRIBED"))
S: C04 OK done
(That is, the mailbox "Foo" isn't subscribed, but it has a child that is.) Then A1 or A2 happens ๐ญ
A1) If the mailbox "Foo" had also been subscribed, the last command would return this:
C: C04 LIST (SUBSCRIBED RECURSIVEMATCH) "" "%"
S: * LIST (\Subscribed) "/" "Foo" ("CHILDINFO"
("SUBSCRIBED"))
S: C04 OK done
or even this:
C: C04 LIST (SUBSCRIBED RECURSIVEMATCH) "" "%"
S: * LIST (\Subscribed \HasChildren) "/" "Foo"
("CHILDINFO" ("SUBSCRIBED"))
S: C04 OK done
Okay so A2 is the twist ๐, where "Foo" isn't in the original hierarchy and isn't subscribed. Then the last command gives this ๐
C: C04 LIST (SUBSCRIBED RECURSIVEMATCH) "" "%"
S: * LIST (\NonExistent) "/" "Foo" ("CHILDINFO"
("SUBSCRIBED"))
S: C04 OK done
B) Now let's assume no mailbox is subscribed ๐. Then LIST (SUBSCRIBED RECURSIVEMATCH) "" "%" returns zero responses, because there are no subscribed children, even though "Foo" still has children. Iconic emptiness ๐ซฅ
(no responses)
C) And finally, suppose only "Foo" and "Moo" are subscribed โจ. Now we get this:
C: C04 LIST (SUBSCRIBED RECURSIVEMATCH) "" "%" RETURN
(CHILDREN)
S: * LIST (\HasChildren \Subscribed) "/" "Foo"
S: * LIST (\HasNoChildren \Subscribed) "/" "Moo"
S: C04 OK done
That tells us "Foo" has children, but none of them is subscribed ๐ฅน
8: Okay, this one shows that CHILDINFO comes back whether or not child mailboxes match the canonical LIST pattern ๐ฆ. Let's say we have this hierarchy:
C: D01 LIST "" "*"
S: * LIST (\Marked \NoInferiors) "/" "inbox"
S: * LIST () "/" "foo2"
S: * LIST () "/" "foo2/bar1"
S: * LIST () "/" "foo2/bar2"
S: * LIST () "/" "baz2"
S: * LIST () "/" "baz2/bar2"
S: * LIST () "/" "baz2/bar22"
S: * LIST () "/" "baz2/bar222"
S: * LIST () "/" "eps2"
S: * LIST () "/" "eps2/mamba"
S: * LIST () "/" "qux2/bar2"
S: D01 OK done
And these mailboxes are subscribed ๐:
C: D02 LIST (SUBSCRIBED) "" "*"
S: * LIST (\Subscribed) "/" "foo2/bar1"
S: * LIST (\Subscribed) "/" "foo2/bar2"
S: * LIST (\Subscribed) "/" "baz2/bar2"
S: * LIST (\Subscribed) "/" "baz2/bar22"
S: * LIST (\Subscribed) "/" "baz2/bar222"
S: * LIST (\Subscribed) "/" "eps2"
S: * LIST (\Subscribed) "/" "eps2/mamba"
S: * LIST (\Subscribed) "/" "qux2/bar2"
S: D02 OK done
The client starts with this command ๐:
C: D03 LIST (RECURSIVEMATCH SUBSCRIBED) "" "*2"
S: * LIST () "/" "foo2" ("CHILDINFO" ("SUBSCRIBED"))
S: * LIST (\Subscribed) "/" "foo2/bar2"
S: * LIST (\Subscribed) "/" "baz2/bar2"
S: * LIST (\Subscribed) "/" "baz2/bar22"
S: * LIST (\Subscribed) "/" "baz2/bar222"
S: * LIST (\Subscribed) "/" "eps2" ("CHILDINFO" ("SUBSCRIBED"))
S: * LIST (\Subscribed) "/" "qux2/bar2"
S: D03 OK done
The server is also allowed to include these two, but this would break a restriction in Section 6.3.9.6, because CHILDINFO is redundant here ๐ โโ๏ธ
S: * LIST () "/" "baz2" ("CHILDINFO" ("SUBSCRIBED"))
S: * LIST (\NonExistent) "/" "qux2" ("CHILDINFO" ("SUBSCRIBED"))
So CHILDINFO shows up for "foo2", "baz2", and "eps2" because each one has subscribed children ๐. But the details are different. For "foo2", only one of its two subscribed children matches the pattern. For "baz2", all of the subscribed children match. For "eps2", none of the subscribed children match ๐ญ
Now watch this. If the client sends this instead ๐ง:
C: D03 LIST (RECURSIVEMATCH SUBSCRIBED) "" "*"
S: * LIST () "/" "foo2" ("CHILDINFO" ("SUBSCRIBED"))
S: * LIST (\Subscribed) "/" "foo2/bar1"
S: * LIST (\Subscribed) "/" "foo2/bar2"
S: * LIST () "/" "baz2" ("CHILDINFO" ("SUBSCRIBED"))
S: * LIST (\Subscribed) "/" "baz2/bar2"
S: * LIST (\Subscribed) "/" "baz2/bar22"
S: * LIST (\Subscribed) "/" "baz2/bar222"
S: * LIST (\Subscribed) "/" "eps2" ("CHILDINFO" ("SUBSCRIBED"))
S: * LIST (\Subscribed) "/" "eps2/mamba"
S: * LIST (\Subscribed) "/" "qux2/bar2"
S: D03 OK done
then the LIST responses for "foo2", "baz2", and "eps2" still carry CHILDINFO ๐. That info is redundant, since the client can work it out on its own ๐คทโโ๏ธ
9: This one is a flex ๐ with extended syntax for the mailbox pattern. It also proves that having CHILDINFO doesn't automatically mean \HasChildren โจ
C: a1 LIST "" ("foo")
S: * LIST () "/" foo
S: a1 OK done
C: a2 LIST (SUBSCRIBED) "" "foo/*"
S: * LIST (\Subscribed \NonExistent) "/" foo/bar
S: a2 OK done
C: a3 LIST (SUBSCRIBED RECURSIVEMATCH) "" foo RETURN (CHILDREN)
S: * LIST (\HasNoChildren) "/" foo ("CHILDINFO" ("SUBSCRIBED"))
S: a3 OK done
10: Here a server that supports missing mailbox hierarchy elements tells a client that didn't pick the RECURSIVEMATCH selection option that a child mailbox matches the selection criteria ๐
C: a1 LIST (REMOTE) "" *
S: * LIST () "/" music/rock
S: * LIST (\Remote) "/" also/jazz
S: a1 OK done
C: a2 LIST () "" %
S: * LIST (\NonExistent \HasChildren) "/" music
S: a2 OK done
C: a3 LIST (REMOTE) "" %
S: * LIST (\NonExistent \HasChildren) "/" music
S: * LIST (\NonExistent \HasChildren) "/" also
S: a3 OK done
C: a3.1 LIST "" (% music/rock)
S: * LIST () "/" music/rock
S: a3.1 OK done
Since "music/rock" is the only mailbox under "music", the server doesn't need to also return "music" ๐ But clients must handle both cases, so be ready for either one ๐
11: These examples show the STATUS return option in action ๐
C: A01 LIST "" % RETURN (STATUS (MESSAGES UNSEEN))
S: * LIST () "." "INBOX"
S: * STATUS "INBOX" (MESSAGES 17 UNSEEN 16)
S: * LIST () "." "foo"
S: * STATUS "foo" (MESSAGES 30 UNSEEN 29)
S: * LIST (\NoSelect) "." "bar"
S: A01 OK List completed.
"bar" isn't selectable, so it gets no STATUS reply ๐ โโ๏ธ
C: A02 LIST (SUBSCRIBED RECURSIVEMATCH) "" % RETURN (STATUS
(MESSAGES))
S: * LIST (\Subscribed) "." "INBOX"
S: * STATUS "INBOX" (MESSAGES 17)
S: * LIST () "." "foo" (CHILDINFO ("SUBSCRIBED"))
S: A02 OK List completed.
"foo" still gets a LIST reply because it has matching children ๐ซถ, but there's no STATUS reply for it, since "foo" itself doesn't match the selection criteria ๐
6.3.10. NAMESPACE Command โจ
Arguments: none
Responses: REQUIRED untagged responses: NAMESPACE
Result: OK - command completed
NO - Can't complete the command
BAD - arguments invalid
okay bestie, NAMESPACE is the "so, what's my mailbox neighbourhood look like?" command ๐๏ธ๐
It makes the server send back exactly one untagged NAMESPACE response ๐ That response lists the prefix and hierarchy delimiter for the server's Personal Namespace(s), Other Users' Namespace(s), and Shared Namespace(s) it's willing to show off ๐ฆ If a namespace class isn't available, you get a NIL in its spot, no drama ๐ The namespace-response-extensions ABNF non-terminal exists for future expansion, and it MAY be included in the NAMESPACE response โจ
Example 1:
In this one, the server has a single Personal Namespace. There's no leading prefix on personal mailboxes, and "/" is the hierarchy delimiter ๐ธ
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) NIL NIL
S: A001 OK NAMESPACE command completed
Example 2:
A user logged on anonymously ๐ No personal mailboxes are tied to the anonymous user, and they don't have access to the Other Users' Namespace. Shared mailboxes need no prefix, and the hierarchy delimiter is "." ๐
C: A001 NAMESPACE
S: * NAMESPACE NIL NIL (("" "."))
S: A001 OK NAMESPACE command completed
Example 3:
A server with a Personal Namespace and one Shared Namespace ๐ง
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) NIL (("Public Folders/" "/"))
S: A001 OK NAMESPACE command completed
Example 4:
Now we're getting fancy: a Personal Namespace, an Other Users' Namespace, and multiple Shared Namespaces ๐ Notice that each namespace can use a different hierarchy delimiter. Iconic behaviour ๐ฅ
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) (("~" "/")) (("#shared/" "/")
("#public/" "/")("#ftp/" "/")("#news." "."))
S: A001 OK NAMESPACE command completed
The prefix string is what lets a client do cool stuff, like automatically making personal mailboxes or LISTing every available mailbox inside a namespace ๐
Example 5:
A server that only offers the Personal Namespace, with a leading prefix of INBOX on personal mailboxes and a hierarchy delimiter of "." ๐ฆ
C: A001 NAMESPACE
S: * NAMESPACE (("INBOX." ".")) NIL NIL
S: A001 OK NAMESPACE command completed
Then the client automatically creates a mailbox to store sent items ๐
C: A002 CREATE "INBOX.Sent Mail"
S: A002 OK CREATE command completed
Okay, real talk: a server will usually only support one Personal Namespace and one Other User's Namespace, but there are situations where there MAY be multiples of these, and a client MUST be prepared for them ๐ญ If a client is configured to create a certain mailbox, it can get confusing about which Personal Namespace to put it in. In that case, a client SHOULD let the user pick which namespaces to create the mailbox in, or it can just use the first Personal Namespace ๐ซถ
Example 6:
Here the server has two Personal Namespaces. Besides the regular one, the user also has an extra Personal Namespace that gives access to mailboxes in an MH format mailstore ๐
The client is set up to save a copy of everything the user sends into a mailbox with the \Sent attribute (see Section 7.3.1) ๐จ Also, whenever a message is deleted from a mailbox, the client moves it to a mailbox with the \Trash attribute ๐๏ธ The server uses the \NonExistent mailbox attribute to say "these don't exist yet, but you can make them." Once they're created, they can be used for \Sent or \Trash, and the server stops including \NonExistent for them ๐
Heads up: this example shows how extension parameters can be passed along to describe the #mh namespace. Look at the made-up "X-PARAM" extension parameter ๐ง
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")("#mh/" "/" "X-PARAM"
("FLAG1" "FLAG2"))) NIL NIL
S: A001 OK NAMESPACE command completed
C: A002 LIST (SPECIAL-USE) "" "*"
S: * LIST (\NonExistent \Archive) "/" Archives
S: * LIST (\NonExistent \Drafts) "/" Drafts
S: * LIST (\NonExistent \Junk) "/" Junk
S: * LIST (\NonExistent \Sent) "/" "Sent Mail"
S: * LIST (\NonExistent \Trash) "/" "Deleted Items"
S: A002 OK LIST Completed
C: A003 LIST (SPECIAL-USE) "#mh/" "*"
S: * LIST (\NonExistent \Archive) "/" "#mh/Archives"
S: * LIST (\NonExistent \Drafts) "/" "#mh/Drafts"
S: * LIST (\NonExistent \Junk) "/" "#mh/Junk"
S: * LIST (\NonExistent \Sent) "/" "#mh/Sent Mail"
S: * LIST (\NonExistent \Trash) "/" "#mh/Deleted Items"
S: A003 OK LIST Completed
The user wants to keep just one copy of sent mail, but it's unclear which Personal Namespace the client should use to create the 'Sent Mail' mailbox ๐ค So the user gets prompted to pick a namespace, and only one 'Sent Mail' mailbox gets created โจ
C: A004 CREATE "Sent Mail"
S: A004 OK CREATE command completed
The client is designed to keep two 'Deleted Items' mailboxes, one for each namespace ๐ง
C: A005 CREATE "Delete Items"
S: A005 OK CREATE command completed
C: A006 CREATE "#mh/Deleted Items"
S: A006 OK CREATE command completed
The next level of hierarchy after the Other Users' Namespace prefix SHOULD consist of <username>, where <username> is a user name as per the LOGIN or AUTHENTICATE command ๐ค
A client can build a LIST command by adding a "%" onto the Other Users' Namespace prefix. That lets it discover the Personal Namespaces of other users that the currently authenticated user is allowed to see ๐
When the server answers a LIST command like that, it SHOULD NOT return user names that haven't granted the user in question access to their personal mailboxes. Privacy first, bestie ๐
A server MAY return a LIST response containing only the names of users who have explicitly granted access to the user in question โจ
Or, a server MAY return NO to such a LIST command. In that case, the user name has to be included with the Other Users' Namespace prefix before any other user's mailboxes can be listed ๐ โโ๏ธ
Example 7:
A server that gives you a list of other users' mailboxes that the logged-on user can access ๐
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) (("Other Users/" "/")) NIL
S: A001 OK NAMESPACE command completed
C: A002 LIST "" "Other Users/%"
S: * LIST () "/" "Other Users/Mike"
S: * LIST () "/" "Other Users/Karen"
S: * LIST () "/" "Other Users/Matthew"
S: * LIST () "/" "Other Users/Tesa"
S: A002 OK LIST command completed
Example 8:
A server that does NOT give you a list of other users' accessible mailboxes ๐ The mailboxes can only be listed if the client includes the other user's name after the Other Users' Namespace prefix.
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) (("#Users/" "/")) NIL
S: A001 OK NAMESPACE command completed
Here, the logged-on user can access Mike's Personal Namespace, but the server chose to hide that info from the LIST response. Still, by adding the user name Mike (taken from user input) to the Other Users' Namespace prefix, the client can get a listing of Mike's personal mailboxes ๐
C: A002 LIST "" "#Users/%"
S: A002 NO The requested item could not be found.
C: A003 LIST "" "#Users/Mike/%"
S: * LIST () "/" "#Users/Mike/INBOX"
S: * LIST () "/" "#Users/Mike/Foo"
S: A003 OK LIST command completed.
A prefix string doesn't always have to include a hierarchy delimiter, since in some cases it isn't needed as part of the prefix ๐ฐ
Example 9:
A server that reaches the Other Users' Namespace by putting a '~' followed by <username> in front of others' mailboxes, where <username> is a user name as per the LOGIN or AUTHENTICATE command ๐ฆ
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) (("~" "/")) NIL
S: A001 OK NAMESPACE command completed
Listing the mailboxes for user mark ๐
C: A002 LIST "" "~mark/%"
S: * LIST () "/" "~mark/INBOX"
S: * LIST () "/" "~mark/foo"
S: A002 OK LIST command completed
6.3.11. STATUS Command โจ
Arguments: mailbox name
status data item names
Responses: REQUIRED untagged responses: STATUS
Result: OK - status completed
NO - status failure: no status for that name
BAD - command unknown or arguments invalid
The STATUS command asks for the status of a specific mailbox ๐ฌ It doesn't change the currently selected mailbox, and it doesn't touch the state of any messages in the mailbox being checked ๐งโโ๏ธ
STATUS is basically the shortcut for opening a second IMAP4rev2 connection and running EXAMINE on a mailbox just to peek at its status, while keeping your current mailbox selected in the first connection ๐ซถ
Unlike LIST, STATUS is NOT guaranteed to respond fast ๐ In some cases it can be really slow. Some implementations have the server internally open the mailbox as "read-only" to get certain status info. Also, unlike LIST, STATUS doesn't accept wildcards ๐ โโ๏ธ
Note: STATUS is meant for checking mailboxes other than the one currently selected. Because STATUS can cause the mailbox to be opened internally, and because that info is already available another way on the selected mailbox, the STATUS command SHOULD NOT be used on the currently selected mailbox. Still, servers MUST be able to run STATUS on the selected mailbox. (That might also happen implicitly when the STATUS return option is used in a LIST command.) The STATUS command MUST NOT be used as a "check for new messages in the selected mailbox" operation. (For the proper way to check for new messages, see Sections 7 and 7.4.1.) STATUS SIZE can take a significant amount of time, depending on the server implementation. Clients should use STATUS SIZE cautiously. ๐ฅบ
The status data items you can currently request are:
MESSAGES: the number of messages in the mailbox ๐ฎUIDNEXT: the next unique identifier value of the mailbox. Refer to Section 2.3.1.1 for more information ๐ขUIDVALIDITY: the unique identifier validity value of the mailbox. Refer to Section 2.3.1.1 for more information ๐ชชUNSEEN: the number of messages that do not have the \Seen flag set ๐๏ธDELETED: the number of messages that have the \Deleted flag set ๐๏ธSIZE: the total size of the mailbox in octets. This isn't strictly required to be an exact value, but it MUST be equal to or greater than the sum of the values of the RFC822.SIZE FETCH message data items (see Section 6.4.5) of all messages in the mailbox ๐
Example:
C: A042 STATUS blurdybloop (UIDNEXT MESSAGES)
S: * STATUS blurdybloop (MESSAGES 231 UIDNEXT 44292)
S: A042 OK STATUS completed
6.3.12. APPEND Command โจ
Arguments: mailbox name
OPTIONAL flag parenthesized list
OPTIONAL date/time string
message literal
Responses: OPTIONAL untagged response: LIST
Result: OK - append completed
NO - append error: can't append to that mailbox, error
in flags or date/time or message text
BAD - command unknown or arguments invalid
okay so APPEND is how you drop a brand-new message into the END of a mailbox ๐ฌ๐ You hand it the literal message as the argument, and it gets tacked on like a fresh text at the bottom of the chat. The message SHOULD look like an [RFC5322] or [I18N-HDRS] message ๐ฆ 8-bit characters are totally allowed in there, no cap. BUT if your server can't handle 8-bit data properly, it MUST be able to reversibly convert that 8-bit APPEND data down to 7 bits using a [MIME-IMB] content transfer encoding. Like, it has to be able to undo it perfectly ๐ซถ
Note: There may be exceptions, such as draft messages, in which required [RFC5322] header fields are omitted in the message literal argument to APPEND. The full implications of doing so must be understood and carefully weighed. ๐
If you include a flag parenthesized list, those flags SHOULD get set on the new message ๐ If you don't, the flag list defaults to "empty" ๐ธ
If you give a date-time, the internal date SHOULD be set to it โฐ If you don't, it defaults to the current date and time, which is honestly iconic for a default โจ
Now the big-deal part: if the append fails for ANY reason, the mailbox MUST be restored to how it was before the APPEND attempt ๐ญ The only thing allowed to change is possibly the UIDNEXT value. No partial appending, bestie. It's all or nothing ๐
If the destination mailbox doesn't exist, the server MUST return an error, and it MUST NOT automatically create the mailbox ๐ โโ๏ธ Unless it's certain the mailbox can't be created, the server MUST send the response code "[TRYCREATE]" as the prefix of the text of the tagged NO response ๐ง That's basically a hint saying "hey, you could try a CREATE and then retry the APPEND if that works!" ๐
When the APPEND goes through, the server returns an APPENDUID response code (see Section 7.1), unless otherwise specified below. โจ
Here's a sneaky one ๐ If a mailbox lets the client APPEND to it but NOT SELECT or EXAMINE it, the server MUST NOT send an APPENDUID response code, because that would disclose information about the mailbox. Privacy is a whole vibe ๐
And if a mailbox has UIDNOTSTICKY status (see Section 7.1), the server MAY omit the APPENDUID response code, since it isn't meaningful there anyway ๐
If the mailbox is currently selected, normal new message actions SHOULD happen ๐ฅ Specifically, the server SHOULD tell the client right away with an untagged EXISTS response. If it doesn't, the client MAY issue a NOOP command after one or more APPEND commands ๐
If the server decides to convert (normalize) the mailbox name, it SHOULD return an untagged LIST with an OLDNAME extended data item. The OLDNAME value is the mailbox name you supplied, and the name parameter is the normalized one. (See Section 6.3.9.7 for more details.) ๐ฆ
Example:
C: A003 APPEND saved-messages (\Seen) {326}
S: + Ready for literal data
C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
C: From: Fred Foobar <foobar@Blurdybloop.example>
C: Subject: afternoon meeting
C: To: mooch@owatagu.siam.edu.example
C: Message-Id: <B27397-0100000@Blurdybloop.example>
C: MIME-Version: 1.0
C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
C:
C: Hello Joe, do you think we can meet at 3:30 tomorrow?
C:
S: A003 OK APPEND completed
Example:
C: A003 APPEND saved-messages (\Seen) {297+}
C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
C: From: Fred Foobar <foobar@example.com>
C: Subject: afternoon meeting
C: To: mooch@example.com
C: Message-Id: <B27397-0100000@example.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 38505 3955] APPEND completed
C: A004 COPY 2:4 meeting
S: A004 OK [COPYUID 38505 304,319:320 3956:3958] Done
C: A005 UID COPY 305:310 meeting
S: A005 OK No matching messages, so nothing copied
C: A006 COPY 2 funny
S: A006 OK Done
C: A007 SELECT funny
S: * 1 EXISTS
S: * OK [UIDVALIDITY 3857529045] Validity session-only
S: * OK [UIDNEXT 2] Predicted next UID
S: * NO [UIDNOTSTICKY] Non-persistent UIDs
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S: * OK [PERMANENTFLAGS (\Deleted \Seen)] Limited
S: * LIST () "." funny
S: A007 OK [READ-WRITE] SELECT completed
In this example, A003 and A004 show a successful append and copy to a mailbox that hands back the UIDs assigned to the messages ๐ A005 is the "nothing copied" one ๐ Back in A003, message 2 had UID 304 and message 3 had UID 319, so UIDs 305 through 310 don't exist (check Section 2.3.1.1 for the deets). A006 copies a message and gets no COPYUID back, and as expected, A007 reveals that the mail store behind that mailbox doesn't support persistent UIDs ๐ฅบ
Note: The APPEND command is not used for message delivery, because it does not provide a mechanism to transfer [SMTP] envelope information. ๐ฎ
6.3.13. IDLE Command ๐ฆ
Arguments: none
Responses: continuation data will be requested; the client sends
the continuation data "DONE" to end the command
Result: OK - IDLE completed after client sent "DONE"
NO - failure: the server will not allow the IDLE
command at this time
BAD - command unknown or arguments invalid
So without IDLE, a client has to keep poll-poll-polling the server for changes to the selected mailbox (new mail, deletions, flag changes) ๐ฉ Way more desirable is the server just pushing updates in real time, so you see new mail the instant it lands โก That's exactly what IDLE does: it's the client saying "hey, I'm ready for live updates" ๐ธ
The client sends IDLE when it's ready to accept unsolicited updates. The server asks for a response to IDLE with the continuation ("+") response. IDLE stays active until the client answers that continuation, and while IDLE is active, the server is free to send untagged EXISTS, EXPUNGE, FETCH, and other responses at any time ๐ฅ If the server chooses to send unsolicited FETCH responses, they MUST include a UID FETCH item ๐ซถ
IDLE ends when the server gets a "DONE" continuation from the client, which satisfies the server's continuation request ๐ At that point, the server MAY send any remaining queued untagged responses, and then it MUST immediately send the tagged response to the IDLE command and get ready for other commands ๐ Like with any other command, processing a new command may trigger unsolicited untagged responses, subject to the ambiguity limitations. And the client MUST NOT send a command while the server is waiting for DONE, because the server wouldn't be able to tell a command apart from a continuation ๐
Also, the server MAY consider a client inactive if it has an IDLE command running. If that server has an inactivity timeout, it MAY log the client off implicitly once the timeout period ends ๐ So clients using IDLE are advised to end IDLE and reissue it at least every 29 minutes to avoid getting logged off โฐ The good news: you still get instant mailbox updates, even though you only need to "poll" every half hour ๐
Example:
C: A001 SELECT INBOX
S: * FLAGS (\Deleted \Seen \Flagged)
S: * OK [PERMANENTFLAGS (\Deleted \Seen \Flagged)] Limited
S: * 3 EXISTS
S: * OK [UIDVALIDITY 1]
S: * OK [UIDNEXT 1]
S: * LIST () "/" INBOX
S: A001 OK [READ-WRITE] SELECT completed
C: A002 IDLE
S: + idling
...time passes; new mail arrives...
S: * 4 EXISTS
C: DONE
S: A002 OK IDLE terminated
...another client expunges message 2 now...
C: A003 FETCH 4 ALL
S: * 4 FETCH (...)
S: A003 OK FETCH completed
C: A004 IDLE
S: * 2 EXPUNGE
S: * 3 EXISTS
S: + idling
...time passes; another client expunges message 3...
S: * 3 EXPUNGE
S: * 2 EXISTS
...time passes; new mail arrives...
S: * 3 EXISTS
C: DONE
S: A004 OK IDLE terminated
C: A005 FETCH 3 ALL
S: * 3 FETCH (...)
S: A005 OK FETCH completed
C: A006 IDLE
6.4. Client Commands - Selected State ๐
In the selected state, commands that manipulate messages in a mailbox are permitted ๐โจ
On top of the universal commands (CAPABILITY, NOOP, and LOGOUT) and the authenticated state commands (SELECT, EXAMINE, NAMESPACE, CREATE, DELETE, RENAME, SUBSCRIBE, UNSUBSCRIBE, LIST, STATUS, and APPEND), the following commands are valid in the selected state: CLOSE, UNSELECT, EXPUNGE, SEARCH, FETCH, STORE, COPY, MOVE, and UID ๐
6.4.1. CLOSE Command ๐ช
Arguments: none
Responses: no specific responses for this command
Result: OK - close completed, now in authenticated state
BAD - command unknown or arguments invalid
CLOSE permanently removes all messages with the \Deleted flag set from the currently selected mailbox, and it takes you back from the selected state to the authenticated state ๐ฅ No untagged EXPUNGE responses get sent along the way ๐
No messages are removed and no error is given if the mailbox was selected by EXAMINE or is otherwise read-only, so it's chill ๐ธ
Even with a mailbox selected, you MAY issue a SELECT, EXAMINE, or LOGOUT command without CLOSE-ing first ๐ฆ Those three implicitly close the current mailbox without doing an expunge. BUT when you've deleted a ton of messages, CLOSE-LOGOUT or CLOSE-SELECT is way faster than EXPUNGE-LOGOUT or EXPUNGE-SELECT, because it skips sending the untagged EXPUNGE responses (which the client would probably just ignore anyway) ๐๏ธ๐จ
Example:
C: A341 CLOSE
S: A341 OK CLOSE completed
6.4.2. UNSELECT Command ๐ซง
Arguments: none
Responses: no specific responses for this command
Result: OK - unselect completed, now in authenticated state
BAD - no mailbox selected, or argument supplied but
none permitted
UNSELECT frees up the session's resources tied to the selected mailbox and sends the server back to the authenticated state ๐งน It does the exact same stuff as CLOSE, except that NO messages get permanently removed from the mailbox. Gentle exit, no drama ๐ท
Example:
C: A342 UNSELECT
S: A342 OK Unselect completed
6.4.3. EXPUNGE Command ๐งนโจ
Arguments: none
Responses: untagged responses: EXPUNGE
Result: OK - expunge completed
NO - expunge failure: can't expunge (e.g., permission
denied)
BAD - command unknown or arguments invalid
Okay bestie, EXPUNGE is the big delete button ๐. It permanently removes every message in the currently selected mailbox that has the \Deleted flag set. Before the server says OK, it sends an untagged EXPUNGE response for each message it removes, so you always know exactly what got yeeted ๐๏ธ.
Example:
C: A202 EXPUNGE
S: * 3 EXPUNGE
S: * 3 EXPUNGE
S: * 5 EXPUNGE
S: * 8 EXPUNGE
S: A202 OK EXPUNGE completed
Note: In this example, messages 3, 4, 7, and 11 had the \Deleted flag set. See the description of the EXPUNGE response (Section 7.5.1) for further explanation. ๐
6.4.4. SEARCH Command ๐๐
Arguments: OPTIONAL result specifier
OPTIONAL [CHARSET] specification
searching criteria (one or more)
Responses: OPTIONAL untagged response: ESEARCH
Result: OK - search completed
NO - search error: can't search that [CHARSET] or
criteria
BAD - command unknown or arguments invalid
SEARCH is how you dig through a mailbox for the messages that match your vibe, aka your searching criteria ๐โจ.
The SEARCH command can also include result options. These control what info comes back about the matching messages, inside an untagged ESEARCH response ๐. If you don't give any result option, or you give an empty list written as (), ALL is assumed (more on that below). The order of the options doesn't matter ๐ธ. Options can have parameters in parentheses. The exception is when an option has a mandatory parameter that can always be written as a number or a sequence-set. Then that parameter doesn't need the parentheses. Check out "Formal Syntax" (Section 9) for the details ๐. If an option has parameters, they're made of atoms, strings, and/or lists, in one specific order. Any options that aren't defined by extensions the server supports MUST be rejected with a BAD response ๐ซ.
Note that IMAP4rev1 used SEARCH responses [RFC3501] instead of ESEARCH responses. Clients that only support IMAP4rev2 MUST ignore SEARCH responses ๐.
This document specifies the following result options:
MIN
Returns the lowest message number/UID that satisfies the SEARCH criteria ๐.
If the SEARCH gives no matches, the server MUST NOT include the MIN result option in the ESEARCH response. It still MUST send the ESEARCH response, though ๐ซถ.
MAX
Returns the highest message number/UID that satisfies the SEARCH criteria ๐.
If the SEARCH gives no matches, the server MUST NOT include the MAX result option in the ESEARCH response. It still MUST send the ESEARCH response, though ๐ซถ.
ALL
Returns all message numbers/UIDs that satisfy the SEARCH criteria, using the sequence-set syntax ๐ง. The client MUST NOT assume that the messages/UIDs will be listed in any particular order ๐ โโ๏ธ.
If the SEARCH gives no matches, the server MUST NOT include the ALL result option in the ESEARCH response. It still MUST send the ESEARCH response ๐ซถ.
COUNT
Returns the number of messages that satisfy the SEARCH criteria ๐ข. This result option MUST always be included in the ESEARCH response ๐ฏ.
SAVE
This option tells the server to remember the result of the SEARCH or UID SEARCH command (and also any command based on SEARCH, like SORT and THREAD [RFC5256]). It then stores that result in an internal variable we'll call the "search result variable" ๐ง . The client can use the "$" marker to refer to what's in that variable. The "$" marker can go wherever a message sequence or UID sequence would go, and the server swaps it out for the list of messages in the search result variable. So the client can reuse the result of the latest remembered SEARCH as a parameter for another command ๐ช. See Section 6.4.4.1 for how the value of the search result variable is figured out, how other commands affect it, and how the SAVE return option plays with the other return options ๐.
If there's no other SEARCH result option, the SAVE result option also suppresses any ESEARCH response the SEARCH command would have sent otherwise ๐คซ.
Note: Future extensions to this document might let servers return multiple ESEARCH responses for one extended SEARCH command. However, all of the options above MUST result in a single ESEARCH response, whether they're used alone or together. This guarantee keeps things simple for IMAP4rev2 clients ๐งธ. Future SEARCH extensions that loosen this rule will have to describe how results from multiple ESEARCH responses get combined ๐งฉ.
Searching criteria are made of one or more search keys ๐.
When you give more than one key, the result is the intersection (AND function) of the messages that match all of them. For example, the criteria DELETED FROM "SMITH" SINCE 1-Feb-1994 refers to all deleted messages from Smith with an INTERNALDATE after February 1, 1994 ๐. A search key can also be a parenthesized list of one or more search keys. That's how you use things like OR and NOT ๐ญ.
Server implementations MAY exclude [MIME-IMB] body parts with terminal content media types other than TEXT and MESSAGE from consideration in SEARCH matching ๐.
The OPTIONAL [CHARSET] specification is the word "CHARSET" followed by the name of a character set from the registry [CHARSET-REG] ๐๏ธ. It tells you the [CHARSET] of the strings that appear in the search criteria. [MIME-IMB] content transfer encodings and [MIME-HDRS] strings in [RFC5322]/[MIME-IMB] headers MUST be decoded before text gets compared ๐. Servers MUST support the US-ASCII and UTF-8 charsets. Other CHARSETs MAY be supported. Clients SHOULD use UTF-8 ๐. If CHARSET isn't provided, IMAP4rev2 servers MUST assume UTF-8, so picking CHARSET UTF-8 is redundant. It's still allowed, though, for better compatibility with existing IMAP4rev1 clients ๐ค.
If the server doesn't support the CHARSET you asked for, it MUST return a tagged NO response (not a BAD) ๐ โโ๏ธ. This response SHOULD contain the BADCHARSET response code, which MAY list the CHARSETs the server supports ๐งพ.
For any search key that uses strings, and unless it says otherwise, a message matches if the string is a substring of the associated text ๐งต. The matching SHOULD be case insensitive for characters in the ASCII range. For language-sensitive, case-insensitive searching, consider using [IMAP-I18N] ๐. Note that the empty string counts as a substring. This is handy for a HEADER search when you want to check whether a header field is present in the message ๐.
The defined search keys are below. Check "Formal Syntax" (Section 9) for the exact syntax of the arguments ๐.
<sequence set>
Messages whose message sequence numbers match the specified message sequence number set ๐ข.
ALL
Every message in the mailbox. It's also the default initial key for ANDing ๐.
ANSWERED
Messages with the \Answered flag set โ
.
BCC <string>
Messages that have the specified string in the envelope structure's Blind Carbon Copy (BCC) field ๐ต๏ธ.
BEFORE <date>
Messages whose internal date (ignoring time and timezone) is earlier than the specified date โช.
BODY <string>
Messages that have the specified string in the body of the message. Unlike TEXT (see below), this doesn't look at any header fields ๐. Servers are allowed to do flexible matching for this key. For example, they could match "swim" to both "swam" and "swum" in English text, or only do full-word matching, where "swim" won't match "swimming" ๐โโ๏ธ.
CC <string>
Messages that have the specified string in the envelope structure's CC field ๐จ.
DELETED
Messages with the \Deleted flag set ๐๏ธ.
DRAFT
Messages with the \Draft flag set โ๏ธ.
FLAGGED
Messages with the \Flagged flag set โญ.
FROM <string>
Messages that have the specified string in the envelope structure's FROM field ๐ฌ.
HEADER <field-name> <string>
Messages that have a header field with the specified field-name (as defined in [RFC5322]) and that contain the specified string in the text of that header field (what comes after the colon) ๐ฏ. If the string to search is zero-length, this matches every message that has a header field with the specified field-name, no matter what it says. Servers should use a substring search for this SEARCH item, since clients can use it for automatic processing that isn't started by end users ๐ค. For example, it can be used when searching for Message-ID or Content-Type header field values that need to be exact, or for searching header fields the IMAP server might not know anything about ๐ง .
KEYWORD <flag>
Messages with the specified keyword flag set ๐ท๏ธ.
LARGER <n>
Messages with an RFC822.SIZE larger than the specified number of octets ๐.
NOT <search-key>
Messages that do NOT match the specified search key ๐ โโ๏ธ.
ON <date>
Messages whose internal date (ignoring time and timezone) falls within the specified date ๐ .
OR <search-key1> <search-key2>
Messages that match either search key ๐.
SEEN
Messages with the \Seen flag set ๐.
SENTBEFORE <date>
Messages whose [RFC5322] Date: header field (ignoring time and timezone) is earlier than the specified date ๐ฐ๏ธ.
SENTON <date>
Messages whose [RFC5322] Date: header field (ignoring time and timezone) falls within the specified date ๐๏ธ.
SENTSINCE <date>
Messages whose [RFC5322] Date: header field (ignoring time and timezone) is within or later than the specified date ๐ซ.
SINCE <date>
Messages whose internal date (ignoring time and timezone) is within or later than the specified date ๐ .
SMALLER <n>
Messages with an RFC822.SIZE smaller than the specified number of octets ๐ญ.
SUBJECT <string>
Messages that have the specified string in the envelope structure's SUBJECT field ๐ฃ.
TEXT <string>
Messages that have the specified string in the header (including MIME header fields) or body of the message ๐งบ. Servers are allowed to do flexible matching for this key too, like matching "swim" to both "swam" and "swum" in English, or only doing full-word matching, where "swim" won't match "swimming" ๐โโ๏ธ.
TO <string>
Messages that have the specified string in the envelope structure's TO field ๐.
UID <sequence set>
Messages whose unique identifiers match the specified unique identifier set. Sequence-set ranges are permitted ๐.
UNANSWERED
Messages that do NOT have the \Answered flag set ๐.
UNDELETED
Messages that do NOT have the \Deleted flag set ๐.
UNDRAFT
Messages that do NOT have the \Draft flag set ๐ซถ.
UNFLAGGED
Messages that do NOT have the \Flagged flag set ๐ธ.
UNKEYWORD <flag>
Messages that do NOT have the specified keyword flag set ๐ง.
UNSEEN
Messages that do NOT have the \Seen flag set ๐ป.
Example:
Okay bestie, the examples are still going, so let's keep the vibe ๐
C: A282 SEARCH RETURN (MIN COUNT) FLAGGED
SINCE 1-Feb-1994 NOT FROM "Smith"
S: * ESEARCH (TAG "A282") MIN 2 COUNT 3
S: A282 OK SEARCH completed
Example:
C: A283 SEARCH RETURN () FLAGGED
SINCE 1-Feb-1994 NOT FROM "Smith"
S: * ESEARCH (TAG "A283") ALL 2,10:11
S: A283 OK SEARCH completed
Example:
C: A284 SEARCH TEXT "string not in mailbox"
S: * ESEARCH (TAG "A284")
S: A284 OK SEARCH completed
C: A285 SEARCH CHARSET UTF-8 TEXT {12}
S: + Ready for literal text
C: ะพัะฟััะบ
S: * ESEARCH (TAG "A285") ALL 43
S: A285 OK SEARCH completed
The next example shows how to find the first unseen message in the mailbox. So cute, right? ๐ฆ
Example:
C: A284 SEARCH RETURN (MIN) UNSEEN
S: * ESEARCH (TAG "A284") MIN 4
S: A284 OK SEARCH completed
This one is my favourite ๐ญ If the ESEARCH UID indicator is there, then all the data in the ESEARCH response is about UIDs. So the MIN result specifier gets followed by a UID, no exceptions ๐ซถ
Example:
C: A285 UID SEARCH RETURN (MIN MAX) 1:5000
S: * ESEARCH (TAG "A285") UID MIN 7 MAX 3800
S: A285 OK SEARCH completed
And here's how you get the number of deleted messages ๐ง
Example:
C: A286 SEARCH RETURN (COUNT) DELETED
S: * ESEARCH (TAG "A286") COUNT 15
S: A286 OK SEARCH completed
6.4.4.1. SAVE Result Option and SEARCH Result Variable โจ
Okay, the SAVE result option is giving main character energy ๐
Upon successful completion of a SELECT or an EXAMINE command (after the tagged OK response), the current search result variable is reset to the empty sequence.
A successful SEARCH command with the SAVE result option sets the value of the search result variable to the list of messages found in the SEARCH command. For example, if no messages were found, the search result variable will contain the empty sequence.
Any of the following SEARCH commands MUST NOT change the search result variable:
- a SEARCH command that caused the server to return the BAD tagged response,
- a SEARCH command with no SAVE result option that caused the server to return NO tagged response, and
- a successful SEARCH command with no SAVE result option.
A SEARCH command with the SAVE result option that caused the server to return the NO tagged response sets the value of the search result variable to the empty sequence.
When a message listed in the search result variable is EXPUNGEd, it is automatically removed from the list. Implementors are reminded that if the server stores the list as a list of message numbers, it MUST automatically adjust them when notifying the client about expunged messages, as described in Section 7.5.1. Servers, this is your sign to keep those numbers in sync ๐ฅ
If the server decides to send a new UIDVALIDITY value while the mailbox is opened, it causes the resetting of the search variable to the empty sequence.
Note that even if the $ marker contains the empty sequence of messages, it must be treated by all commands accepting message sets as parameters as a valid, but non-matching, list of messages. For example, the FETCH $ command would return a tagged OK response and no FETCH responses. See also Example 5 in Section 6.4.4.4. ๐
The SAVE result option doesn't change whether the server would return items corresponding to MIN, MAX, ALL, or COUNT result options.
When the SAVE result option is combined with the MIN or MAX result option, and both ALL and COUNT result options are absent, the corresponding MIN/MAX is returned (if the search result is not empty), but the $ marker would contain a single message as returned in the MIN/MAX return item.
If the SAVE result option is combined with both MIN and MAX result options, and both ALL and COUNT result options are absent, the $ marker would contain zero messages, one message, or two messages as returned in the MIN/MAX return items.
If the SAVE result option is combined with the ALL and/or COUNT result option(s), the $ marker would always contain all messages found by the SEARCH or UID SEARCH command.
The following table summarizes the additional requirement on ESEARCH server implementations described in this section.
+==============================+====================+
| Combination of Result Option | "$" Marker Value |
+==============================+====================+
| SAVE MIN | MIN |
+------------------------------+--------------------+
| SAVE MAX | MAX |
+------------------------------+--------------------+
| SAVE MIN MAX | MIN & MAX |
+------------------------------+--------------------+
| SAVE * [m] | all found messages |
+------------------------------+--------------------+
Table 4
where '*' means "ALL" and/or "COUNT", and '[m]' means optional "MIN" and/or "MAX"
Implementation note: server implementors, "$" can reference IMAP message sequences or UID sequences, depending on the context where it is used. For example, the $ marker can be set as a result of a SEARCH (SAVE) command and used as a parameter to a UID FETCH command (which accepts a UID sequence, not a message sequence), or the $ marker can be set as a result of a UID SEARCH (SAVE) command and used as a parameter to a FETCH command (which accepts a message sequence, not a UID sequence). Server implementations need to automatically map the $ marker value to message numbers or UIDs, depending on the context where the $ marker is used. ๐ง
6.4.4.2. Multiple Commands in Progress ๐
Use of a SEARCH RETURN (SAVE) command followed by a command using the "$" marker creates direct dependency between the two commands. As directed by Section 5.5, a server MUST execute the two commands in the order they were received.
A client MAY pipeline a SEARCH RETURN (SAVE) command with one or more commands using the "$" marker, as long as this doesn't create an ambiguity, as described in Section 5.5. Examples 7-9 in Section 6.4.4.4 explain this in more details. Pipelining, but make it organised ๐
6.4.4.3. Refusing to Save Search Results ๐ธ
In some cases, the server MAY refuse to save a SEARCH (SAVE) result, for example, if an internal limit on the number of saved results is reached. In this case, the server MUST return a tagged NO response containing the NOTSAVED response code and set the search result variable to the empty sequence, as described in Section 6.4.4.1. Sorry server, no saving today ๐
6.4.4.4. Examples Showing Use of the SAVE Result Option โจ
Okay bestie, quick heads up: anything starting with // in these examples is just a comment for us humans. It's not part of the protocol ๐
1. First up, the client can use a SEARCH result to FETCH headers of the messages it found ๐ฌ
Example 1:
C: A282 SEARCH RETURN (SAVE) FLAGGED SINCE 1-Feb-1994
NOT FROM "Smith"
S: A282 OK SEARCH completed, result saved
C: A283 FETCH $ (UID INTERNALDATE FLAGS BODY.PEEK[HEADER])
S: * 2 FETCH (UID 14 ...
S: * 84 FETCH (UID 100 ...
S: * 882 FETCH (UID 1115 ...
S: A283 OK completed
The client can also pipeline the two commands ๐ฅ
Example 2:
C: A282 SEARCH RETURN (SAVE) FLAGGED SINCE 1-Feb-1994
NOT FROM "Smith"
C: A283 FETCH $ (UID INTERNALDATE FLAGS BODY.PEEK[HEADER])
S: A282 OK SEARCH completed
S: * 2 FETCH (UID 14 ...
S: * 84 FETCH (UID 100 ...
S: * 882 FETCH (UID 1115 ...
S: A283 OK completed
2. Next, the result of one SEARCH can be used as input to another SEARCH. It's giving chaining ๐ฆ
Example 3:
C: A300 SEARCH RETURN (SAVE) SINCE 1-Jan-2004
NOT FROM "Smith"
S: A300 OK SEARCH completed
C: A301 UID SEARCH UID $ SMALLER 4096
S: * ESEARCH (TAG "A301") UID ALL 17,900,901
S: A301 OK completed
Note: the second command in Example 3 can be swapped out for this one:
C: A301 UID SEARCH $ SMALLER 4096
and the result of the command would be the same. โจ
3. Here the "$" marker gets combined with other message numbers using the OR SEARCH criterion. ๐ง
Example 4:
C: P282 SEARCH RETURN (SAVE) SINCE 1-Feb-1994
NOT FROM "Smith"
S: P282 OK SEARCH completed
C: P283 SEARCH CHARSET UTF-8 (OR $ 1,3000:3021) TEXT {8+}
C: ะผะฐัั
S: * ESEARCH (TAG "P283") ALL 882,1102,3003,3005:3006
S: P283 OK completed
4. A failed SEARCH sets the search result variable to the empty list. Oof ๐ The server doesn't implement the KOI8-R charset, so this one fails.
Example 5:
C: B282 SEARCH RETURN (SAVE) SINCE 1-Feb-1994
NOT FROM "Smith"
S: B282 OK SEARCH completed
C: B283 SEARCH RETURN (SAVE) CHARSET KOI8-R
(OR $ 1,3000:3021) TEXT {4}
C: XXXX
S: B283 NO [BADCHARSET UTF-8] KOI8-R is not supported
//After this command, the saved result variable contains
//no messages. A client that wants to reissue the B283
//SEARCH command with another CHARSET would have to reissue
//the B282 command as well. One possible workaround for
//this is to include the desired CHARSET parameter
//in the earliest SEARCH RETURN (SAVE) command in a
//sequence of related SEARCH commands, to cause
//the earliest SEARCH in the sequence to fail.
//A better approach might be to always use CHARSET UTF-8
//instead.
Note: this document format is limited to 7-bit ASCII text, so there's no way to show actual KOI8-R data here. The "XXXX" is just a placeholder for what would be 4 octets of 8-bit data in a real transaction. ๐
5. Using the "$" marker when it holds no messages is not an error, bestie. Totally valid ๐ธ
Example 6:
C: E282 SEARCH RETURN (SAVE) SINCE 28-Oct-2006
NOT FROM "Eric"
C: E283 COPY $ "Other Messages"
//The "$" contains no messages
S: E282 OK SEARCH completed
S: E283 OK COPY completed, nothing copied
Example 7:
C: F282 SEARCH RETURN (SAVE) KEYWORD $Junk
C: F283 COPY $ "Junk"
C: F284 STORE $ +FLAGS.Silent (\Deleted)
S: F282 OK SEARCH completed
S: F283 OK COPY completed
S: F284 OK STORE completed
Example 8:
C: G282 SEARCH RETURN (SAVE) KEYWORD $Junk
C: G283 SEARCH RETURN (ALL) SINCE 28-Oct-2006
FROM "Eric"
// The server can execute the two SEARCH commands
// in any order, as they don't have any dependency.
// For example, it may return:
S: * ESEARCH (TAG "G283") ALL 3:15,27,29:103
S: G283 OK SEARCH completed
S: G282 OK SEARCH completed
The following example shows that the result of the second SEARCH RETURN (SAVE) always overrides the result of the first. Plot twist ๐
Example 9:
C: H282 SEARCH RETURN (SAVE) KEYWORD $Junk
C: H283 SEARCH RETURN (SAVE) SINCE 28-Oct-2006
FROM "Eric"
S: H282 OK SEARCH completed
S: H283 OK SEARCH completed
// At this point "$" would contain results of H283
The following example shows the behavioral difference between different combinations of ESEARCH result options. So many combos, so much drama ๐
Example 10:
C: C282 SEARCH RETURN (ALL) SINCE 12-Feb-2006
NOT FROM "Smith"
S: * ESEARCH (TAG "C283") ALL 2,10:15,21
//$ value hasn't changed
S: C282 OK SEARCH completed
C: C283 SEARCH RETURN (ALL SAVE) SINCE 12-Feb-2006
NOT FROM "Smith"
S: * ESEARCH (TAG "C283") ALL 2,10:15,21
//$ value is 2,10:15,21
S: C283 OK SEARCH completed
C: C284 SEARCH RETURN (SAVE MIN) SINCE 12-Feb-2006
NOT FROM "Smith"
S: * ESEARCH (TAG "C284") MIN 2
//$ value is 2
S: C284 OK SEARCH completed
C: C285 SEARCH RETURN (MAX SAVE MIN) SINCE
12-Feb-2006 NOT FROM "Smith"
S: * ESEARCH (TAG "C285") MIN 2 MAX 21
//$ value is 2,21
S: C285 OK SEARCH completed
C: C286 SEARCH RETURN (MAX SAVE MIN COUNT)
SINCE 12-Feb-2006 NOT FROM "Smith"
S: * ESEARCH (TAG "C286") MIN 2 MAX 21 COUNT 8
//$ value is 2,10:15,21
S: C286 OK SEARCH completed
C: C286 SEARCH RETURN (ALL SAVE MIN) SINCE
12-Feb-2006 NOT FROM "Smith"
S: * ESEARCH (TAG "C286") MIN 2 ALL 2,10:15,21
//$ value is 2,10:15,21
S: C286 OK SEARCH completed
6.4.5. FETCH Command โจ
Arguments:
- sequence set
- message data item names or macro
Responses:
- untagged responses: FETCH
Result:
- OK - fetch completed
- NO - fetch error: can't fetch that data
- BAD - command unknown or arguments invalid
The FETCH command pulls up data attached to a message in the mailbox ๐ฅ The data items you want can be a single atom or a parenthesized list.
Most data items, the ones listed under the msg-att-static rule in the formal syntax (Section 9), are static and MUST NOT change for any particular message. โจ Other data items, the ones under the msg-att-dynamic rule, MAY change because of a STORE command or outside events. ๐ฆ
For example, if a client gets an ENVELOPE for a message it already knows the envelope for, it can safely ignore the newly sent envelope. ๐
There are three macros that bundle up commonly used sets of data items so you can use them instead of listing items one by one. A macro has to be used all on its own, never mixed with other macros or data items. ๐
- ALL: Macro equivalent to:
(FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) - FAST: Macro equivalent to:
(FLAGS INTERNALDATE RFC822.SIZE) - FULL: Macro equivalent to:
(FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY)
Several data items reference "section" or "section-binary". See Section 6.4.5.1 for their detailed definition. ๐ง
The data items you can currently fetch are:
BINARY[<section-binary>]<<partial>> Asks for the specified section to be sent after its Content-Transfer-Encoding has been decoded. ๐
The <partial> argument, if present, asks for only a subset of the data to come back. A partial FETCH BINARY works the same way as a partial FETCH BODY, with one difference: the <partial> arguments refer to the DECODED section data. ๐
Note that this data item can only be requested for leaf body parts: those with media types other than multipart/*, message/rfc822, or message/global.
BINARY.PEEK[<section-binary>]<<partial>> An alternate form of BINARY[<section-binary>] that doesn't implicitly set the \Seen flag. ๐
BINARY.SIZE[<section-binary>] Asks for the decoded size of the section (basically, the size you should expect back from the matching FETCH BINARY request). ๐
Note: client authors are cautioned that this might be an expensive operation for some server implementations. Asking for it when you don't need it could hurt performance, since servers would have to calculate the value every single time you request it. ๐ญ
Note that this data item can only be requested for leaf body parts: those with media types other than multipart/*, message/rfc822, or message/global.
BODY A non-extensible form of BODYSTRUCTURE. ๐
BODY[<section>]<<partial>> The text of a particular body section. If BODY[] is specified (with the section left out), the FETCH is asking for the [RFC5322] expression of the entire message. ๐จ
You can also fetch a substring of the text you designated. To do that, add an open angle bracket ("<"), the octet position of the first octet you want, a period, the maximum number of octets you want, and a close angle bracket (">") to the part specifier. If the starting octet is past the end of the text, you get back an empty string. ๐ซถ
Any partial fetch that tries to read past the end of the text gets truncated as needed. A partial fetch that starts at octet 0 comes back as a partial fetch, even when that truncation happens. ๐
Note: This means that BODY[]<0.2048> of a 1500-octet message will return BODY[]<0> with a literal of size 1500, not BODY[].
Note: A substring fetch of a HEADER.FIELDS or HEADER.FIELDS.NOT part specifier is calculated after the header has been subsetted. ๐ธ
The \Seen flag gets implicitly set. If that makes the flags change, they SHOULD be included as part of the FETCH responses. โจ
BODY.PEEK[<section>]<<partial>> An alternate form of BODY[<section>] that doesn't implicitly set the \Seen flag. ๐ฆ
BODYSTRUCTURE The [MIME-IMB] body structure of the message. The server computes this by parsing the [MIME-IMB] header fields in the [RFC5322] header and the [MIME-IMB] headers. See Section 7.5.2 for more details. ๐งฉ
ENVELOPE The envelope structure of the message. The server computes this by parsing the [RFC5322] header into its component parts, filling in various fields with defaults where needed. See Section 7.5.2 for more details. ๐
FLAGS The flags that are set for this message. ๐ฉ
INTERNALDATE The internal date of the message. ๐๏ธ
RFC822.SIZE The size of the message, as defined in Section 2.3.4. ๐
UID The unique identifier for the message. ๐
Example:
C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)])
S: * 2 FETCH ....
S: * 3 FETCH ....
S: * 4 FETCH ....
S: A654 OK FETCH completed
6.4.5.1. FETCH Section Specification
okay so a bunch of FETCH data items point at a "section" or "section-binary" ๐งฉ A section specification is a set of zero or more part specifiers, separated by periods. Each part specifier is either a part number or one of these: HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, MIME, or TEXT. (Non-numeric part specifiers have to be the last one in a section specification. ๐ ) An empty section specification means the entire message, header included. โจ
Every message has at least one part number. Messages that don't use MIME, and MIME messages that aren't multipart and don't have an encapsulated message inside them, only have a part 1. ๐ธ
Multipart messages get consecutive part numbers, in the order they show up in the message. If a particular part is of type message or multipart, its parts MUST be indicated by a period followed by the part number within that nested multipart part. ๐
A part of type MESSAGE/RFC822 or MESSAGE/GLOBAL also has nested part numbers, which refer to parts of the MESSAGE part's body. ๐ฆ
The HEADER, HEADER.FIELDS, HEADER.FIELDS.NOT, and TEXT part specifiers can stand alone, or they can be prefixed by one or more numeric part specifiers, as long as that numeric part specifier refers to a part of type MESSAGE/RFC822 or MESSAGE/GLOBAL. The MIME part specifier MUST be prefixed by one or more numeric part specifiers. ๐ง
The HEADER, HEADER.FIELDS, and HEADER.FIELDS.NOT part specifiers point at the [RFC5322] header of the message, or of an encapsulated [MIME-IMT] MESSAGE/RFC822 or MESSAGE/GLOBAL message. HEADER.FIELDS and HEADER.FIELDS.NOT are followed by a list of field-names (as defined in [RFC5322]) and give back a subset of the header. The HEADER.FIELDS subset only has the header fields whose field-name matches one of the names in the list. HEADER.FIELDS.NOT is the opposite: it only has the header fields whose field-name doesn't match. Field matching is ASCII-range case insensitive, but otherwise it's exact. ๐
Subsetting doesn't cut out the blank line from [RFC5322] that separates the header from the body. That blank line is included in every header fetch, except when the message has no body and no blank line. ๐ซถ
The MIME part specifier points at the [MIME-IMB] header for that part. ๐
The TEXT part specifier points at the text body of the message, and it leaves out the [RFC5322] header. ๐
Here's a complex message with some of its part specifiers, so you can see how the numbering works. ๐
HEADER ([RFC5322] header of the message)
TEXT ([RFC5322] text body of the message) MULTIPART/MIXED
1 TEXT/PLAIN
2 APPLICATION/OCTET-STREAM
3 MESSAGE/RFC822
3.HEADER ([RFC5322] header of the message)
3.TEXT ([RFC5322] text body of the message) MULTIPART/MIXED
3.1 TEXT/PLAIN
3.2 APPLICATION/OCTET-STREAM
4 MULTIPART/MIXED
4.1 IMAGE/GIF
4.1.MIME ([MIME-IMB] header for the IMAGE/GIF)
4.2 MESSAGE/RFC822
4.2.HEADER ([RFC5322] header of the message)
4.2.TEXT ([RFC5322] text body of the message) MULTIPART/MIXED
4.2.1 TEXT/PLAIN
4.2.2 MULTIPART/ALTERNATIVE
4.2.2.1 TEXT/PLAIN
4.2.2.2 TEXT/RICHTEXT
6.4.6. STORE Command ๐พ
Arguments: sequence set
message data item name
value for message data item
Responses: untagged responses: FETCH
Result: OK - store completed
NO - store error: can't store that data
BAD - command unknown or arguments invalid
The STORE command changes data attached to a message in the mailbox. โ๏ธ Normally, STORE gives back the updated value of the data in an untagged FETCH response. Adding a ".SILENT" suffix to the data item name stops that untagged FETCH, and the server SHOULD assume that the client has worked out the updated value itself, or doesn't care about it. ๐คซ
Note: Whether or not you used the ".SILENT" suffix, the server SHOULD send an untagged FETCH response if it sees a change to a message's flags coming from an external source. The point is that the flag status is known for sure, with no race condition. ๐
The data items you can store right now are:
FLAGS <flag list> : Replaces the flags for the message with the argument. The new value of the flags comes back as if you'd done a FETCH of those flags. ๐
FLAGS.SILENT <flag list> : Same as FLAGS, but it doesn't send back a new value. ๐ค
+FLAGS <flag list> : Adds the argument to the flags for the message. The new value comes back as if you'd done a FETCH of those flags. โ
+FLAGS.SILENT <flag list> : Same as +FLAGS, but no new value comes back. ๐ซฅ
-FLAGS <flag list> : Removes the argument from the flags for the message. The new value comes back as if you'd done a FETCH of those flags. โ
-FLAGS.SILENT <flag list> : Same as -FLAGS, but no new value comes back. ๐
Example:
C: A003 STORE 2:4 +FLAGS (\Deleted)
S: * 2 FETCH (FLAGS (\Deleted \Seen))
S: * 3 FETCH (FLAGS (\Deleted))
S: * 4 FETCH (FLAGS (\Deleted \Flagged \Seen))
S: A003 OK STORE completed
6.4.7. COPY Command ๐
Arguments: sequence set
mailbox name
Responses: no specific responses for this command
Result: OK - copy completed
NO - copy error: can't copy those messages or to that
name
BAD - command unknown or arguments invalid
The COPY command copies the specified message(s) to the end of the destination mailbox you pick. ๐ฆ The flags and internal date of the message(s) SHOULD be kept in the copy. ๐ท
If the destination mailbox doesn't exist, a server MUST return an error. It MUST NOT automatically create the mailbox. ๐ซ Unless it's certain the destination mailbox can not be created, the server MUST send the response code "[TRYCREATE]" as the prefix of the text in the tagged NO response. That's basically a hint saying "hey, you can try a CREATE and then retry the COPY if the CREATE works." ๐ก
If COPY fails for any reason, server implementations MUST restore the destination mailbox to how it was before the COPY attempt (other than possibly incrementing UIDNEXT). In other words, a partial copy MUST NOT be done. ๐ค
On a successful COPY, the server returns a COPYUID response code (see Section 7.1). There are two exceptions to this, listed below. โจ
For a mailbox where the client has permission to COPY to it, but not to SELECT or EXAMINE it, the server MUST NOT send a COPYUID response code, because that would reveal information about the mailbox. ๐
For a mailbox with UIDNOTSTICKY status (see Section 7.1), the server MAY leave out the COPYUID response code, since it doesn't mean anything there. ๐ซ
Example:
C: A003 COPY 2:4 MEETING
S: A003 OK [COPYUID 38505 304,319:320 3956:3958] COPY completed
6.4.8. MOVE Command ๐
Arguments: sequence set
mailbox name
Responses: no specific responses for this command
Result: OK - move completed
NO - move error: can't move those messages or to that
name
BAD - command unknown or arguments invalid
The MOVE command moves the specified message(s) to the end of the destination mailbox. ๐ฆ The flags and internal date of the message(s) SHOULD be preserved. ๐
Basically, a new message is made 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, that has the same effect as this sequence:
[UID] COPY[UID] STORE +FLAGS.SILENT \DELETEDUID EXPUNGE
Even though MOVE does the same thing as those steps, the semantics aren't identical. The in-between states those steps produce don't happen, and the response codes are different. ๐ซง Specifically, 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. ๐ โโ๏ธ
Unlike COPY, a MOVE of a set of messages might fail partway through the set. No matter whether the whole set gets moved, each individual message MUST be either moved or left alone. 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 result in a bunch of duplicate messages. ๐ฏ This holds even if the server returns a tagged NO response to the command. ๐
If the destination mailbox doesn't exist, a server MUST return an error. It MUST NOT automatically create the mailbox. Unless it's certain the destination mailbox cannot be created, the server MUST send the response code "[TRYCREATE]" as the prefix of the text in the tagged NO response. Same vibe as COPY: it hints that the client can attempt a CREATE and retry the MOVE if the CREATE works. ๐
Because MOVE is so similar to COPY, any extensions that affect COPY affect MOVE in the same way. Response codes listed in Section 7.1, plus the ones defined by extensions, get sent the same way they are for COPY. ๐
Servers send COPYUID in response to a MOVE or a UID MOVE (see Section 6.4.9) command. For more on COPYUID, check Section 7.1. Heads up: there are several exceptions listed in Section 6.4.7 that let servers skip COPYUID. ๐
Servers are also REQUIRED to send the COPYUID response code in an untagged OK before sending EXPUNGE or similar responses. Sending COPYUID in the tagged OK instead, as described in Section 6.4.7, means clients first get an EXPUNGE for a message and only afterwards the COPYUID for that same message. That order is genuinely annoying to process usefully. ๐ญ
An example:
C: a UID MOVE 42:69 foo
S: * OK [COPYUID 432432 42:69 1202:1229]
S: * 22 EXPUNGE
...More EXPUNGE responses from the server...
S: a OK Done
The server might send unrelated EXPUNGE responses too, if some messages happen to get expunged at the same time. That's totally normal IMAP behaviour, bestie. ๐ธ
Moving a message to the currently selected mailbox (where the source and target mailboxes are the same) is allowed, as long as copying the message to the currently selected mailbox is allowed. ๐ช
The server may send EXPUNGE 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. ๐ง
MOVE and UID MOVE can be pipelined with other commands, but you have to be careful. Both commands change sequence numbers and also allow unrelated EXPUNGE responses. The renumbering of other messages in the source mailbox after any EXPUNGE response can be super surprising, and it makes it unsafe to pipeline any command that relies on message sequence numbers after a MOVE or UID MOVE. Similarly, MOVE can't be pipelined with a command that might cause message renumbering. ๐ See Section 5.5 for more on the ambiguities, plus the handling requirements for both clients and servers. ๐ซถ
6.4.9. UID Command
Arguments: command name
command arguments
Responses: untagged responses: FETCH, ESEARCH, EXPUNGE
Result: OK - UID command completed NO - UID command error BAD - command unknown or arguments invalid
Okay so the UID command is literally the bestie of the whole protocol ๐ It has three forms, and each one is a little different, so let's go through them. ๐
In the first form, you give it a COPY, MOVE, FETCH, or STORE command, with the arguments that go with that command. The twist is that the numbers in the sequence-set are unique identifiers instead of message sequence numbers ๐ฆ Sequence-set ranges are allowed, but ngl there's no promise that unique identifiers will be contiguous, so don't assume they are ๐
A non-existent unique identifier gets ignored with no error message at all ๐ So it's totally possible for a UID FETCH to come back OK with no data, or for a UID COPY, UID MOVE, or UID STORE to come back OK without doing anything. Not a bug, just vibes ๐ธ
In the second form, the UID command wraps an EXPUNGE command with an extra parameter, a sequence set of UIDs to operate on. UID EXPUNGE permanently removes all messages that have BOTH the \Deleted flag set AND a UID inside that sequence set, from the currently selected mailbox. If a message doesn't have the \Deleted flag set, or its UID isn't in the sequence set, it's not affected at all โจ
UID EXPUNGE is especially useful for disconnected use clients ๐ง When you resync with the server, using UID EXPUNGE instead of plain EXPUNGE means the client can't accidentally nuke messages that other clients marked \Deleted in the meantime, between the last time it was connected and the moment it resyncs. Main character protection ๐
Example:
C: A003 UID EXPUNGE 3000:3002
S: * 3 EXPUNGE
S: * 3 EXPUNGE
S: * 3 EXPUNGE
S: A003 OK UID EXPUNGE completed
In the third form, the UID command takes a SEARCH command with its SEARCH arguments. The arguments mean the same thing as they do for SEARCH, BUT the numbers in an ESEARCH response for a UID SEARCH are unique identifiers, not message sequence numbers ๐ Also, the matching ESEARCH response MUST include the UID indicator ๐ซถ For example, UID SEARCH 1:100 UID 443:557 gives back the unique identifiers for the intersection of two sequence sets: the message sequence number range 1:100 and the UID range 443:557 ๐ฅ
Note: in that example, the UID range 443:557 shows up. The same thing about non-existent unique identifiers being ignored with no error message applies here too ๐ So even if neither UID 443 nor UID 557 exists, that range is still valid, and it would include an existing UID 495 ๐
Also note that a UID range of 559:* always includes the UID of the last message in the mailbox, even if 559 is higher than any UID that's been assigned ๐ญ That's because the contents of a range don't depend on which order the endpoints are written in. So any UID range with * as one of the endpoints covers at least one message (the one with the highest UID), unless the mailbox is empty ๐ฆ
The number after the "*" in an untagged FETCH or EXPUNGE response is ALWAYS a message sequence number, never a unique identifier, EVEN for a UID command response ๐ However, server implementations MUST implicitly include the UID message data item as part of any FETCH response caused by a UID command, whether or not a UID was asked for as a message data item in the FETCH ๐
Note: The rule about including the UID message data item in a FETCH response mainly applies to UID FETCH and UID STORE, including a UID FETCH that doesn't list UID as a message data item. Even though the other UID commands are unlikely to cause an untagged FETCH, this rule applies to them too ๐ธ
Example:
C: A999 UID FETCH 4827313:4828442 FLAGS
S: * 23 FETCH (FLAGS (\Seen) UID 4827313)
S: * 24 FETCH (FLAGS (\Seen) UID 4827943)
S: * 25 FETCH (FLAGS (\Seen) UID 4828442)
S: A999 OK UID FETCH completed
6.5. Client Commands - Experimental/Expansion
Each command that is NOT part of this specification MUST have at least one capability name (see Section 6.1.1) associated with it. (Multiple commands can share the same capability name.) ๐
Server implementations MUST NOT send any added untagged responses (the ones not specified in this specification), UNLESS the client asked for them by issuing the associated experimental command (specified in an extension document) or the ENABLE command (Section 6.3.1). ๐ฅ
The example below shows how a client can check for the presence of a made-up XPIG-LATIN capability, one that adds the XPIG-LATIN command and the XPIG-LATIN untagged response ๐ง (Heads up: for an extension, the command name and the capability name don't have to match ๐)
Example:
C: a441 CAPABILITY
S: * CAPABILITY IMAP4rev2 XPIG-LATIN
S: a441 OK CAPABILITY completed
C: A442 XPIG-LATIN
S: * XPIG-LATIN ow-nay eaking-spay ig-pay atin-lay
S: A442 OK XPIG-LATIN ompleted-cay
7. Server Responses โจ
Server responses come in three forms: status responses, server data, and command continuation requests ๐ The info in a server response, the stuff labeled "Contents:" in the response descriptions below, is described by what it DOES, not by its syntax. The exact syntax of server responses lives in "Formal Syntax" (Section 9) ๐
The client MUST be prepared to accept any response at all times ๐ซถ
Status responses can be tagged or untagged. Tagged status responses tell you the completion result (OK, NO, or BAD) of a client command, and they carry a tag matching that command ๐ฆ
Some status responses, and ALL server data, are untagged. An untagged response is marked with the token "*" instead of a tag. Untagged status responses give you the server greeting or server status that doesn't signal a command finishing (like an impending system shutdown alert) ๐ For historical reasons, untagged server data responses are also called "unsolicited data," although strictly speaking, only unilateral server data is truly "unsolicited" ๐ค
Certain server data MUST be remembered by the client when it arrives, and the description of that data says so ๐ฅ This data carries critical info that affects how ALL later commands and responses get interpreted (for example, updates about messages being created or destroyed) ๐
Other server data SHOULD be remembered for later reference. If the client doesn't need to remember it, or remembering it has no obvious purpose (for example, a SEARCH response when no SEARCH command is in progress), the data can be ignored ๐ธ
Here's an example of unilateral untagged server data: when the IMAP connection is in the selected state, the server checks the mailbox for new messages as part of command execution ๐ง Normally that happens with every command, so a NOOP command is enough to check for new messages โจ If new messages turn up, the server sends an untagged EXISTS response with the new mailbox size ๐ Server implementations that offer multiple simultaneous access to the same mailbox SHOULD also send appropriate unilateral untagged FETCH and EXPUNGE responses if another agent changes any message flags or expunges any messages ๐
Command continuation request responses use the token "+" instead of a tag ๐ The server sends these to say it accepted an incomplete client command and is ready for the rest of it ๐ฆ
7.1. Server Responses - Generic Status Responses ๐
Status responses are OK, NO, BAD, PREAUTH, and BYE ๐ OK, NO, and BAD can be tagged or untagged. PREAUTH and BYE are always untagged ๐ซถ
Status responses MAY include an OPTIONAL "response code" ๐ฅ A response code is data inside square brackets, in the form of an atom, possibly followed by a space and arguments ๐ The response code carries extra info or status codes for client software beyond the OK/NO/BAD condition, and it's defined when there's a specific action a client can take based on that extra info โจ
The currently defined response codes are:
ALERT The human-readable text contains a special alert that gets shown to the user in a way that grabs their attention ๐จ Content of ALERT response codes received on a connection WITHOUT TLS or SASL security-layer confidentiality SHOULD be ignored by clients ๐ If they ARE displayed, such alerts MUST be clearly marked as potentially suspicious ๐ (Note that some existing clients are known to hyperlink returned text, which makes them very dangerous ๐ญ) Alerts received AFTER a TLS/SASL confidentiality layer has been successfully set up MUST be presented to the user ๐
ALREADYEXISTS The operation tries to create something that already exists, like when a CREATE or RENAME command tries to make a mailbox and one with that name is already there ๐
C: o356 RENAME this that
S: o356 NO [ALREADYEXISTS] Mailbox "that" already exists
APPENDUID Followed by the UIDVALIDITY of the destination mailbox and the UID assigned to the appended message in that mailbox, it tells you the message was appended to the destination mailbox with that UID ๐ฆ
If the server also supports the [MULTIAPPEND] extension, AND multiple messages were appended in the APPEND command, then the second value is a UID set containing the UIDs assigned to the appended messages, in the order they were sent in the APPEND command ๐ง This UID set may NOT contain extraneous UIDs or the symbol "*" ๐
Note: the UID set form of the APPENDUID response code MUST NOT be used if only a single message was appended. Specifically, a server MUST NOT send a range like 123:123. This is because a client that doesn't support [MULTIAPPEND] expects only a single UID, not a UID set ๐ซฃ
UIDs are assigned in strictly ascending order in the mailbox (see Section 2.3.1.1). Also, a range of 12:10 is exactly equivalent to 10:12 and refers to the sequence 10,11,12 ๐ธ
This response code is returned in a tagged OK response to the APPEND command ๐
AUTHENTICATIONFAILED Authentication failed for some reason the server won't go into detail about. Typically this includes "unknown user" and "bad password" ๐
This is the same as sending no response code at all, EXCEPT that when a client sees AUTHENTICATIONFAILED, it knows the problem wasn't, e.g., UNAVAILABLE, so there's no point retrying the same login/password later ๐
C: b LOGIN "fred" "foo"
S: b NO [AUTHENTICATIONFAILED] Authentication failed
AUTHORIZATIONFAILED Authentication worked fine with the authentication identity, BUT the server can't or won't let that identity act as the requested authorization identity ๐ This only applies when the authentication and authorization identities are different ๐
C: c1 AUTHENTICATE PLAIN
[...]
S: c1 NO [AUTHORIZATIONFAILED] No such authorization-ID
C: c2 AUTHENTICATE PLAIN
[...]
S: c2 NO [AUTHORIZATIONFAILED] Authenticator is not an admin
BADCHARSET ๐ Optionally followed by a parenthesized list of charsets. A SEARCH failed because the given charset isn't supported by this implementation ๐. If the optional list of charsets is given, it lists the charsets that are supported by this implementation, so the client has something to work with ๐ซถ.
CANNOT ๐ซ This operation violates some invariant of the server and can never succeed. Not "try again later," just no. ๐ โโ๏ธ
C: l create "///////"
S: l NO [CANNOT] Adjacent slashes are not supported
CAPABILITY โจ Followed by a list of capabilities. This can show up in the initial OK or PREAUTH response to transmit an initial capabilities list. It can also appear in tagged responses to LOGIN or AUTHENTICATE commands. Lowkey the best part: if a client recognizes this response code and nothing changed in the TLS and/or authentication state since it was received, the client doesn't need to send a separate CAPABILITY command. Efficient, bestie ๐ง
CLIENTBUG ๐ The server has detected a client bug. This can accompany any of OK, NO, and BAD, depending on what the client bug is. So the vibe is "the server caught you," but the exact flavor depends on the mistake ๐ญ
C: k1 select "/archive/projects/experiment-iv"
[...]
S: k1 OK [READ-ONLY] Done
C: k2 status "/archive/projects/experiment-iv" (messages)
[...]
S: k2 OK [CLIENTBUG] Done
CLOSED ๐ฆ The CLOSED response code has no parameters. A server returns it when the currently selected mailbox gets closed implicitly because of a SELECT or EXAMINE command on another mailbox. It works like a boundary line ๐: everything before the CLOSED response code is about the mailbox that got closed, and everything after it is about the newly selected mailbox. Main character handoff, iykyk.
There's no need to return the CLOSED response code on completion of the CLOSE or the UNSELECT command (or similar). Those commands just close the currently selected mailbox without opening a new one, so there's nothing to hand off ๐ธ
CONTACTADMIN ๐ The user should contact the system administrator or support desk. Pretty self-explanatory, but still a whole vibe ๐
C: e login "fred" "foo"
S: e NO [CONTACTADMIN]
COPYUID ๐ Followed by the UIDVALIDITY of the destination mailbox, a UID set containing the UIDs of the message(s) in the source mailbox that were copied to the destination mailbox, followed by another UID set containing the UIDs assigned to the copied message(s) in the destination mailbox. Put together, it says the message(s) got copied to the destination mailbox with the stated UID(s). Very organized, very iconic ๐
The source UID set is in the order the message(s) was copied. The destination UID set lines up with the source UID set and is in that same order. Neither UID set may contain extraneous UIDs or the symbol "*". No sneaky extras allowed ๐ โโ๏ธ
UIDs are assigned in strictly ascending order in the mailbox (refer to Section 2.3.1.1). Also, a range of 12:10 is exactly equivalent to 10:12, and it refers to the sequence 10,11,12. Same squad, just reversed ๐
This response code is returned in a tagged OK response to the COPY or UID COPY command, or in the untagged OK response to the MOVE or UID MOVE command ๐
CORRUPTION ๐ The server discovered that some relevant data (e.g., the mailbox) is corrupt. This response code doesn't include any information about what's corrupt, but the server can write that to its logfiles. So the client gets the bad news, and the details live in the server's logs ๐
C: i select "/archive/projects/experiment-iv"
S: i NO [CORRUPTION] Cannot open mailbox
EXPIRED ๐ฅ Either authentication succeeded or the server no longer had the necessary data. Either way, access is no longer permitted using that passphrase. The client or user should get a new passphrase ๐
C: d login "fred" "foo"
S: d NO [EXPIRED] That password isn't valid any more
EXPUNGEISSUED ๐งน Someone else has issued an EXPUNGE for the same mailbox. The client may want to issue NOOP soon. [IMAP-MULTIACCESS] discusses this subject in depth, so go read it if you're curious ๐ค
C: h search from maria@example.com
S: * ESEARCH (TAG "h") ALL 1:3,5,8,13,21,42
S: h OK [EXPUNGEISSUED] Search completed
HASCHILDREN ๐ถ The mailbox delete operation failed because the mailbox has one or more children, and the server doesn't allow deletion of mailboxes with children. Family tree says no ๐ณ
C: m356 DELETE Notes
S: o356 NO [HASCHILDREN] Mailbox "Notes" has children
that need to be deleted first
INUSE ๐ชต An operation hasn't been carried out because it involves sawing off a branch someone else is sitting on ๐ค. Someone else may be holding an exclusive lock needed for this operation, or the operation may involve deleting a resource someone else is using, typically a mailbox. The operation may succeed if the client tries again later, so patience is the move โณ
C: g delete "/archive/projects/experiment-iv"
S: g NO [INUSE] Mailbox in use
LIMIT ๐งฎ The operation ran up against an implementation limit of some kind, such as the number of flags on a single message or the number of flags used in a mailbox. Even the best servers have a ceiling, bestie ๐
C: m STORE 42 FLAGS f1 f2 f3 f4 f5 ... f250
S: m NO [LIMIT] At most 32 flags in one mailbox supported
NONEXISTENT ๐ป The operation attempts to delete something that does not exist. Similar to ALREADYEXISTS, just in the opposite direction ๐ช
C: p RENAME this that
S: p NO [NONEXISTENT] No such mailbox
NOPERM ๐ The access control system (e.g., ACL; see [RFC4314]) does not permit this user to carry out an operation, such as selecting or creating a mailbox. Not on the list, not getting in ๐ช
C: f select "/archive/projects/experiment-iv"
S: f NO [NOPERM] Access denied
OVERQUOTA ๐ The user would be over quota after the operation. (The user may or may not be over quota already. Tea ๐ซ.)
Note that if the server sends OVERQUOTA but doesn't support the IMAP QUOTA extension defined by [RFC2087], then there is a quota, but the client can't find out what the quota is. Mysterious, honestly ๐ต๏ธโโ๏ธ
C: n1 uid copy 1:* oldmail
S: n1 NO [OVERQUOTA] Sorry
C: n2 uid copy 1:* oldmail
S: n2 OK [OVERQUOTA] You are now over your soft quota
PARSE ๐งฉ The human-readable text represents an error in parsing the [RFC5322] header or [MIME-IMB] headers of a message in the mailbox. The message's header is giving broken, and the server is calling it out ๐จ
PERMANENTFLAGS ๐ท๏ธ Followed by a parenthesized list of flags, and it indicates which of the known flags the client can change permanently. Any flags that are in the FLAGS untagged response but not in the PERMANENTFLAGS list cannot be set permanently. The PERMANENTFLAGS list can also include the special flag *, which indicates that it's possible to create new keywords by attempting to store those keywords in the mailbox โจ. If the client attempts to STORE a flag that is not in the PERMANENTFLAGS list, the server will either ignore the change or store the state change for the remainder of the current session only. Temporary is still a little bit real ๐ซ
There's no need for a server that included the special flag * to return a new PERMANENTFLAGS response code when a new keyword was successfully set on a message upon client request. However, if the server has a limit on the number of different keywords that can be stored in a mailbox and that limit is reached, the server MUST send a new PERMANENTFLAGS response code without the special flag *. That one's a hard rule, no exceptions ๐จ
PRIVACYREQUIRED ๐ถ๏ธ The operation is not permitted due to a lack of data confidentiality. If TLS isn't in use, the client could try STARTTLS (see Section 6.2.1) or alternatively reconnect on an Implicit TLS port, and then repeat the operation. Get the privacy first, then try again ๐
C: d login "fred" "foo"
S: d NO [PRIVACYREQUIRED] Connection offers no privacy
C: d select inbox
S: d NO [PRIVACYREQUIRED] Connection offers no privacy
READ-ONLY ๐ The mailbox is selected as read-only, or its access while selected has changed from read-write to read-only. Look, don't touch ๐
READ-WRITE โ๏ธ The mailbox is selected as read-write, or its access while selected has changed from read-only to read-write. Okay, now you can touch ๐ฅฐ
SERVERBUG ๐ The server encountered a bug in itself or violated one of its own invariants. Oops, the server messed up, and it's saying so out loud ๐ญ
C: j select "/archive/projects/experiment-iv"
S: j NO [SERVERBUG] This should not happen
TRYCREATE ๐ ๏ธ An APPEND, COPY, or MOVE attempt is failing because the target mailbox does not exist (as opposed to some other reason). This is a hint to the client that the operation can succeed if the mailbox is first created by the CREATE command. Build it first, then slay ๐
UIDNEXT ๐ข Followed by a decimal number, and it indicates the next unique identifier value. Refer to Section 2.3.1.1 for more information ๐
UIDNOTSTICKY ๐ชจ The selected mailbox is supported by a mail store that does not support persistent UIDs. That means UIDVALIDITY will be different each time the mailbox is selected. Consequently, APPEND or COPY to this mailbox will not return an APPENDUID or COPYUID response code ๐
This response code is returned in an untagged NO response to the SELECT command.
Note: servers SHOULD NOT have any UIDNOTSTICKY mail stores. This facility exists to support legacy mail stores in which it is technically infeasible to support persistent UIDs. This should be avoided when designing new mail stores. Legacy only, please ๐ง
UIDVALIDITY ๐ Followed by a decimal number, and it indicates the unique identifier validity value. Refer to Section 2.3.1.1 for more information ๐ชช
UNAVAILABLE ๐ Temporary failure because a subsystem is down. For example, an IMAP server that uses a Lightweight Directory Access Protocol (LDAP) or Radius server for authentication might use this response code when the LDAP/Radius server is down. Backend said "brb" ๐ฐ๏ธ
C: a LOGIN "fred" "foo"
S: a NO [UNAVAILABLE] User's backend down for maintenance
UNKNOWN-CTE ๐งพ The server does not know how to decode the section's Content-Transfer-Encoding. The encoding is giving unreadable, and the server is not pretending it can read it ๐คทโโ๏ธ
Client implementations MUST ignore response codes that they do not recognize. Yes, even the mystery ones, because that's how we stay compatible ๐
7.1.1. OK Response
Contents: OPTIONAL response code human-readable text
The OK response indicates an information message from the server. When tagged, it indicates successful completion of the associated command ๐. The human-readable text MAY be presented to the user as an information message. The untagged form indicates an information-only message; the nature of the information MAY be indicated by a response code ๐.
The untagged form is also used as one of three possible greetings at connection startup. It indicates that the connection is not yet authenticated and that a LOGIN or an AUTHENTICATE command is needed ๐. Hello, now log in, babe ๐ซถ
Example:
S: * OK IMAP4rev2 server ready
C: A001 LOGIN fred blurdybloop
S: * OK [ALERT] System shutdown in 10 minutes
S: A001 OK LOGIN Completed
7.1.2. NO Response
Contents: OPTIONAL response code human-readable text
The NO response is the server's way of saying "hmm, something went wrong operationally" ๐ When it's tagged, it means the command you sent didn't finish successfully. When it's untagged, it's more of a heads-up or warning, and the command can still complete just fine โจ The human-readable text is where the server explains what's going on.
Example:
C: A222 COPY 1:2 owatagusiam
S: * NO Disk is 98% full, please delete unnecessary data
S: A222 OK COPY completed
C: A223 COPY 3:200 blurdybloop
S: * NO Disk is 99% full, please delete unnecessary data
S: * NO Disk is 99% full, please delete unnecessary data
S: A223 NO COPY failed: disk is full
Wait, I need to correct that example. Here is the exact transcript, character for character:
C: A222 COPY 1:2 owatagusiam
S: * NO Disk is 98% full, please delete unnecessary data
S: A222 OK COPY completed
C: A223 COPY 3:200 blurdybloop
S: * NO Disk is 98% full, please delete unnecessary data
S: * NO Disk is 99% full, please delete unnecessary data
S: A223 NO COPY failed: disk is full
Okay bestie, that's the real one ๐ซถ The untagged NO lines are warnings, and the tagged NO at the end is the one that means the COPY actually failed ๐ญ
7.1.3. BAD Response
Contents: OPTIONAL response code human-readable text
Okay so BAD is the server basically saying "that's a protocol-level error" ๐ When it's tagged, it's pointing at the exact command that caused the problem, and the tag tells you which one. When it's untagged, the server can't pin the error on a specific command, or something inside the server itself broke. Either way, the human-readable text explains the situation ๐
Example:
C: ...very long command line...
S: * BAD Command line too long
C: ...empty line...
S: * BAD Empty command line
C: A443 EXPUNGE
S: * BAD Disk crash, attempting salvage to a new disk!
S: * OK Salvage successful, no data lost
S: A443 OK Expunge completed
7.1.4. PREAUTH Response
Contents: OPTIONAL response code human-readable text
PREAUTH is always untagged and it's one of the three possible greetings when you first connect ๐ฆ It means the connection was already authenticated some other way, so you don't need to send LOGIN or AUTHENTICATE. Lowkey iconic, but there's a catch: since PREAUTH drops you straight into the authenticated state, it kind of blocks you from using STARTTLS (Section 6.2.1). So the PREAUTH response SHOULD only be sent by servers on connections already protected by TLS (like an Implicit TLS port [RFC8314]) or protected some other way, like IPsec. Clients that need mandatory TLS MUST close the connection after getting PREAUTH on a port that isn't protected ๐จ
Example:
S: * PREAUTH IMAP4rev2 server logged in as Smith
7.1.5. BYE Response
Contents: OPTIONAL response code human-readable text
BYE is always untagged and it means the server is about to close the connection ๐ The human-readable text MAY be shown to the user in a status report by the client. A BYE gets sent in one of four situations:
- as part of a normal logout sequence. The server will close the connection after sending the tagged OK response to the LOGOUT command.
- as a panic shutdown announcement. The server closes the connection immediately.
- as an announcement of an inactivity autologout. The server closes the connection immediately.
- as one of three possible greetings at connection startup, indicating that the server is not willing to accept a connection from this client. The server closes the connection immediately.
The difference between a BYE from a normal LOGOUT (the first case) and a BYE from a failure (the other three) is that in the failure cases the connection closes right away ๐ญ In every case, the client SHOULD keep reading response data from the server until the connection is closed. That way any pending untagged or completion responses still get read and processed ๐ซถ
Example:
S: * BYE Autologout; idle for too long
7.2. Server Responses - Server Status
These responses are always untagged. This is how server status data gets sent from the server to the client ๐
7.2.1. ENABLED Response
Contents: capability listing
The ENABLED response shows up as a result of an ENABLE command โจ The capability listing is a space-separated list of capability names that the server supports and that were successfully enabled. The ENABLED response MAY contain no capabilities, which means none of the extensions the client asked for got enabled ๐
Example:
S: * ENABLED CONDSTORE QRESYNC
7.2.2. CAPABILITY Response
Contents: capability listing
The CAPABILITY response comes back as a result of a CAPABILITY command ๐ The capability listing is a space-separated list of capability names the server supports. The capability listing MUST include the atom "IMAP4rev2", but it doesn't have to be the first one listed. Order doesn't mean anything here, so don't stress about it ๐
Client and server implementations MUST implement the capabilities "AUTH=PLAIN" (described in [PLAIN]), and MUST implement "STARTTLS" and "LOGINDISABLED" on the cleartext port. Check out the Security Considerations (Section 11) for important info about these capabilities ๐ฅ
A capability name that begins with "AUTH=" tells you the server supports that particular authentication mechanism [SASL] ๐
The LOGINDISABLED capability means the LOGIN command is turned off. The server will reply with a tagged NO response to any attempt to use LOGIN, even if the user name and password are valid (their validity will not be checked) ๐
An IMAP client MUST NOT issue the LOGIN command if the server advertises the LOGINDISABLED capability.
Other capability names mean the server supports an extension, revision, or amendment to the IMAP4rev2 protocol. If the IMAP4rev1 capability is not advertised, server responses MUST conform to this document until the client issues a command that uses an additional capability. If both IMAP4rev1 and IMAP4rev2 capabilities are advertised, server responses MUST conform to [RFC3501] until the client issues a command that uses an additional capability. (For example, the client can issue ENABLE IMAP4rev2 to turn on IMAP4rev2-specific behavior ๐ง)
Capability names SHOULD be registered with IANA using the RFC Required policy [RFC8126]. A server SHOULD NOT offer unregistered capability names ๐
Client implementations SHOULD NOT require any capability name other than "IMAP4rev2", and possibly "STARTTLS" and "LOGINDISABLED" (on a cleartext port). Client implementations MUST ignore any unknown capability names ๐
A server MAY send capabilities automatically, by using the CAPABILITY response code in the initial PREAUTH or OK responses and by sending an updated CAPABILITY response code in the tagged OK response as part of a successful authentication. A client doesn't need to send a separate CAPABILITY command if it recognizes these automatic capabilities and nothing changed in the TLS and/or authentication state since they arrived ๐ฆ
The list of capabilities a server returns MAY change during the connection. It's quite common for the server to change the list after successful TLS negotiation (STARTTLS command) and/or after successful authentication (AUTHENTICATE or LOGIN commands) ๐ธ
Example:
S: * CAPABILITY STARTTLS AUTH=GSSAPI IMAP4rev2 LOGINDISABLED
XPIG-LATIN
Note that in the above example, XPIG-LATIN is a fictitious capability name ๐ง
7.3. Server Responses - Mailbox Status
These responses are always untagged. This is how mailbox status data gets sent from the server to the client. Many of these responses typically come from a command with the same name ๐
7.3.1. LIST Response ๐
Okay so the LIST response is what the server sends back when you send a LIST command ๐ Each one hands you back a single name that matches your LIST spec, and you can get loads of them for one command. Here's what the bundle looks like:
Contents:
name attributes
hierarchy delimiter
name
OPTIONAL extension data
Let's talk about the base mailbox name attributes first, aka the little vibe tags that describe a mailbox ๐ฆ
\NonExistent
The "\NonExistent" attribute means the mailbox name doesn't point to a real mailbox ๐ป It's not really useful on its own, because names that match the canonical LIST pattern but don't exist must not be returned unless one of the two conditions below is also satisfied:
- The mailbox name also satisfies the selection criteria (for example, it is subscribed and the "SUBSCRIBED" selection option has been specified).
- "RECURSIVEMATCH" has been specified, and the mailbox name has at least one descendant mailbox name that does not match the LIST pattern and does match the selection criteria.
In practice, the "\NonExistent" attribute is usually returned with one or more of "\Subscribed", "\Remote", "\HasChildren", or the CHILDINFO extended data item. โจ
The "\NonExistent" attribute implies "\NoSelect". ๐
\Noinferiors
No child levels of hierarchy can exist under this name. None exist now, and none can be created in the future. Bestie, that's a hard no ๐ซ
\Noselect
You can't use this name as a selectable mailbox. Iykyk ๐
\HasChildren
This attribute tells you the mailbox has child mailboxes ๐ณ A server SHOULD NOT set this attribute if there are child mailboxes and the user does not have permission to access any of them. In that case, \HasNoChildren SHOULD be used. Sometimes though, a server can't efficiently figure out whether the user can access any child mailboxes, so it's not always that simple ๐ฅบ
Also, even though the \HasChildren attribute for a mailbox must be correct at the time the server processes the mailbox, a client must be prepared for a plot twist: the mailbox is marked with \HasChildren, but no child mailbox shows up in the response to the LIST command. This could happen if another client deleted the children, or made them inaccessible to the user with access control, before the server got around to listing them. Main character energy from the server, honestly ๐ญ
\HasNoChildren
This attribute means the mailbox has NO child mailboxes that are accessible to the currently authenticated user ๐ โโ๏ธ
\Marked
The server has marked this mailbox as "interesting" โญ It probably contains messages that were added since the last time the mailbox was selected.
\Unmarked
The mailbox doesn't contain any additional messages since the last time it was selected. Nothing new, bestie ๐
\Subscribed
The mailbox name was subscribed to using the SUBSCRIBE command ๐
\Remote
The mailbox is a remote mailbox ๐ฐ๏ธ
It is an error for the server to return both a \HasChildren and a \HasNoChildren attribute in the same LIST response. If a client runs into a LIST response with both of those attributes present, it should act as if both are absent in that LIST response. Not the vibe, so we just ignore both ๐
Note: the \HasNoChildren attribute should not be confused with the \NoInferiors attribute, which indicates that no child mailboxes exist now and none can be created in the future. Different vibes, totally different things!
If it isn't feasible for the server to determine whether or not the mailbox is "interesting", the server SHOULD NOT send either \Marked or \Unmarked. The server MUST NOT send more than one of \Marked, \Unmarked, and \Noselect for a single mailbox, and it MAY send none of these. Choose your fighter, but never more than one ๐ฅ
In addition to the base mailbox name attributes above, an IMAP server MAY also include any or all of the following attributes that denote the "role" (or "special-use") of a mailbox ๐ผ These get included along with the base attributes. A given mailbox may have none, one, or more than one of these. Sometimes a special use is advice to a client about what to put in that mailbox, and other times it's advice about what to expect to find there. Both are iconic ๐
\All
This mailbox presents all messages in the user's message store ๐ Implementations MAY omit some messages, such as, perhaps, those in \Trash and \Junk. When this special use is supported, it is almost certain to be a virtual mailbox.
\Archive
This mailbox is used to archive messages ๐๏ธ What an "archival" mailbox means is server dependent. Typically, it's used to get messages out of the inbox, or otherwise keep them out of the user's way, while still keeping them accessible.
\Drafts
This mailbox holds draft messages, usually messages that are being composed but haven't been sent yet โ๏ธ On some servers this might be a virtual mailbox, holding messages from other mailboxes that are marked with the "\Draft" message flag. Or it might just be advice that a client put drafts here.
\Flagged
This mailbox presents all messages marked in some way as "important" ๐ฉ When this special use is supported, it's likely a virtual mailbox collecting messages (from other mailboxes) that are marked with the "\Flagged" message flag.
\Junk
This is where messages deemed to be junk mail get held ๐๏ธ Some servers might put messages here automatically. Or it might just be advice for a client-side spam filter. Ew, but make it organized ๐
\Sent
This mailbox holds copies of messages that have been sent ๐ค Some servers might put messages here automatically. Or it might just be advice that a client save sent messages here.
\Trash
This mailbox holds messages that have been deleted or marked for deletion ๐งบ On some servers this might be a virtual mailbox, holding messages from other mailboxes that are marked with the "\Deleted" message flag. Or it might just be advice that a client that doesn't use the IMAP "\Deleted" model should use as its trash location. On servers that strictly expect the IMAP "\Deleted" model, this special use is likely not supported.
All special-use attributes are OPTIONAL, and any given server or message store may support any combination of them, or none at all. Usually there's at most one mailbox with a given attribute for a given user, but on some servers or message stores it's possible for multiple mailboxes to have the same special-use attribute ๐งฉ
Special-use attributes are likely to be user specific ๐ For example, User Adam might share his \Sent mailbox with user Barb, but that mailbox is unlikely to also serve as Barb's \Sent mailbox. Not everyone gets the same main character mailbox!
Other mailbox name attributes can be found in the "IMAP Mailbox Name Attributes" registry [IMAP-MAILBOX-NAME-ATTRS-REG] ๐
The hierarchy delimiter is the character used to separate levels of hierarchy in a mailbox name ๐ฟ A client can use it to create child mailboxes and to search higher or lower levels of the naming hierarchy. All children of a top-level hierarchy node MUST use the same separator character. A NIL hierarchy delimiter means there's no hierarchy, and the name is a "flat" name ๐ฅ
The name represents an unambiguous left-to-right hierarchy and MUST be valid for use as a reference in the LIST command. Unless \Noselect or \NonExistent is indicated, the name MUST also be valid as an argument for commands, such as SELECT, that accept mailbox names. So it has to work everywhere, periodt ๐
The name might be followed by an OPTIONAL series of extended fields, which is a parenthesized list of tagged data (also called an "extended data item") ๐ The first element of an extended field is a string that identifies the type of data. [RFC5258] specifies requirements on string registration (these strings are called "tags", and they're not to be confused with IMAP command tags). In particular, it states that "Tags MUST be registered with IANA". This document doesn't change that. See Section 9.5 of [RFC5258] for the registration template. The server MAY return data in the extended fields that the client didn't directly ask for in the corresponding LIST command. For example, the client can enable extra extended fields by using another IMAP extension that makes use of the extended LIST responses. The client MUST ignore all extended fields it doesn't recognize, so no drama ๐ซถ
Example:
S: * LIST (\Noselect) "/" ~/Mail/foo
Example:
S: * LIST (\Marked) ":" Tables (tablecloth (("edge" "lacy")
("color" "red")) Sample "text")
S: * LIST () ":" Tables:new (tablecloth ("edge" "lacy")
Sample ("text" "more text"))
7.3.2. NAMESPACE Response ๐ธ
Contents:
Contents: the prefix and hierarchy delimiter to the server's
Personal Namespace(s), Other Users' Namespace(s), and
Shared Namespace(s)
The NAMESPACE response happens as a result of a NAMESPACE command ๐บ๏ธ It gives you the prefix and hierarchy delimiter for the server's Personal Namespace(s), Other Users' Namespace(s), and Shared Namespace(s) that the server wants to expose. For any namespace class that isn't available, the response will contain a NIL. The Namespace-Response-Extensions ABNF non-terminal is defined for extensibility and MAY be included in the response. Extensible and open to growth, love that for it ๐ฆ
Example:
S: * NAMESPACE (("" "/")) (("~" "/")) NIL
7.3.3. STATUS Response โจ
Contents:
Contents:
name
status parenthesized list
The STATUS response happens as a result of a STATUS command ๐ It returns the mailbox name that matches the STATUS specification, along with the requested mailbox status information. Quick and to the point, I respect it ๐
Example:
S: * STATUS blurdybloop (MESSAGES 231 UIDNEXT 44292)
7.3.4. ESEARCH Response ๐โจ
Contents: one or more search-return-data pairs
Okay bestie, the ESEARCH response shows up whenever the server answers a SEARCH or UID SEARCH command ๐ It starts with an optional search correlator. If that's missing, the response wasn't triggered by one specific IMAP command. If it's there, it holds the tag of the command that caused it to be sent ๐
After the correlator comes an optional UID indicator. When that's present, everything in the ESEARCH response is about UIDs. When it isn't, all the data is about message numbers ๐ฆ
The rest of the response is one or more search data pairs. Each pair starts with a unique return item name, then a space, then its data. The pairs can come in any order ๐ Unless an extension says otherwise, a return item name SHOULD appear only once in an ESEARCH response ๐
This document specifies these return item names:
MIN Returns the lowest message number or UID that matches the SEARCH criteria. ๐ธ
If the SEARCH finds no matches, the server MUST NOT include the MIN return item in the ESEARCH response. It still MUST send the ESEARCH response though, so it's not skipping out on the whole thing ๐
MAX Returns the highest message number or UID that matches the SEARCH criteria. ๐
If the SEARCH finds no matches, the server MUST NOT include the MAX return item in the ESEARCH response. It still MUST send the ESEARCH response ๐
ALL Returns every message number or UID that matches the SEARCH criteria, written using the sequence-set syntax. Each set MUST be complete. Specifically, a UID set only shows up in an ESEARCH response when every number in the range corresponds to an existing (matching) message. The client MUST NOT assume that messages or UIDs will be listed in any particular order ๐ญ
If the SEARCH finds no matches, the server MUST NOT include the ALL return item in the ESEARCH response. It still MUST send the ESEARCH response โจ
COUNT Returns the number of messages that match the SEARCH criteria. This return item MUST always be included in the ESEARCH response ๐ฅ
Example:
S: * ESEARCH UID COUNT 17 ALL 4:18,21,28
Example:
S: * ESEARCH (TAG "a567") UID COUNT 17 ALL 4:18,21,28
Example:
S: * ESEARCH COUNT 18 ALL 1:17,21
7.3.5. FLAGS Response ๐ฉ
Contents: flag parenthesized list
The FLAGS response happens when the client runs a SELECT or EXAMINE command. The flag parenthesized list tells you which flags apply to this mailbox, and at a minimum that includes the system-defined flags. Other flags can exist too, depending on how the server is implemented ๐ท
The update from the FLAGS response MUST be remembered by the client. Literally keep that in your memory bank ๐ง ๐
Example:
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
7.4. Server Responses - Mailbox Size ๐ฆ
These responses are always untagged. This is how the server tells the client that the mailbox size has changed ๐ Right after the "*" token there's a number, and that number is a message count ๐ข
7.4.1. EXISTS Response ๐ง
Contents: none
The EXISTS response reports how many messages are in the mailbox. It shows up as a result of a SELECT or EXAMINE command, and also whenever the size of the mailbox changes (like when new messages arrive) ๐ฌ
The update from the EXISTS response MUST be remembered by the client. Keep track of that count, bestie ๐
Example:
S: * 23 EXISTS
7.5. Server Responses - Message Status ๐
These responses are always untagged. This is how the server sends message data to the client, often because of a command that has the same name. Right after the "*" token is a number, and that number is a message sequence number ๐
7.5.1. EXPUNGE Response ๐๏ธ
Contents: none
The EXPUNGE response tells you that the message sequence number you named has been permanently removed from the mailbox ๐ The message sequence number of each message after it goes down by 1 right away, and that decrease shows up in message sequence numbers in later responses, including other untagged EXPUNGE responses ๐ฆ
The EXPUNGE response also lowers the number of messages in the mailbox. You don't need to send an EXISTS response with the new count, because it's already handled ๐
Here's the tricky bit: because of that immediate decrement rule, the message sequence numbers in a run of successive EXPUNGE responses depend on the order the messages get removed. If they go from lower numbers to higher, or from higher numbers to lower, the output looks different. For example, if the last 5 messages in a 9-message mailbox are expunged, a "lower to higher" server will send five untagged EXPUNGE responses for message sequence number 5. A "higher to lower" server will send successive untagged EXPUNGE responses for message sequence numbers 9, 8, 7, 6, and 5 ๐คฏ
An EXPUNGE response MUST NOT be sent when no command is in progress, and it MUST NOT be sent while responding to a FETCH, STORE, or SEARCH command. This rule keeps the message sequence numbers from getting out of sync between client and server, so it's super important ๐ซถ A command isn't "in progress" until the complete command has been received. In particular, a command isn't "in progress" while the command continuation is being negotiated ๐
Note: UID FETCH, UID STORE, and UID SEARCH are different commands from FETCH, STORE, and SEARCH. An EXPUNGE response MAY be sent during a UID command. ๐
The update from the EXPUNGE response MUST be remembered by the client.
Example:
S: * 44 EXPUNGE
7.5.2. FETCH Response ๐
Contents: message data
The FETCH response sends data about a message back to the client. The data comes as pairs of data item names and values, and the values go inside parentheses ๐ This response happens as the result of a FETCH or STORE command, and it can also happen when the server decides to do it on its own (like flag updates) โจ
The current data items are:
BINARY[<section-binary>]<<number>> This is an <nstring> or <literal8> with the content of the specified section, after removing any encoding named in the matching Content-Transfer-Encoding header field. If <number> is present, it refers to the offset within the DECODED section data ๐
If the domain of the decoded data is "8bit" and the data doesn't contain the NUL octet, the server SHOULD return the data in a <string> instead of a <literal8>. This lets the client figure out whether the "8bit" data has a NUL octet without having to scan the whole data stream for NULs ๐ต๏ธโโ๏ธ
Messaging clients and servers have been notoriously lax about the Internet CRLF convention for ending lines of textual data (text/* media types) in Internet protocols. Ugh, the worst ๐ญ When sending data in a BINARY[...] FETCH data item, servers MUST ensure that textual line-oriented sections are always sent using the IMAP CRLF line termination syntax. This applies no matter how the data is stored on the server ๐
If the server doesn't know how to decode the section's Content-Transfer-Encoding, it MUST fail the request and issue a "NO" response that contains the UNKNOWN-CTE response code ๐
BINARY.SIZE[<section-binary>] This is the size of the section after removing any encoding named in the matching Content-Transfer-Encoding header field. The value returned MUST match the size of the <nstring> or <literal8> that the corresponding FETCH BINARY request returns ๐
If the server doesn't know how to decode the section's Content-Transfer-Encoding, it MUST fail the request and issue a "NO" response that contains the UNKNOWN-CTE response code ๐
โโ๏ธ
BODY This is a form of BODYSTRUCTURE without the extension data ๐งฉ
BODY[<section>]<<origin octet>> This is a string with the body contents of the specified section. The client SHOULD interpret the string according to the content transfer encoding, body type, and subtype ๐ธ
If the origin octet is specified, this string is a substring of the entire body contents, starting at that origin octet. So BODY[]<0> MAY be truncated, but BODY[] is NEVER truncated ๐ซฃ
Note: The origin octet facility MUST NOT be used by a server in a FETCH response unless the client specifically requested it with a FETCH of a BODY[<section>]<<partial>> data item. ๐ซ
8-bit textual data is allowed if a [CHARSET] identifier is part of the body parameter parenthesized list for this section. Headers (the HEADER or MIME part specifiers, or the header portion of a MESSAGE/RFC822 or MESSAGE/GLOBAL part) MAY be in UTF-8. Also, the [RFC5322] delimiting blank line between the header and the body isn't affected by header-line subsetting. The blank line is always included as part of the header data, except when a message has no body and no blank line ๐ฆ
Non-textual data, like binary data, MUST be transfer encoded into a textual form, such as base64, before it's sent to the client. To get the original binary data back, the client MUST decode the transfer-encoded string ๐
BODYSTRUCTURE This is a parenthesized list that describes the [MIME-IMB] body structure of a message. The server works it out by parsing the [MIME-IMB] header fields and filling in defaults for various fields where needed ๐งฑ
For example, a simple text message of 48 lines and 2279 octets can have a body structure of:
("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 2279 48)
Multiple parts are shown with parenthesis nesting. Instead of a body type as the first element of the parenthesized list, there's a sequence of one or more nested body structures. The second element of the parenthesized list is the multipart subtype (mixed, digest, parallel, alternative, etc.) ๐ช
For example, a two-part message made of a text part and a base64-encoded text attachment can have a body structure of:
(("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 1152 23)
("TEXT" "PLAIN" ("CHARSET" "US-ASCII" "NAME" "cc.diff")
"<960723163407.20117h@cac.washington.edu>" "Compiler diff"
"BASE64" 4554 73) "MIXED")
Extension data follows the multipart subtype. Extension data is never returned with the BODY fetch, but it can be returned with a BODYSTRUCTURE fetch. Extension data, if present, MUST be in the defined order. The extension data of a multipart body part is in the following order: ๐
body parameter parenthesized list This is a parenthesized list of attribute/value pairs, as defined in [MIME-IMB]. For example, ("foo" "bar" "baz" "rag") means "bar" is the value of "foo", and "rag" is the value of "baz" ๐ Servers SHOULD decode parameter-value continuations and parameter-value character sets as described in [RFC2231]. For example, if the message contains parameters "baz*0", "baz*1", and "baz*2", the server should decode them per [RFC2231], concatenate them, and return the resulting value as a parameter "baz". Similarly, if the message contains parameters "foo*0*" and "foo*1*", the server should decode them per [RFC2231], convert to UTF-8, concatenate them, and return the resulting value as a parameter "foo*" ๐
Okay bestie, we're still in BODYSTRUCTURE land ๐ โจ The body disposition field is a parenthesized list: a disposition type string, then a parenthesized list of attribute/value pairs, all defined in [DISPOSITION]. Servers SHOULD decode parameter-value continuations as described in [RFC2231] ๐
body language is a string or parenthesized list with the body language value from [LANGUAGE-TAGS] ๐ธ
body location is a string with the body content URI from [LOCATION] ๐ฆ
Any extension data after that is not defined yet in this version of the protocol ๐ It can be zero or more NILs, strings, numbers, or nested parenthesized lists of those. Client implementations that do a BODYSTRUCTURE fetch MUST be prepared to accept it. Server implementations MUST NOT send it until a revision of this protocol has defined it. Very strict, very important ๐
The basic fields of a non-multipart body part come in this order:
body type is a string with the content media-type name from [MIME-IMB] ๐
body subtype is a string with the content subtype name from [MIME-IMB] ๐
body parameter parenthesized list is a parenthesized list of attribute/value pairs, like ("foo" "bar" "baz" "rag"), where "bar" is the value of "foo" and "rag" is the value of "baz". It's defined in [MIME-IMB] โจ
body id is a string with the Content-ID header field value, as defined in Section 7 of [MIME-IMB] ๐ซถ
body description is a string with the Content-Description header field value, as defined in Section 8 of [MIME-IMB] ๐
body encoding is a string with the content transfer encoding, as defined in Section 6 of [MIME-IMB] ๐
body size is a number giving the size of the body in octets. This size is measured in its transfer encoding, NOT after any decoding. (Sorry, I had to yell that, it's a classic trap ๐ญ)
A body type of type MESSAGE and subtype RFC822 has, right after the basic fields, the envelope structure, the body structure, and the size in text lines of the encapsulated message ๐จ
A body type of type TEXT has, right after the basic fields, the size of the body in text lines. Again, that size is in its content transfer encoding, not the decoded size ๐ง
Extension data follows the basic fields and the type-specific fields above. It's never returned with the BODY fetch, but it can come back with a BODYSTRUCTURE fetch. If it's present, it MUST be in the defined order ๐
The extension data of a non-multipart body part comes in this order:
body MD5 is a string with the body MD5 value from [MD5] ๐ฅ
body disposition has the same content and function as the body disposition for a multipart body part ๐
body language is a string or parenthesized list with the body language value from [LANGUAGE-TAGS] ๐ธ
body location is a string with the body content URI from [LOCATION] ๐ฆ
Any extension data after that is still not defined in this version and would work the same way as the multipart extension data above ๐
ENVELOPE is a parenthesized list describing the envelope structure of a message. The server computes it by parsing the [RFC5322] header into its component parts, filling in defaults for various fields where needed ๐
The envelope fields come in this order: date, subject, from, sender, reply-to, to, cc, bcc, in-reply-to, and message-id. The date, subject, in-reply-to, and message-id fields are strings. The from, sender, reply-to, to, cc, and bcc fields are parenthesized lists of address structures ๐ฌ
An address structure is a parenthesized list describing an electronic mail address. Its fields come in this order: display name, the [SMTP] at-domain-list (the source route and obs-route ABNF production from [RFC5322]), the mailbox name (the local-part ABNF production from [RFC5322]), and the hostname ๐บ๏ธ
[RFC5322] group syntax shows up as a special address structure where the hostname field is NIL. If the mailbox name is also NIL, it's an end-of-group marker (the semicolon in RFC 822 syntax). If the mailbox name is non-NIL, it's a start-of-group marker, and the mailbox name holds the group name phrase ๐งฉ
If the Date, Subject, In-Reply-To, and Message-ID header fields are missing from the [RFC5322] header, the matching envelope member is NIL. If those header fields are present but empty, the matching member is the empty string ๐ซง
Note: some servers may return a NIL envelope member in the "present but empty" case. Clients SHOULD treat NIL and the empty string as identical.
Note: [RFC5322] requires that all messages have a valid Date header field. So for a well-formed message, the date member can't be NIL or the empty string. It can be NIL for a malformed or draft message ๐
Note: [RFC5322] requires that In-Reply-To and Message-ID header fields, if present, have non-empty content. So for a well-formed message, those envelope members can't be the empty string. They can still be the empty string for a malformed message ๐
If the From, To, Cc, and Bcc header fields are missing from the [RFC5322] header, or are present but empty, the matching envelope member is NIL ๐ซ
If the Sender or Reply-To header fields are missing from the [RFC5322] header, or are present but empty, the server sets the matching envelope member to the same value as the from member. The client isn't expected to know how to do this ๐คซ
Note: [RFC5322] requires that all messages have a valid From header field. So for a well-formed message, the from, sender, and reply-to members can't be NIL. They can be NIL for a malformed or draft message ๐ฉ
FLAGS is a parenthesized list of the flags set for this message ๐ฉ
INTERNALDATE is a string with the internal date of the message ๐ฐ๏ธ
RFC822.SIZE is a number with the size of a message, as described in Section 2.3.4 ๐
UID is a number with the unique identifier of the message ๐
If the server chooses to send unsolicited FETCH responses, they MUST include the UID FETCH item. The original spec notes this is a new requirement compared to [RFC3501] ๐
Example:
S: * 23 FETCH (FLAGS (\Seen) RFC822.SIZE 44827 UID 447)
7.6. Server Responses - Command Continuation Request
The command continuation request is marked with a "+" token instead of a tag ๐ฏ It means the server is ready to take the rest of a command from the client. The rest of the response is a line of text ๐ฌ
This response is used in the AUTHENTICATE command to send server data to the client and ask for more client data. It's also used when any command argument is a synchronizing literal ๐
The client is NOT permitted to send the octets of a synchronizing literal unless the server says it's expected. That lets the server process commands and reject errors line by line ๐ฆ The rest of the command, including the CRLF that ends the command, comes after the literal octets. If there are more command arguments, the literal octets are followed by a space and those arguments ๐ง
Example:
C: A001 LOGIN {11}
S: + Ready for additional command text
C: FRED FOOBAR {7}
S: + Ready for additional command text
C: fat man
S: A001 OK LOGIN completed
C: A044 BLURDYBLOOP {102856}
S: A044 BAD No such command as "BLURDYBLOOP"
8. Sample IMAP4rev2 Connection โจ
Here's a transcript of an IMAP4rev2 connection on a non-TLS port ๐ A long line in this sample got broken up for editorial clarity, so don't panic if it wraps ๐
S: * OK [CAPABILITY STARTTLS AUTH=SCRAM-SHA-256 LOGINDISABLED
IMAP4rev2] IMAP4rev2 Service Ready
C: a000 starttls
S: a000 OK Proceed with TLS negotiation
<TLS negotiation>
C: A001 AUTHENTICATE SCRAM-SHA-256
biwsbj11c2VyLHI9ck9wck5HZndFYmVSV2diTkVrcU8=
S: + cj1yT3ByTkdmd0ViZVJXZ2JORWtxTyVodllEcFdVYTJSYVRDQWZ1eEZJbGopaE
5sRiRrMCxzPVcyMlphSjBTTlk3c29Fc1VFamI2Z1E9PSxpPTQwOTY=
C: Yz1iaXdzLHI9ck9wck5HZndFYmVSV2diTkVrcU8laHZZRHBXVWEyUmFUQ0FmdXhG
SWxqKWhObEYkazAscD1kSHpiWmFwV0lrNGpVaE4rVXRlOXl0YWc5empmTUhnc3Ft
bWl6N0FuZFZRPQ==
S: + dj02cnJpVFJCaTIzV3BSUi93dHVwK21NaFVaVW4vZEI1bkxUSlJzamw5NUc0
PQ==
C:
S: A001 OK SCRAM-SHA-256 authentication successful
C: babc ENABLE IMAP4rev2
S: * ENABLED IMAP4rev2
S: babc OK Some capabilities enabled
C: a002 select inbox
S: * 18 EXISTS
S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S: * OK [UIDVALIDITY 3857529045] UIDs valid
S: * LIST () "/" INBOX ("OLDNAME" ("inbox"))
S: a002 OK [READ-WRITE] SELECT completed
C: a003 fetch 12 full
S: * 12 FETCH (FLAGS (\Seen) INTERNALDATE
"17-Jul-1996 02:44:25 -0700" RFC822.SIZE 4286 ENVELOPE (
"Wed, 17 Jul 1996 02:23:25 -0700 (PDT)"
"IMAP4rev2 WG mtg summary and minutes"
(("Terry Gray" NIL "gray" "cac.washington.edu"))
(("Terry Gray" NIL "gray" "cac.washington.edu"))
(("Terry Gray" NIL "gray" "cac.washington.edu"))
((NIL NIL "imap" "cac.washington.edu"))
((NIL NIL "minutes" "CNRI.Reston.VA.US")
("John Klensin" NIL "KLENSIN" "MIT.EDU")) NIL NIL
"<B27397-0100000@cac.washington.ed>")
BODY ("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT"
3028 92))
S: a003 OK FETCH completed
C: a004 fetch 12 body[header]
S: * 12 FETCH (BODY[HEADER] {342}
S: Date: Wed, 17 Jul 1996 02:23:25 -0700 (PDT)
S: From: Terry Gray <gray@cac.washington.edu>
S: Subject: IMAP4rev2 WG mtg summary and minutes
S: To: imap@cac.washington.edu
S: cc: minutes@CNRI.Reston.VA.US, John Klensin <KLENSIN@MIT.EDU>
S: Message-Id: <B27397-0100000@cac.washington.edu>
S: MIME-Version: 1.0
S: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
S:
S: )
S: a004 OK FETCH completed
C: a005 store 12 +flags \deleted
S: * 12 FETCH (FLAGS (\Seen \Deleted))
S: a005 OK +FLAGS completed
C: a006 logout
S: * BYE IMAP4rev2 server terminating connection
S: a006 OK LOGOUT completed
9. Formal Syntax ๐
The syntax below is written in Augmented Backus-Naur Form (ABNF) notation, as specified in [ABNF] ๐ง
If a later rule overlaps an earlier one in alternative or optional rules, the rule listed earlier MUST take priority ๐ฅ For example, "\Seen" parsed as a flag is the \Seen flag name and NOT a flag-extension, even though \Seen could also be parsed as a flag-extension. A few of these overlaps are noted below, but not all of them ๐ซ
Note: [ABNF] rules MUST be followed strictly; in particular:
Okay bestie, we're still in the Formal Syntax era ๐ and these rules come first, no cap โจ
- Unless otherwise noted, all alphabetic characters are case insensitive. Uppercase or lowercase characters are only used to define token strings for editorial clarity ๐ Implementations MUST accept these strings in a case-insensitive fashion ๐ซถ
- In all cases, SP refers to exactly one space ๐ It is not permitted to swap in a TAB, add extra spaces, or treat SP as equivalent to linear whitespace (LWSP). Not the vibe ๐ญ
- The ASCII NUL character,
%x00, MUST NOT be used anywhere, except in the OCTET production ๐
Here's the grammar, and yes it's long, but every single line matters ๐ฅ
SP = <Defined in RFC 5234>
CTL = <Defined in RFC 5234>
CRLF = <Defined in RFC 5234>
ALPHA = <Defined in RFC 5234>
DIGIT = <Defined in RFC 5234>
DQUOTE = <Defined in RFC 5234>
OCTET = <Defined in RFC 5234>
address = "(" addr-name SP addr-adl SP addr-mailbox SP
addr-host ")"
addr-adl = nstring
; Holds route from [RFC5322] obs-route if
; non-NIL
addr-host = nstring
; NIL indicates [RFC5322] group syntax.
; Otherwise, holds [RFC5322] domain name
addr-mailbox = nstring
; NIL indicates end of [RFC5322] group; if
; non-NIL and addr-host is NIL, holds
; [RFC5322] group name.
; Otherwise, holds [RFC5322] local-part
; after removing [RFC5322] quoting
addr-name = nstring
; If non-NIL, holds phrase from [RFC5322]
; mailbox after removing [RFC5322] quoting
append = "APPEND" SP mailbox [SP flag-list] [SP date-time]
SP literal
append-uid = uniqueid
astring = 1*ASTRING-CHAR / string
ASTRING-CHAR = ATOM-CHAR / resp-specials
atom = 1*ATOM-CHAR
ATOM-CHAR = <any CHAR except atom-specials>
atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards /
quoted-specials / resp-specials
authenticate = "AUTHENTICATE" SP auth-type [SP initial-resp]
*(CRLF base64)
auth-type = atom
; Authentication mechanism name, as defined by
; [SASL], Section 7.1
base64 = *(4base64-char) [base64-terminal]
base64-char = ALPHA / DIGIT / "+" / "/"
; Case sensitive
base64-terminal = (2base64-char "==") / (3base64-char "=")
body = "(" (body-type-1part / body-type-mpart) ")"
body-extension = nstring / number / number64 /
"(" body-extension *(SP body-extension) ")"
; Future expansion. Client implementations
; MUST accept body-extension fields. Server
; implementations MUST NOT generate
; body-extension fields except as defined by
; future Standard or Standards Track
; revisions of this specification.
body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang
[SP body-fld-loc *(SP body-extension)]]]
; MUST NOT be returned on non-extensible
; "BODY" fetch
body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang
[SP body-fld-loc *(SP body-extension)]]]
; MUST NOT be returned on non-extensible
; "BODY" fetch
body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP
body-fld-enc SP body-fld-octets
body-fld-desc = nstring
body-fld-dsp = "(" string SP body-fld-param ")" / nil
body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/
"QUOTED-PRINTABLE") DQUOTE) / string
; Content-Transfer-Encoding header field value.
; Defaults to "7BIT" (as per RFC 2045)
; if not present in the body part.
body-fld-id = nstring
body-fld-lang = nstring / "(" string *(SP string) ")"
body-fld-loc = nstring
body-fld-lines = number64
body-fld-md5 = nstring
body-fld-octets = number
body-fld-param = "(" string SP string *(SP string SP string) ")" /
nil
body-type-1part = (body-type-basic / body-type-msg / body-type-text)
[SP body-ext-1part]
body-type-basic = media-basic SP body-fields
; MESSAGE subtype MUST NOT be "RFC822" or
; "GLOBAL"
body-type-mpart = 1*body SP media-subtype
[SP body-ext-mpart]
; MULTIPART body part
body-type-msg = media-message SP body-fields SP envelope
SP body SP body-fld-lines
body-type-text = media-text SP body-fields SP body-fld-lines
capability = ("AUTH=" auth-type) / atom
; New capabilities SHOULD be
; registered with IANA using the
; RFC Required policy, i.e., in
; a Standards Track, an Experimental,
; or an Informational RFC.
capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev2"
*(SP capability)
; See Section 6.1.1 for information about
; required security-related capabilities.
; Servers that offer RFC 1730 compatibility MUST
; list "IMAP4" as the first capability.
; Servers that offer RFC 3501 compatibility MUST
; list "IMAP4rev1" as one of the capabilities.
CHAR = <defined in [ABNF]>
CHAR8 = %x01-ff
; any OCTET except NUL, %x00
charset = atom / quoted
childinfo-extended-item = "CHILDINFO" SP "("
list-select-base-opt-quoted
*(SP list-select-base-opt-quoted) ")"
; Extended data item (mbox-list-extended-item)
; returned when the RECURSIVEMATCH
; selection option is specified.
; Note 1: the CHILDINFO extended data item tag can be
; returned with or without surrounding quotes, as per
; mbox-list-extended-item-tag production.
; Note 2: The selection options are always returned
; quoted, unlike their specification in
; the extended LIST command.
child-mbox-flag = "\HasChildren" / "\HasNoChildren"
; attributes for the CHILDREN return option, at most
; one possible per LIST response
command = tag SP (command-any / command-auth /
command-nonauth / command-select) CRLF
; Modal based on state
command-any = "CAPABILITY" / "LOGOUT" / "NOOP"
; Valid in all states
command-auth = append / create / delete / enable / examine /
list / namespace-command / rename /
select / status / subscribe / unsubscribe /
idle
; Valid only in Authenticated or Selected state
command-nonauth = login / authenticate / "STARTTLS"
; Valid only when in Not Authenticated state
command-select = "CLOSE" / "UNSELECT" / "EXPUNGE" / copy /
move / fetch / store / search / uid
; Valid only when in Selected state
continue-req = "+" SP (resp-text / base64) CRLF
copy = "COPY" SP sequence-set SP mailbox
create = "CREATE" SP mailbox
; Use of INBOX gives a NO error
date = date-text / DQUOTE date-text DQUOTE
date-day = 1*2DIGIT
; Day of month
date-day-fixed = (SP DIGIT) / 2DIGIT
; Fixed-format version of date-day
date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
"Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
date-text = date-day "-" date-month "-" date-year
date-year = 4DIGIT
date-time = DQUOTE date-day-fixed "-" date-month "-" date-year
SP time SP zone DQUOTE
delete = "DELETE" SP mailbox
; Use of INBOX gives a NO error
digit-nz = %x31-39
; 1-9
eitem-standard-tag = atom
; a tag for LIST extended data item defined in a Standard
; Track or Experimental RFC.
eitem-vendor-tag = vendor-token "-" atom
; a vendor-specific tag for LIST extended data item
enable = "ENABLE" 1*(SP capability)
enable-data = "ENABLED" *(SP capability)
envelope = "(" env-date SP env-subject SP env-from SP
env-sender SP env-reply-to SP env-to SP env-cc SP
env-bcc SP env-in-reply-to SP env-message-id ")"
env-bcc = "(" 1*address ")" / nil
env-cc = "(" 1*address ")" / nil
env-date = nstring
env-from = "(" 1*address ")" / nil
env-in-reply-to = nstring
env-message-id = nstring
env-reply-to = "(" 1*address ")" / nil
env-sender = "(" 1*address ")" / nil
env-subject = nstring
env-to = "(" 1*address ")" / nil
esearch-response = "ESEARCH" [search-correlator] [SP "UID"]
*(SP search-return-data)
; ESEARCH response replaces SEARCH response
; from IMAP4rev1.
examine = "EXAMINE" SP mailbox
fetch = "FETCH" SP sequence-set SP (
"ALL" / "FULL" / "FAST" /
fetch-att / "(" fetch-att *(SP fetch-att) ")")
fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
"RFC822.SIZE" /
"BODY" ["STRUCTURE"] / "UID" /
"BODY" section [partial] /
"BODY.PEEK" section [partial] /
"BINARY" [".PEEK"] section-binary [partial] /
"BINARY.SIZE" section-binary
flag = "\Answered" / "\Flagged" / "\Deleted" /
"\Seen" / "\Draft" / flag-keyword / flag-extension
; Does not include "\Recent"
flag-extension = "\" atom
; Future expansion. Client implementations
; MUST accept flag-extension flags. Server
; implementations MUST NOT generate
; flag-extension flags except as defined by
; a future Standard or Standards Track
; revisions of this specification.
; "\Recent" was defined in RFC 3501
; and is now deprecated.
flag-fetch = flag / obsolete-flag-recent
flag-keyword = "$MDNSent" / "$Forwarded" / "$Junk" /
"$NotJunk" / "$Phishing" / atom
flag-list = "(" [flag *(SP flag)] ")"
flag-perm = flag / "\*"
greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF
header-fld-name = astring
header-list = "(" header-fld-name *(SP header-fld-name) ")"
idle = "IDLE" CRLF "DONE"
initial-resp = (base64 / "=")
; "initial response" defined in
; Section 4 of [SASL]
list = "LIST" [SP list-select-opts] SP
mailbox SP mbox-or-pat
[SP list-return-opts]
list-mailbox = 1*list-char / string
Okay, the grammar era is in full swing ๐ ๐ Here's the next chunk of rules, kept exactly as written.
list-char = ATOM-CHAR / list-wildcards / resp-specials
list-return-opt = return-option
; Note that return-option is the ABNF
; non-terminal used by RFC 5258
list-return-opts = "RETURN" SP
"(" [list-return-opt *(SP list-return-opt)] ")"
; list return options, e.g., CHILDREN
list-select-base-opt = "SUBSCRIBED" / option-extension
; options that can be used by themselves
list-select-base-opt-quoted = DQUOTE list-select-base-opt DQUOTE
list-select-independent-opt = "REMOTE" / option-extension
; options that do not syntactically interact with
; other options
list-select-mod-opt = "RECURSIVEMATCH" / option-extension
; options that require a list-select-base-opt
; to also be present
list-select-opt = list-select-base-opt / list-select-independent-opt
/ list-select-mod-opt
list-select-opts = "(" [
(*(list-select-opt SP) list-select-base-opt
*(SP list-select-opt))
/ (list-select-independent-opt
*(SP list-select-independent-opt))
] ")"
; Any number of options may be in any order.
; If a list-select-mod-opt appears, then a
; list-select-base-opt must also appear.
; This allows these:
; ()
; (REMOTE)
; (SUBSCRIBED)
; (SUBSCRIBED REMOTE)
; (SUBSCRIBED RECURSIVEMATCH)
; (SUBSCRIBED REMOTE RECURSIVEMATCH)
; But does NOT allow these:
; (RECURSIVEMATCH)
; (REMOTE RECURSIVEMATCH)
Next up are the literals and the mailbox rules, which are super important for not mixing up your INBOX casing ๐ฆ
list-wildcards = "%" / "*"
literal = "{" number64 ["+"] "}" CRLF *CHAR8
; <number64> represents the number of CHAR8s.
; A non-synchronizing literal is distinguished
; from a synchronizing literal by the presence of
; "+" before the closing "}".
; Non-synchronizing literals are not allowed when
; sent from server to the client.
literal8 = "~{" number64 "}" CRLF *OCTET
; <number64> represents the number of OCTETs
; in the response string.
login = "LOGIN" SP userid SP password
mailbox = "INBOX" / astring
; INBOX is case insensitive. All case variants
; of INBOX (e.g., "iNbOx") MUST be interpreted as
; INBOX, not as an astring. An astring that
; consists of the case-insensitive sequence
; "I" "N" "B" "O" "X" is considered
; to be an INBOX and not an astring.
; Refer to Section 5.1 for further
; semantic details of mailbox names.
mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list /
esearch-response /
"STATUS" SP mailbox SP "(" [status-att-list] ")" /
number SP "EXISTS" / namespace-response /
obsolete-search-response /
obsolete-recent-response
; obsolete-search-response and
; obsolete-recent-response can only be returned
; by servers that support both IMAPrev1
; and IMAPrev2.
mailbox-list = "(" [mbx-list-flags] ")" SP
(DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox
[SP mbox-list-extended]
; This is the list information pointed to by the ABNF
; item "mailbox-data", which is defined above
mbox-list-extended = "(" [mbox-list-extended-item
*(SP mbox-list-extended-item)] ")"
mbox-list-extended-item = mbox-list-extended-item-tag SP
tagged-ext-val
mbox-list-extended-item-tag = astring
; The content MUST conform to either
; "eitem-vendor-tag" or "eitem-standard-tag"
; ABNF productions.
mbox-or-pat = list-mailbox / patterns
mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag
*(SP mbx-list-oflag) /
mbx-list-oflag *(SP mbx-list-oflag)
mbx-list-oflag = "\Noinferiors" / child-mbox-flag /
"\Subscribed" / "\Remote" / flag-extension
; Other flags; multiple from this list are
; possible per LIST response, but each flag
; can only appear once per LIST response
mbx-list-sflag = "\NonExistent" / "\Noselect" / "\Marked" /
"\Unmarked"
; Selectability flags; only one per LIST response
Now the media types, message data, and the namespace stuff. The namespace bit has a lot of nested structure, so hold on to your hair clips ๐โจ
media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" /
"FONT" / "MESSAGE" / "MODEL" / "VIDEO" ) DQUOTE)
/ string)
SP media-subtype
; FONT defined in [RFC8081].
; MODEL defined in [RFC2077].
; Other top-level media types
; are defined in [MIME-IMT].
media-message = DQUOTE "MESSAGE" DQUOTE SP
DQUOTE ("RFC822" / "GLOBAL") DQUOTE
; Defined in [MIME-IMT]
media-subtype = string
; Defined in [MIME-IMT]
media-text = DQUOTE "TEXT" DQUOTE SP media-subtype
; Defined in [MIME-IMT]
message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att))
move = "MOVE" SP sequence-set SP mailbox
msg-att = "(" (msg-att-dynamic / msg-att-static)
*(SP (msg-att-dynamic / msg-att-static)) ")"
msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")"
; MAY change for a message
msg-att-static = "ENVELOPE" SP envelope /
"INTERNALDATE" SP date-time /
"RFC822.SIZE" SP number64 /
"BODY" ["STRUCTURE"] SP body /
"BODY" section ["<" number ">"] SP nstring /
"BINARY" section-binary SP (nstring / literal8) /
"BINARY.SIZE" section-binary SP number /
"UID" SP uniqueid
; MUST NOT change for a message
name-component = 1*UTF8-CHAR
; MUST NOT contain ".", "/", "%", or "*"
namespace = nil / "(" 1*namespace-descr ")"
namespace-command = "NAMESPACE"
namespace-descr = "(" string SP
(DQUOTE QUOTED-CHAR DQUOTE / nil)
[namespace-response-extensions] ")"
namespace-response-extensions = *namespace-response-extension
namespace-response-extension = SP string SP
"(" string *(SP string) ")"
namespace-response = "NAMESPACE" SP namespace
SP namespace SP namespace
; The first Namespace is the Personal Namespace(s).
; The second Namespace is the Other Users'
; Namespace(s).
; The third Namespace is the Shared Namespace(s).
Last stretch of this part: the number types, the obsolete bits, the option stuff, and the response rules. Almost there, bestie ๐ฆ๐
nil = "NIL"
nstring = string / nil
number = 1*DIGIT
; Unsigned 32-bit integer
; (0 <= n < 4,294,967,296)
number64 = 1*DIGIT
; Unsigned 63-bit integer
; (0 <= n <= 9,223,372,036,854,775,807)
nz-number = digit-nz *DIGIT
; Non-zero unsigned 32-bit integer
; (0 < n < 4,294,967,296)
nz-number64 = digit-nz *DIGIT
; Unsigned 63-bit integer
; (0 < n <= 9,223,372,036,854,775,807)
obsolete-flag-recent = "\Recent"
obsolete-recent-response = number SP "RECENT"
obsolete-search-response = "SEARCH" *(SP nz-number)
oldname-extended-item = "OLDNAME" SP "(" mailbox ")"
; Extended data item (mbox-list-extended-item)
; returned in a LIST response when a mailbox is
; renamed or deleted. Also returned when
; the server canonicalized the provided mailbox
; name.
; Note 1: the OLDNAME tag can be returned
; with or without surrounding quotes, as per
; mbox-list-extended-item-tag production.
option-extension = (option-standard-tag / option-vendor-tag)
[SP option-value]
option-standard-tag = atom
; an option defined in a Standards Track or
; Experimental RFC
option-val-comp = astring /
option-val-comp *(SP option-val-comp) /
"(" option-val-comp ")"
option-value = "(" option-val-comp ")"
option-vendor-tag = vendor-token "-" atom
; a vendor-specific option, non-standard
partial-range = number64 ["." nz-number64]
; Copied from RFC 5092 (IMAP URL)
; and updated to support 64-bit sizes.
partial = "<" number64 "." nz-number64 ">"
; Partial FETCH request. 0-based offset of
; the first octet, followed by the number of
; octets in the fragment.
password = astring
patterns = "(" list-mailbox ")"
; [RFC5258] supports multiple patterns,
; but this document only requires one
; to be supported.
; If the server is also implementing
; [RFC5258], the "patterns" syntax from
; that document must be followed.
quoted = DQUOTE *QUOTED-CHAR DQUOTE
QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> /
"\" quoted-specials / UTF8-2 / UTF8-3 / UTF8-4
quoted-specials = DQUOTE / "\"
rename = "RENAME" SP mailbox SP mailbox
; Use of INBOX as a destination gives a NO error
response = *(continue-req / response-data) response-done
response-data = "*" SP (resp-cond-state / resp-cond-bye /
mailbox-data / message-data / capability-data /
enable-data) CRLF
response-done = response-tagged / response-fatal
response-fatal = "*" SP resp-cond-bye CRLF
; Server closes connection immediately
response-tagged = tag SP resp-cond-state CRLF
resp-code-apnd = "APPENDUID" SP nz-number SP append-uid
resp-code-copy = "COPYUID" SP nz-number SP uid-set SP uid-set
resp-cond-auth = ("OK" / "PREAUTH") SP resp-text
; Authentication condition
resp-cond-bye = "BYE" SP resp-text
resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text
; Status condition
resp-specials = "]"
resp-text = ["[" resp-text-code "]" SP] [text]
okay bestie, the grammar keeps going and it's still giving precision ๐๐
resp-text-code = "ALERT" /
"BADCHARSET" [SP "(" charset *(SP charset) ")" ] /
capability-data / "PARSE" /
"PERMANENTFLAGS" SP
"(" [flag-perm *(SP flag-perm)] ")" /
"READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
"UIDNEXT" SP nz-number /
"UIDVALIDITY" SP nz-number /
resp-code-apnd / resp-code-copy / "UIDNOTSTICKY" /
"UNAVAILABLE" / "AUTHENTICATIONFAILED" /
"AUTHORIZATIONFAILED" / "EXPIRED" /
"PRIVACYREQUIRED" / "CONTACTADMIN" / "NOPERM" /
"INUSE" / "EXPUNGEISSUED" / "CORRUPTION" /
"SERVERBUG" / "CLIENTBUG" / "CANNOT" /
"LIMIT" / "OVERQUOTA" / "ALREADYEXISTS" /
"NONEXISTENT" / "NOTSAVED" / "HASCHILDREN" /
"CLOSED" /
"UNKNOWN-CTE" /
atom [SP 1*<any TEXT-CHAR except "]">]
return-option = "SUBSCRIBED" / "CHILDREN" / status-option /
option-extension
search = "SEARCH" [search-return-opts]
SP search-program
search-correlator = SP "(" "TAG" SP tag-string ")"
search-key = "ALL" / "ANSWERED" / "BCC" SP astring /
"BEFORE" SP date / "BODY" SP astring /
"CC" SP astring / "DELETED" / "FLAGGED" /
"FROM" SP astring / "KEYWORD" SP flag-keyword /
"ON" SP date / "SEEN" /
"SINCE" SP date / "SUBJECT" SP astring /
"TEXT" SP astring / "TO" SP astring /
"UNANSWERED" / "UNDELETED" / "UNFLAGGED" /
"UNKEYWORD" SP flag-keyword / "UNSEEN" /
; Above this line were in [IMAP2]
"DRAFT" / "HEADER" SP header-fld-name SP astring /
"LARGER" SP number64 / "NOT" SP search-key /
"OR" SP search-key SP search-key /
"SENTBEFORE" SP date / "SENTON" SP date /
"SENTSINCE" SP date / "SMALLER" SP number64 /
"UID" SP sequence-set / "UNDRAFT" / sequence-set /
"(" search-key *(SP search-key) ")"
search-modifier-name = tagged-ext-label
search-mod-params = tagged-ext-val
; This non-terminal shows recommended syntax
; for future extensions.
search-program = ["CHARSET" SP charset SP]
search-key *(SP search-key)
; CHARSET argument to SEARCH MUST be
; registered with IANA.
search-ret-data-ext = search-modifier-name SP search-return-value
; Note that not every SEARCH return option
; is required to have the corresponding
; ESEARCH return data.
search-return-data = "MIN" SP nz-number /
"MAX" SP nz-number /
"ALL" SP sequence-set /
"COUNT" SP number /
search-ret-data-ext
; All return data items conform to
; search-ret-data-ext syntax.
; Note that "$" marker is not allowed
; after the ALL return data item.
search-return-opts = SP "RETURN" SP "(" [search-return-opt
*(SP search-return-opt)] ")"
search-return-opt = "MIN" / "MAX" / "ALL" / "COUNT" /
"SAVE" /
search-ret-opt-ext
; conforms to generic search-ret-opt-ext
; syntax
search-ret-opt-ext = search-modifier-name [SP search-mod-params]
search-return-value = tagged-ext-val
; Data for the returned search option.
; A single "nz-number"/"number"/"number64" value
; can be returned as an atom (i.e., without
; quoting). A sequence-set can be returned
; as an atom as well.
section = "[" [section-spec] "]"
section-binary = "[" [section-part] "]"
section-msgtext = "HEADER" /
"HEADER.FIELDS" [".NOT"] SP header-list /
"TEXT"
; top-level or MESSAGE/RFC822 or
; MESSAGE/GLOBAL part
section-part = nz-number *("." nz-number)
; body part reference.
; Allows for accessing nested body parts.
section-spec = section-msgtext / (section-part ["." section-text])
section-text = section-msgtext / "MIME"
; text other than actual body part (headers,
; etc.)
select = "SELECT" SP mailbox
seq-number = nz-number / "*"
; message sequence number (COPY, FETCH, STORE
; commands) or unique identifier (UID COPY,
; UID FETCH, UID STORE commands).
; * represents the largest number in use. In
; the case of message sequence numbers, it is
; the number of messages in a non-empty mailbox.
; In the case of unique identifiers, it is the
; unique identifier of the last message in the
; mailbox or, if the mailbox is empty, the
; mailbox's current UIDNEXT value.
; The server should respond with a tagged BAD
; response to a command that uses a message
; sequence number greater than the number of
; messages in the selected mailbox. This
; includes "*" if the selected mailbox is empty.
seq-range = seq-number ":" seq-number
; two seq-number values and all values between
; these two regardless of order.
; Example: 2:4 and 4:2 are equivalent and
; indicate values 2, 3, and 4.
; Example: a unique identifier sequence range of
; 3291:* includes the UID of the last message in
; the mailbox, even if that value is less than
; 3291.
sequence-set = (seq-number / seq-range) ["," sequence-set]
; set of seq-number values, regardless of order.
; Servers MAY coalesce overlaps and/or execute
; the sequence in any order.
; Example: a message sequence number set of
; 2,4:7,9,12:* for a mailbox with 15 messages is
; equivalent to 2,4,5,6,7,9,12,13,14,15
; Example: a message sequence number set of
; *:4,5:7 for a mailbox with 10 messages is
; equivalent to 10,9,8,7,6,5,4,5,6,7 and MAY
; be reordered and overlap coalesced to be
; 4,5,6,7,8,9,10.
sequence-set =/ seq-last-command
; Allow for "result of the last command"
; indicator.
seq-last-command = "$"
status = "STATUS" SP mailbox SP
"(" status-att *(SP status-att) ")"
status-att = "MESSAGES" / "UIDNEXT" / "UIDVALIDITY" /
"UNSEEN" / "DELETED" / "SIZE"
status-att-val = ("MESSAGES" SP number) /
("UIDNEXT" SP nz-number) /
("UIDVALIDITY" SP nz-number) /
("UNSEEN" SP number) /
("DELETED" SP number) /
("SIZE" SP number64)
; Extensions to the STATUS responses
; should extend this production.
; Extensions should use the generic
; syntax defined by tagged-ext.
status-att-list = status-att-val *(SP status-att-val)
status-option = "STATUS" SP "(" status-att *(SP status-att) ")"
; This ABNF production complies with
; <option-extension> syntax.
store = "STORE" SP sequence-set SP store-att-flags
store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP
(flag-list / (flag *(SP flag)))
string = quoted / literal
subscribe = "SUBSCRIBE" SP mailbox
tag = 1*<any ASTRING-CHAR except "+">
tag-string = astring
; <tag> represented as <astring>
tagged-ext-label = tagged-label-fchar *tagged-label-char
; Is a valid RFC 3501 "atom".
tagged-label-fchar = ALPHA / "-" / "_" / "."
tagged-label-char = tagged-label-fchar / DIGIT / ":"
tagged-ext-comp = astring /
tagged-ext-comp *(SP tagged-ext-comp) /
"(" tagged-ext-comp ")"
; Extensions that follow this general
; syntax should use nstring instead of
; astring when appropriate in the context
; of the extension.
; Note that a message set or a "number"
; can always be represented as an "atom".
; A URL should be represented as
; a "quoted" string.
tagged-ext-simple = sequence-set / number / number64
tagged-ext-val = tagged-ext-simple /
"(" [tagged-ext-comp] ")"
text = 1*(TEXT-CHAR / UTF8-2 / UTF8-3 / UTF8-4)
; Non-ASCII text can only be returned
; after ENABLE IMAP4rev2 command
TEXT-CHAR = <any CHAR except CR and LF>
time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
; Hours minutes seconds
uid = "UID" SP
(copy / move / fetch / search / store /
uid-expunge)
; Unique identifiers used instead of message
; sequence numbers
uid-expunge = "EXPUNGE" SP sequence-set
; Unique identifiers used instead of message
; sequence numbers
uid-set = (uniqueid / uid-range) *("," uid-set)
uid-range = (uniqueid ":" uniqueid)
; two uniqueid values and all values
; between these two regardless of order.
; Example: 2:4 and 4:2 are equivalent.
uniqueid = nz-number
; Strictly ascending
unsubscribe = "UNSUBSCRIBE" SP mailbox
userid = astring
UTF8-CHAR = <Defined in Section 4 of RFC 3629>
UTF8-2 = <Defined in Section 4 of RFC 3629>
UTF8-3 = <Defined in Section 4 of RFC 3629>
UTF8-4 = <Defined in Section 4 of RFC 3629>
vendor-token = "vendor." name-component
; Definition copied from RFC 2244.
; MUST be registered with IANA
zone = ("+" / "-") 4DIGIT
; Signed four-digit value of hhmm representing
; hours and minutes east of Greenwich (that is,
; the amount that the given time differs from
; Universal Time). Subtracting the timezone
; from the given time will give the UT form.
; The Universal Time zone is "+0000".
10. Author's Note ๐
okay so this document is a revision and rewrite of older docs, and it officially supersedes the protocol specs in [RFC3501], [RFC2060], [RFC1730], the unpublished IMAP2bis.TXT document, [IMAP2], and [RFC1064] ๐ง
11. Security Considerations ๐
bestie, IMAP4rev2 traffic (including all your email data!!) goes over the network in plain text unless protection gets negotiated. That means it can be eavesdropped on or messed with ๐ญ You can lock it down with the Implicit TLS port, the STARTTLS command, negotiated confidentiality protection in the AUTHENTICATE command, or some other protection mechanism ๐ซถ
11.1. TLS-Related Security Considerations ๐
this part is for both STARTTLS and the Implicit TLS port.
IMAP client and server implementations MUST comply with the relevant TLS recommendations from [RFC8314]. If recommendations or requirements in this document clash with [RFC8314], like for TLS ciphersuites, the recommendations from this document win ๐
Clients and servers MUST implement TLS 1.2 [TLS-1.2] or newer. Using TLS 1.3 [TLS-1.3] is RECOMMENDED ๐ฅ TLS 1.2 can only be used when the other side hasn't implemented TLS 1.3 yet. Also, when you're on TLS 1.2, IMAP implementations MUST implement the TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 cipher suite. This matters because it guarantees any two compliant implementations can be set up to talk to each other ๐ฆ Other TLS cipher suites recommended in RFC 7525 [RFC7525] are RECOMMENDED too: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, and TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384. All other cipher suites are OPTIONAL. Note that this is a change from Section 2.1 of [IMAP-TLS] ๐ธ
The mandatory-to-implement TLS 1.3 cipher suites are listed in Section 9.1 of [TLS-1.3] ๐ง
During the TLS negotiation [TLS-1.3] [TLS-1.2], the client MUST check that its understanding of the server hostname matches the server's identity as presented in the server Certificate message. This stops on-path attackers from pretending to be the server ๐ This procedure is described in [RFC7817].
Both the client and server MUST check the result of the STARTTLS command and the subsequent TLS [TLS-1.3] [TLS-1.2] negotiation to see whether acceptable authentication and/or privacy was achieved ๐ก๏ธ
11.2. STARTTLS Command versus Use of Implicit TLS Port โจ
for maximum backward compatibility, the client MUST implement both TLS negotiation on an Implicit TLS port AND TLS negotiation using the STARTTLS command on a cleartext port ๐
The server MUST implement TLS negotiation on an Implicit TLS port. The server SHOULD also implement IMAP on a cleartext port. If the server listens on a cleartext port, it MUST allow the STARTTLS command on it ๐
some site and firewall maintainers insist on TLS everywhere and don't want to rely on a config option in every higher-level protocol. So IMAP4rev2 clients SHOULD try both ports 993 and 143 (and both IPv4 and IPv6) at the same time by default, unless the user config or DNS SRV records [RFC6186] say otherwise. A good algorithm for doing that concurrent connect is described in [RFC8305] ๐ฆ
11.3. Client Handling of Unsolicited Responses Not Suitable for the Current Connection State ๐
ngl this one is a whole vibe. Cleartext mail transmission can let someone inject responses that confuse email clients or even crash them ๐ That can happen because of firewall config errors that strip TLS, or weak security policies in email clients that choose not to negotiate TLS in the first place. The following measures are recommended to cut down the damage:
- See Section 7.1.4 for special security considerations related to the PREAUTH response.
- Lots of server responses and response codes only mean something in the authenticated or even selected state. But nothing stops a server (or an on-path attacker) from sending those invalid responses in cleartext before the STARTTLS or AUTHENTICATE commands are issued. So before authentication, clients SHOULD ignore any responses other than CAPABILITY and server status responses (Section 7.1), and any response codes other than CAPABILITY. (Some email clients are known to process LIST responses received before authentication wrong, or FETCH responses when no mailbox is selected. Yikes ๐ญ) Clients SHOULD ignore the ALERT response code until TLS has been successfully negotiated (whether with STARTTLS or TLS on an Implicit TLS port), or a SASL security layer with confidentiality protection has been negotiated. Unless an IMAP extension explicitly allows it, when not in selected state, clients MUST ignore responses and response codes related to message and mailbox status, such as FLAGS, EXISTS, EXPUNGE, and FETCH ๐ซ
11.4. COPYUID and APPENDUID Response Codes ๐
the COPYUID and APPENDUID response codes give back info about the mailbox, and that can be sensitive if the mailbox lets the client COPY or APPEND to it but NOT SELECT or EXAMINE it ๐
So these response codes SHOULD NOT be issued if the client doesn't have access to SELECT or EXAMINE the mailbox ๐
11.5. LIST Command and Other Users' Namespace ๐ซฃ
when a LIST command has an argument with the Other Users' Namespace prefix, a server MUST NOT list users who haven't given list access to their personal mailboxes to the currently authenticated user. Otherwise it could leak who is on the server, or hand attackers a starting list of user accounts to go after ๐ค
11.6. Use of MD5 ๐งพ
the BODYSTRUCTURE FETCH data item can carry the MD5 digest of the message body in the body MD5 field (body-fld-md5 ABNF production). MD5 isn't considered a secure cryptographic hash anymore [RFC6151]. But this field is only there to show the value of the Content-MD5 header field (if the original message had one). That's just a message integrity check, not used for crypto stuff ๐ Also, other integrity mechanisms have come out since RFC 1864 [MD5] was published, and they're way more common now than Content-MD5. Two of them are the DKIM-Signature header field [RFC6376] and S/MIME signing [RFC8550] [RFC8551] ๐
11.7. Other Security Considerations ๐ง
a server error message for an AUTHENTICATE command that fails because the credentials are invalid SHOULD NOT explain why the credentials are invalid ๐คซ
Using the LOGIN command sends passwords in the clear. You can avoid that by using the AUTHENTICATE command with a [SASL] mechanism that doesn't use plaintext passwords, and by negotiating encryption first with STARTTLS or some other protection mechanism ๐
A server implementation MUST implement a configuration that, at the time of authentication, requires one of the following:
- The STARTTLS command has been negotiated, or TLS has been negotiated on an Implicit TLS port OR
- Some other mechanism that protects the session from password snooping has been provided OR
- The following measures are in place:
- a) The LOGINDISABLED capability is advertised, and [SASL] mechanisms (such as PLAIN) that use plaintext passwords are NOT advertised in the CAPABILITY list. AND
- b) The LOGIN command returns an error even if the password is correct AND
- c) The AUTHENTICATE command returns an error with all [SASL] mechanisms that use plaintext passwords, even if the password is correct.
A server error message for a failing LOGIN command SHOULD NOT say that the user name, as opposed to the password, is invalid ๐ โโ๏ธ
A server SHOULD have mechanisms in place to limit or delay failed AUTHENTICATE and LOGIN attempts โณ
A server SHOULD report any authentication failure and analyze those failed attempts for password brute-force attacks as well as password spraying attacks [NCSC]. Accounts whose passwords match well-known passwords from spraying attacks MUST be blocked, and the users on those accounts must be asked to change their passwords. Only a password with significant strength SHOULD be accepted ๐ช
More security considerations are covered in the sections that define the AUTHENTICATE and LOGIN commands (see Sections 6.2.2 and 6.2.3, respectively) ๐
12. IANA Considerations ๐
IANA has updated the "Service Names and Transport Protocol Port Numbers" registry like this:
- The registration for TCP port 143 and the matching "imap" service name now points to this document and [RFC3501].
- The registration for TCP port 993 and the matching "imaps" service name now points to this document, [RFC8314], and [RFC3501].
- UDP ports 143 and 993 have both been marked as "Reserved" in the registry.
More IANA actions are in the subsections below ๐ฆ
12.1. Updates to IMAP Capabilities Registry ๐งฉ
IMAP4 capabilities get registered by publishing a Standards Track or IESG-approved Informational or Experimental RFC. The registry lives at https://www.iana.org/assignments/imap4-capabilities ๐๏ธ
Since this specification revises the AUTH= prefix, STARTTLS, and LOGINDISABLED extensions, IANA has updated the registry entries for those 3 extensions to point to this document and [RFC3501] โจ
12.2. GSSAPI/SASL Service Name ๐๏ธ
GSSAPI/Kerberos/SASL service names get registered by publishing a Standards Track or IESG-approved Experimental RFC. The registry lives at https://www.iana.org/assignments/gssapi-service-names ๐๏ธ
IANA has updated the "imap" service name previously registered in [RFC3501] to point to both this document and [RFC3501] ๐ซถ
12.3. LIST Selection Options, LIST Return Options, and LIST Extended Data Items ๐๏ธ
[RFC5258] sets out the IANA registration procedures for LIST selection options, LIST return options, and LIST extended data items. This document doesn't change those procedures. Specifically, LIST selection options (Section 6.3.9.1) and LIST return options (Section 6.3.9.2) are registered using the procedure in Section 9 of [RFC5258] (and using the registration template from Section 9.3 of [RFC5258]). LIST extended data items are registered using the registration template from Section 9.6 of [RFC5258]) ๐
IANA has added a reference to RFC 9051 for the "OLDNAME" LIST-EXTENDED extended data item entry. This is on top of the existing reference to [RFC5465] ๐
12.4. IMAP Mailbox Name Attributes and IMAP Response Codes ๐ท๏ธ
IANA has updated the "IMAP Mailbox Name Attributes" registry to point to this document as well as [RFC3501] ๐ธ
IANA has also updated the "IMAP Response Codes" registry to point to this document as well as [RFC3501] โญ
13. References ๐
13.1. Normative References โจ
okay bestie, these are the docs the spec leans on to make its rules actually work ๐๐
- [ABNF] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, DOI 10.17487/RFC5234, January 2008,
https://www.rfc-editor.org/info/rfc5234. - [BCP178] Saint-Andre, P., Crocker, D., and M. Nottingham, "Deprecating the "X-" Prefix and Similar Constructs in Application Protocols", BCP 178, RFC 6648, June 2012.
https://www.rfc-editor.org/info/bcp178 - [CHARSET] Freed, N. and J. Postel, "IANA Charset Registration Procedures", BCP 19, RFC 2978, DOI 10.17487/RFC2978, October 2000,
https://www.rfc-editor.org/info/rfc2978. - [DISPOSITION] Troost, R., Dorner, S., and K. Moore, Ed., "Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field", RFC 2183, DOI 10.17487/RFC2183, August 1997,
https://www.rfc-editor.org/info/rfc2183. - [I18N-HDRS] Yang, A., Steele, S., and N. Freed, "Internationalized Email Headers", RFC 6532, DOI 10.17487/RFC6532, February 2012,
https://www.rfc-editor.org/info/rfc6532. - [IMAP-IMPLEMENTATION] Leiba, B., "IMAP4 Implementation Recommendations", RFC 2683, DOI 10.17487/RFC2683, September 1999,
https://www.rfc-editor.org/info/rfc2683. - [IMAP-MULTIACCESS] Gahrns, M., "IMAP4 Multi-Accessed Mailbox Practice", RFC 2180, DOI 10.17487/RFC2180, July 1997,
https://www.rfc-editor.org/info/rfc2180. - [LANGUAGE-TAGS] Alvestrand, H., "Content Language Headers", RFC 3282, DOI 10.17487/RFC3282, May 2002,
https://www.rfc-editor.org/info/rfc3282. - [LOCATION] Palme, J., Hopmann, A., and N. Shelness, "MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)", RFC 2557, DOI 10.17487/RFC2557, March 1999,
https://www.rfc-editor.org/info/rfc2557. - [MD5] Myers, J. and M. Rose, "The Content-MD5 Header Field", RFC 1864, DOI 10.17487/RFC1864, October 1995,
https://www.rfc-editor.org/info/rfc1864. - [MIME-HDRS] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text", RFC 2047, DOI 10.17487/RFC2047, November 1996,
https://www.rfc-editor.org/info/rfc2047. - [MIME-IMB] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, DOI 10.17487/RFC2045, November 1996,
https://www.rfc-editor.org/info/rfc2045. - [MIME-IMT] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types", RFC 2046, DOI 10.17487/RFC2046, November 1996,
https://www.rfc-editor.org/info/rfc2046. - [MULTIAPPEND] Crispin, M., "Internet Message Access Protocol (IMAP) - MULTIAPPEND Extension", RFC 3502, DOI 10.17487/RFC3502, March 2003,
https://www.rfc-editor.org/info/rfc3502. - [NET-UNICODE] Klensin, J. and M. Padlipsky, "Unicode Format for Network Interchange", RFC 5198, DOI 10.17487/RFC5198, March 2008,
https://www.rfc-editor.org/info/rfc5198. - [PLAIN] Zeilenga, K., Ed., "The PLAIN Simple Authentication and Security Layer (SASL) Mechanism", RFC 4616, DOI 10.17487/RFC4616, August 2006,
https://www.rfc-editor.org/info/rfc4616. - [RFC2077] Nelson, S., Parks, C., and , "The Model Primary Content Type for Multipurpose Internet Mail Extensions", RFC 2077, DOI 10.17487/RFC2077, January 1997,
https://www.rfc-editor.org/info/rfc2077. - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997,
https://www.rfc-editor.org/info/rfc2119. - [RFC2231] Freed, N. and K. Moore, "MIME Parameter Value and Encoded Word Extensions: Character Sets, Languages, and Continuations", RFC 2231, DOI 10.17487/RFC2231, November 1997,
https://www.rfc-editor.org/info/rfc2231. - [RFC3503] Melnikov, A., "Message Disposition Notification (MDN) profile for Internet Message Access Protocol (IMAP)", RFC 3503, DOI 10.17487/RFC3503, March 2003,
https://www.rfc-editor.org/info/rfc3503. - [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
https://www.rfc-editor.org/info/rfc4648. - [RFC4752] Melnikov, A., Ed., "The Kerberos V5 ("GSSAPI") Simple Authentication and Security Layer (SASL) Mechanism", RFC 4752, DOI 10.17487/RFC4752, November 2006,
https://www.rfc-editor.org/info/rfc4752. - [RFC5258] Leiba, B. and A. Melnikov, "Internet Message Access Protocol version 4 - LIST Command Extensions", RFC 5258, DOI 10.17487/RFC5258, June 2008,
https://www.rfc-editor.org/info/rfc5258. - [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322, DOI 10.17487/RFC5322, October 2008,
https://www.rfc-editor.org/info/rfc5322. - [RFC5788] Melnikov, A. and D. Cridland, "IMAP4 Keyword Registry", RFC 5788, DOI 10.17487/RFC5788, March 2010,
https://www.rfc-editor.org/info/rfc5788. - [RFC7525] Sheffer, Y., Holz, R., and P. Saint-Andre, "Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)", BCP 195, RFC 7525, DOI 10.17487/RFC7525, May 2015,
https://www.rfc-editor.org/info/rfc7525. - [RFC7817] Melnikov, A., "Updated Transport Layer Security (TLS) Server Identity Check Procedure for Email-Related Protocols", RFC 7817, DOI 10.17487/RFC7817, March 2016,
https://www.rfc-editor.org/info/rfc7817. - [RFC8081] Lilley, C., "The "font" Top-Level Media Type", RFC 8081, DOI 10.17487/RFC8081, February 2017,
https://www.rfc-editor.org/info/rfc8081. - [RFC8098] Hansen, T., Ed. and A. Melnikov, Ed., "Message Disposition Notification", STD 85, RFC 8098, DOI 10.17487/RFC8098, February 2017,
https://www.rfc-editor.org/info/rfc8098. - [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017,
https://www.rfc-editor.org/info/rfc8174. - [RFC8314] Moore, K. and C. Newman, "Cleartext Considered Obsolete: Use of Transport Layer Security (TLS) for Email Submission and Access", RFC 8314, DOI 10.17487/RFC8314, January 2018,
https://www.rfc-editor.org/info/rfc8314. - [SASL] Melnikov, A., Ed. and K. Zeilenga, Ed., "Simple Authentication and Security Layer (SASL)", RFC 4422, DOI 10.17487/RFC4422, June 2006,
https://www.rfc-editor.org/info/rfc4422. - [SCRAM-SHA-256] Hansen, T., "SCRAM-SHA-256 and SCRAM-SHA-256-PLUS Simple Authentication and Security Layer (SASL) Mechanisms", RFC 7677, DOI 10.17487/RFC7677, November 2015,
https://www.rfc-editor.org/info/rfc7677. - [TLS-1.2] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008,
https://www.rfc-editor.org/info/rfc5246. - [TLS-1.3] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
https://www.rfc-editor.org/info/rfc8446. - [UTF-7] Goldsmith, D. and M. Davis, "UTF-7 A Mail-Safe Transformation Format of Unicode", RFC 2152, DOI 10.17487/RFC2152, May 1997,
https://www.rfc-editor.org/info/rfc2152. - [UTF-8] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003,
https://www.rfc-editor.org/info/rfc3629.
13.2. Informative References ๐ธ
13.2.1. Related Protocols ๐
okay bestie, this is the squad list ๐ these are the friend protocols IMAP hangs out with, and the references that the spec leans on.
- [ANONYMOUS] Zeilenga, K., "Anonymous Simple Authentication and Security Layer (SASL) Mechanism", RFC 4505, DOI 10.17487/RFC4505, June 2006, <https://www.rfc-editor.org/info/rfc4505>.
- [CERT-555316] Carnegie Mellon University, "STARTTLS plaintext command injection vulnerability", Software Engineering Institute, CERT Coordination Center, Vulnerability Note VU#555316, September 2011, <https://www.kb.cert.org/vuls/id/555316>.
- [CHARSET-REG] IANA, "Character Set Registrations", <https://www.iana.org/assignments/charset-reg/>.
- [IMAP-DISC] Melnikov, A., Ed., "Synchronization Operations for Disconnected IMAP4 Clients", RFC 4549, DOI 10.17487/RFC4549, June 2006, <https://www.rfc-editor.org/info/rfc4549>.
- [IMAP-I18N] Newman, C., Gulbrandsen, A., and A. Melnikov, "Internet Message Access Protocol Internationalization", RFC 5255, DOI 10.17487/RFC5255, June 2008, <https://www.rfc-editor.org/info/rfc5255>.
- [IMAP-KEYWORDS-REG] IANA, "IMAP and JMAP Keywords", <https://www.iana.org/assignments/imap-jmap-keywords/>.
- [IMAP-MAILBOX-NAME-ATTRS-REG] IANA, "IMAP Mailbox Name Attributes", <https://www.iana.org/assignments/imap-mailbox-name-attributes/>.
- [IMAP-MODEL] Crispin, M., "Distributed Electronic Mail Models in IMAP4", RFC 1733, DOI 10.17487/RFC1733, December 1994, <https://www.rfc-editor.org/info/rfc1733>.
- [IMAP-URL] Melnikov, A., Ed. and C. Newman, "IMAP URL Scheme", RFC 5092, DOI 10.17487/RFC5092, November 2007, <https://www.rfc-editor.org/info/rfc5092>.
- [IMAP-UTF-8] Resnick, P., Ed., Newman, C., Ed., and S. Shen, Ed., "IMAP Support for UTF-8", RFC 6855, DOI 10.17487/RFC6855, March 2013, <https://www.rfc-editor.org/info/rfc6855>.
- [NCSC] NCSC, "Spray you, spray me: defending against password spraying attacks", May 2018, <https://www.ncsc.gov.uk/blog-post/spray-you-spray-me-defending-against-password-spraying-attacks>.
- [RFC2087] Myers, J., "IMAP4 QUOTA extension", RFC 2087, DOI 10.17487/RFC2087, January 1997, <https://www.rfc-editor.org/info/rfc2087>.
- [RFC2177] Leiba, B., "IMAP4 IDLE command", RFC 2177, DOI 10.17487/RFC2177, June 1997, <https://www.rfc-editor.org/info/rfc2177>.
- [RFC2193] Gahrns, M., "IMAP4 Mailbox Referrals", RFC 2193, DOI 10.17487/RFC2193, September 1997, <https://www.rfc-editor.org/info/rfc2193>.
- [RFC2342] Gahrns, M. and C. Newman, "IMAP4 Namespace", RFC 2342, DOI 10.17487/RFC2342, May 1998, <https://www.rfc-editor.org/info/rfc2342>.
- [RFC3348] Gahrns, M. and R. Cheng, "The Internet Message Action Protocol (IMAP4) Child Mailbox Extension", RFC 3348, DOI 10.17487/RFC3348, July 2002, <https://www.rfc-editor.org/info/rfc3348>.
- [RFC3516] Nerenberg, L., "IMAP4 Binary Content Extension", RFC 3516, DOI 10.17487/RFC3516, April 2003, <https://www.rfc-editor.org/info/rfc3516>.
- [RFC3691] Melnikov, A., "Internet Message Access Protocol (IMAP) UNSELECT command", RFC 3691, DOI 10.17487/RFC3691, February 2004, <https://www.rfc-editor.org/info/rfc3691>.
- [RFC4314] Melnikov, A., "IMAP4 Access Control List (ACL) Extension", RFC 4314, DOI 10.17487/RFC4314, December 2005, <https://www.rfc-editor.org/info/rfc4314>.
- [RFC4315] Crispin, M., "Internet Message Access Protocol (IMAP) - UIDPLUS extension", RFC 4315, DOI 10.17487/RFC4315, December 2005, <https://www.rfc-editor.org/info/rfc4315>.
- [RFC4466] Melnikov, A. and C. Daboo, "Collected Extensions to IMAP4 ABNF", RFC 4466, DOI 10.17487/RFC4466, April 2006, <https://www.rfc-editor.org/info/rfc4466>.
- [RFC4731] Melnikov, A. and D. Cridland, "IMAP4 Extension to SEARCH Command for Controlling What Kind of Information Is Returned", RFC 4731, DOI 10.17487/RFC4731, November 2006, <https://www.rfc-editor.org/info/rfc4731>.
- [RFC4959] Siemborski, R. and A. Gulbrandsen, "IMAP Extension for Simple Authentication and Security Layer (SASL) Initial Client Response", RFC 4959, DOI 10.17487/RFC4959, September 2007, <https://www.rfc-editor.org/info/rfc4959>.
- [RFC5161] Gulbrandsen, A., Ed. and A. Melnikov, Ed., "The IMAP ENABLE Extension", RFC 5161, DOI 10.17487/RFC5161, March 2008, <https://www.rfc-editor.org/info/rfc5161>.
- [RFC5182] Melnikov, A., "IMAP Extension for Referencing the Last SEARCH Result", RFC 5182, DOI 10.17487/RFC5182, March 2008, <https://www.rfc-editor.org/info/rfc5182>.
- [RFC5256] Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008, <https://www.rfc-editor.org/info/rfc5256>.
- [RFC5465] Gulbrandsen, A., King, C., and A. Melnikov, "The IMAP NOTIFY Extension", RFC 5465, DOI 10.17487/RFC5465, February 2009, <https://www.rfc-editor.org/info/rfc5465>.
- [RFC5530] Gulbrandsen, A., "IMAP Response Codes", RFC 5530, DOI 10.17487/RFC5530, May 2009, <https://www.rfc-editor.org/info/rfc5530>.
- [RFC5819] Melnikov, A. and T. Sirainen, "IMAP4 Extension for Returning STATUS Information in Extended LIST", RFC 5819, DOI 10.17487/RFC5819, March 2010, <https://www.rfc-editor.org/info/rfc5819>.
- [RFC6151] Turner, S. and L. Chen, "Updated Security Considerations for the MD5 Message-Digest and the HMAC-MD5 Algorithms", RFC 6151, DOI 10.17487/RFC6151, March 2011, <https://www.rfc-editor.org/info/rfc6151>.
- [RFC6154] Leiba, B. and J. Nicolson, "IMAP LIST Extension for Special-Use Mailboxes", RFC 6154, DOI 10.17487/RFC6154, March 2011, <https://www.rfc-editor.org/info/rfc6154>.
- [RFC6186] Daboo, C., "Use of SRV Records for Locating Email Submission/Access Services", RFC 6186, DOI 10.17487/RFC6186, March 2011, <https://www.rfc-editor.org/info/rfc6186>.
- [RFC6376] Crocker, D., Ed., Hansen, T., Ed., and M. Kucherawy, Ed., "DomainKeys Identified Mail (DKIM) Signatures", STD 76, RFC 6376, DOI 10.17487/RFC6376, September 2011, <https://www.rfc-editor.org/info/rfc6376>.
- [RFC6409] Gellens, R. and J. Klensin, "Message Submission for Mail", STD 72, RFC 6409, DOI 10.17487/RFC6409, November 2011, <https://www.rfc-editor.org/info/rfc6409>.
- [RFC6851] Gulbrandsen, A. and N. Freed, Ed., "Internet Message Access Protocol (IMAP) - MOVE Extension", RFC 6851, DOI 10.17487/RFC6851, January 2013, <https://www.rfc-editor.org/info/rfc6851>.
- [RFC7162] Melnikov, A. and D. Cridland, "IMAP Extensions: Quick Flag Changes Resynchronization (CONDSTORE) and Quick Mailbox Resynchronization (QRESYNC)", RFC 7162, DOI 10.17487/RFC7162, May 2014, <https://www.rfc-editor.org/info/rfc7162>.
- [RFC7888] Melnikov, A., Ed., "IMAP4 Non-synchronizing Literals", RFC 7888, DOI 10.17487/RFC7888, May 2016, <https://www.rfc-editor.org/info/rfc7888>.
- [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017, <https://www.rfc-editor.org/info/rfc8126>.
- [RFC8305] Schinazi, D. and T. Pauly, "Happy Eyeballs Version 2: Better Connectivity Using Concurrency", RFC 8305, DOI 10.17487/RFC8305, December 2017, <https://www.rfc-editor.org/info/rfc8305>.
- [RFC8438] Bosch, S., "IMAP Extension for STATUS=SIZE", RFC 8438, DOI 10.17487/RFC8438, August 2018, <https://www.rfc-editor.org/info/rfc8438>.
- [RFC8474] Gondwana, B., Ed., "IMAP Extension for Object Identifiers", RFC 8474, DOI 10.17487/RFC8474, September 2018, <https://www.rfc-editor.org/info/rfc8474>.
- [RFC8550] Schaad, J., Ramsdell, B., and S. Turner, "Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 4.0 Certificate Handling", RFC 8550, DOI 10.17487/RFC8550, April 2019, <https://www.rfc-editor.org/info/rfc8550>.
- [RFC8551] Schaad, J., Ramsdell, B., and S. Turner, "Secure/Multipurpose Internet Mail Extensions (S/MIME) Version 4.0 Message Specification", RFC 8551, DOI 10.17487/RFC8551, April 2019, <https://www.rfc-editor.org/info/rfc8551>.
- [SMTP] Klensin, J., "Simple Mail Transfer Protocol", RFC 5321, DOI 10.17487/RFC5321, October 2008, <https://www.rfc-editor.org/info/rfc5321>.
13.2.2. Historical Aspects of IMAP and Related Protocols ๐ง
and now the throwback era ๐ฐ๏ธโจ these are the OG docs, the ones that got IMAP to where it is today. honestly so iconic, we respect the elders ๐ซถ
- [IMAP-COMPAT] Crispin, M., "IMAP4 Compatibility with IMAP2bis", RFC 2061, DOI 10.17487/RFC2061, December 1996, <https://www.rfc-editor.org/info/rfc2061>.
- [IMAP-HISTORICAL] Crispin, M., "IMAP4 Compatibility with IMAP2 and IMAP2bis", RFC 1732, DOI 10.17487/RFC1732, December 1994, <https://www.rfc-editor.org/info/rfc1732>.
- [IMAP-OBSOLETE] Crispin, M., "Internet Message Access Protocol - Obsolete Syntax", RFC 2062, DOI 10.17487/RFC2062, December 1996, <https://www.rfc-editor.org/info/rfc2062>.
- [IMAP-TLS] Newman, C., "Using TLS with IMAP, POP3 and ACAP", RFC 2595, DOI 10.17487/RFC2595, June 1999, <https://www.rfc-editor.org/info/rfc2595>.
- [IMAP2] Crispin, M., "Interactive Mail Access Protocol: Version 2", RFC 1176, DOI 10.17487/RFC1176, August 1990, <https://www.rfc-editor.org/info/rfc1176>.
- [IMAP2BIS] Crispin, M., "INTERACTIVE MAIL ACCESS PROTOCOL - VERSION 2bis", Work in Progress, Internet-Draft, draft-ietf-imap-imap2bis-02, 29 October 1993, <https://datatracker.ietf.org/doc/html/draft-ietf-imap-imap2bis-02>.
- [RFC1064] Crispin, M., "Interactive Mail Access Protocol: Version 2", RFC 1064, DOI 10.17487/RFC1064, July 1988, <https://www.rfc-editor.org/info/rfc1064>.
- [RFC1730] Crispin, M., "Internet Message Access Protocol - Version 4", RFC 1730, DOI 10.17487/RFC1730, December 1994, <https://www.rfc-editor.org/info/rfc1730>.
- [RFC2060] Crispin, M., "Internet Message Access Protocol - Version 4rev1", RFC 2060, DOI 10.17487/RFC2060, December 1996, <https://www.rfc-editor.org/info/rfc2060>.
- [RFC3501] Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1", RFC 3501, DOI 10.17487/RFC3501, March 2003, <https://www.rfc-editor.org/info/rfc3501>.
- [RFC822] Crocker, D., "STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES", STD 11, RFC 822, DOI 10.17487/RFC0822, August 1982, <https://www.rfc-editor.org/info/rfc822>.
Appendix A. Backward Compatibility with IMAP4rev1 ๐
okay so if you want to stay friends with IMAP4rev1 ๐, you can advertise both IMAP4rev1 and IMAP4rev2 in your CAPABILITY response / response code. (a server doing this will probably also want to advertise the other IMAP4rev1 extensions that got folded into IMAP4rev2, so check Appendix E ๐
.) some IMAP4rev1 responses got cut in IMAP4rev2, but their presence won't break IMAP4rev2-only clients, so no drama ๐ซถ.
if both are advertised, an IMAP client that wants IMAP4rev2 MUST issue an ENABLE IMAP4rev2 command. no skipping this one, bestie ๐ฅ.
compared to IMAP4rev1, some request data items, corresponding response data items, and responses got removed in IMAP4rev2 ๐. see Appendix E for the full tea โ. except for the obsolete SEARCH and RECENT responses, servers advertising both would never send those removed items or responses unless an IMAPrev1 client explicitly asked for them ๐.
servers advertising both IMAP4rev1 and IMAP4rev2 MUST NOT generate UTF-8-quoted strings unless the client has issued ENABLE IMAP4rev2. look into the mechanisms in [IMAP-UTF-8] to make that happen ๐ธ.
servers advertising both, and clients trying to stay compatible with IMAP4rev1 servers, MUST be compatible with the Mailbox International Naming Convention described in Appendix A.1. ๐
also peep Appendix D for the special considerations for servers that support 63-bit body part / message sizes and want to advertise both IMAP4rev1 and IMAP4rev2 ๐ง.
A.1. Mailbox International Naming Convention for Compatibility with IMAP4rev1
support for the Mailbox International Naming Convention in this section is not required for IMAP4rev2-only clients and servers. it's only for backward compatibility with IMAP4rev1 implementations ๐.
by convention, international mailbox names in IMAP4rev1 are written using a modified version of the UTF-7 encoding described in [UTF-7] โจ. modified UTF-7 may also work in servers that implement an earlier version of this protocol ๐ฆ.
in modified UTF-7, printable US-ASCII characters represent themselves, except for & ๐. that means the octet values 0x20-0x25 and 0x27-0x7e. the & (0x26) gets represented by the 2-octet sequence &- ๐
.
all other characters (octet values 0x00-0x1f and 0x7f-0xff) are written in modified base64, with one extra twist from [UTF-7]: , is used instead of / ๐. modified base64 MUST NOT be used to represent any printing of a US-ASCII character that can represent itself. only characters inside the modified base64 alphabet are allowed in modified base64 text ๐
โโ๏ธ.
& shifts you into modified base64 and - shifts you back to US-ASCII ๐. there's no implicit shift from base64 back to US-ASCII, and null shifts (-& while in base64; note that &- while in US-ASCII means &) are not permitted ๐ซ. still, every name starts in US-ASCII and MUST end in US-ASCII. so a name ending in a non-ASCII ISO-10646 character MUST end with a - ๐ฅ.
the reason for all these tweaks is to fix these problems with UTF-7 ๐:
- UTF-7 uses the
+character for shifting. that clashes with the common use of+in mailbox names, especially USENET newsgroup names ๐ญ. - UTF-7's encoding is base64, which uses the
/character. that clashes with/being a popular hierarchy delimiter ๐. - UTF-7 prohibits the unencoded usage of
\. that clashes with\being a popular hierarchy delimiter ๐. - UTF-7 prohibits the unencoded usage of
~. that clashes with~being used by some servers as a home directory indicator ๐ก. - UTF-7 allows multiple alternate forms for the same string. in particular, printable US-ASCII characters can show up in encoded form too ๐.
modified UTF-7 is a convention, but it still sets some requirements for how servers handle any mailbox name with an embedded & character ๐ง. in particular, server implementations MUST preserve the exact form of the modified base64 portion of a modified UTF-7 name and treat that text as case sensitive, even when names are otherwise case insensitive or case folded ๐.
server implementations SHOULD verify that any mailbox name with an embedded & character, used as an argument to CREATE, is: in the correctly modified UTF-7 syntax; free of superfluous shifts; and free of any printing US-ASCII character encoded in modified base64 when that character could represent itself ๐ต๏ธโโ๏ธ. however, client implementations MUST NOT depend on the server doing this, and they SHOULD NOT try to create a mailbox name with an embedded & character unless it follows the modified UTF-7 syntax ๐.
server implementations that export a mail store that doesn't follow the modified UTF-7 convention MUST convert any mailbox name that contains non-ASCII characters or the & character to modified UTF-7 ๐.
โจ examples time โจ
for example, here's a mailbox name mixing English, Chinese, and Japanese text: ~peter/mail/&U,BTFw-/&ZeVnLIqe- ๐.
another example: the string &Jjo! is not a valid mailbox name, because it doesn't shift back to US-ASCII before the ! ๐
. the correct form is &Jjo-!. and &U,BTFw-&ZeVnLIqe- isn't allowed because it has a superfluous shift ๐. the correct form is &U,BTF2XlZyyKng- ๐.
Appendix B. Backward Compatibility with BINARY Extension
IMAP4rev2 picks up a subset of the BINARY extension [RFC3516] ๐ฆ. it adds the extra FETCH items (BINARY, BINARY.PEEK, and BINARY.SIZE) but doesn't bring over the extensions to the APPEND command ๐
โโ๏ธ. if you implement full [RFC3516] functionality, you also need to advertise the BINARY capability in your CAPABILITY response / response code โจ.
Appendix C. Backward Compatibility with LIST-EXTENDED Extension
IMAP4rev2 has most of the goodies from the LIST-EXTENDED extension [RFC5258] ๐. the syntax for multiple mailbox patterns isn't supported in IMAP4rev2, unless the LIST-EXTENDED capability is also advertised in the CAPABILITY response / response code ๐ธ.
Appendix D. 63-Bit Body Part and Message Sizes
IMAP4rev2 raises the body part and message sizes that servers can support from 32 to 63 bits ๐. servers don't have to support 63-bit body parts / message sizes, but clients have to expect them ๐ง.
since IMAP4rev1 didn't support 63-bit body part / message sizes, there's an interop issue for 63-bit-capable servers/mailboxes that both IMAP4rev1 and IMAP4rev2 email clients can reach ๐ฌ. IMAP4rev1 can't retrieve the full content of messages bigger than 4 Gb, so those servers either need to replace messages over 4 Gb with smaller ones, or hide them from IMAP4rev1 clients ๐. this document doesn't prescribe any implementation strategy for dealing with this ๐คทโโ๏ธ.
Appendix E. Changes from RFC 3501 / IMAP4rev1
here's the summary of what changed since RFC 3501 ๐:
- Support for 64-bit message and body part sizes ๐ช.
- Folded in IMAP NAMESPACE [RFC2342], UNSELECT [RFC3691], UIDPLUS [RFC4315], ESEARCH [RFC4731], SEARCHRES [RFC5182], ENABLE [RFC5161], IDLE [RFC2177], SASL-IR [RFC4959], LIST-EXTENDED [RFC5258], LIST-STATUS [RFC5819], MOVE [RFC6851], and LITERAL-extensions [RFC7888] ๐. also folded in IMAP ABNF extensions [RFC4466], response codes [RFC5530], the FETCH side of the BINARY extension [RFC3516], and the list of new mailbox attributes from SPECIAL-USE [RFC6154] ๐.
- Added
STATUS SIZE[RFC8438] andSTATUS DELETED๐. - The
SEARCHcommand now requires returning the ESEARCH response (theSEARCHresponse is now deprecated) ๐. - Clarified which SEARCH keys have to use substring match and which don't ๐.
- Clarified that the server should decode parameter value continuations as described in [RFC2231]. this requirement was hidden in [RFC2231] itself ๐ต๏ธโโ๏ธ.
- Clarified that the
COPYUIDresponse code is returned for bothMOVEandUID MOVE๐ . - Tightened the requirements about
COPY/MOVEcommands not creating a target mailbox. they're also required to return theTRYCREATEresponse code if the target mailbox doesn't exist and can be created ๐ฅ. - Added the
CLOSEDresponse code from [RFC7162].SELECT/EXAMINEwhen a mailbox is already selected now requires aCLOSEDresponse code to be returned ๐. SELECT/EXAMINEare now required to return an untaggedLISTresponse ๐ธ.- The
UNSEENresponse code onSELECT/EXAMINEis now deprecated ๐ฅฒ. - The
RECENTresponse onSELECT/EXAMINE, the\Recentflag,RECENTSTATUS, andSEARCH NEWitems are now deprecated ๐. - Clarified that the server doesn't need to send a new
PERMANENTFLAGSresponse code when a new keyword was successfully added and the server advertised\*earlier for the same mailbox โจ. - For future extensibility, the ABNF for
tagged-ext-simplewas extended to allow for a bare number64 ๐ง. - Added a SHOULD level requirement on IMAP servers to support the
$MDNSent,$Forwarded,$Junk,$NonJunk, and$Phishingkeywords ๐. - Mailbox names and message headers now allow for UTF-8 ๐. support for modified UTF-7 in mailbox names is not required, unless compatibility with IMAP4rev1 is desired ๐ฆ.
- Removed the
CHECKcommand. clients should useNOOPinstead ๐ โโ๏ธ. - The
RFC822,RFC822.HEADER, andRFC822.TEXTFETCH data items were deprecated. clients should use the correspondingBODY[]variants instead ๐. - The
LSUBcommand was deprecated. clients should useLIST (SUBSCRIBED)instead ๐. - The
IDLEcommand can now return updates not related to the currently selected mailbox state ๐. - All unsolicited FETCH updates are required to include UID ๐.
- Clarified that client implementations MUST ignore response codes that they do not recognize. (Changed from a SHOULD to a MUST.) ๐ซถ this one's a big deal bestie ๐ .
- The
resp-textABNF non-terminal was updated to allow for empty text ๐ธ. - After
ENABLE, IMAP4rev2 human-readable response text can include non-ASCII encoded in UTF-8 ๐. - Updated to use modern TLS-related recommendations as per [RFC7525], [RFC7817], and [RFC8314] ๐.
- Added warnings about the use of ALERT response codes and the PREAUTH response โ ๏ธ.
- Replaced the DIGEST-MD5 SASL mechanism with SCRAM-SHA-256. DIGEST-MD5 was deprecated ๐.
- Clarified that any command received from the client resets the server autologout timer โฐ.
- Revised the IANA registration procedure for IMAP extensions and removed the "X" convention in accordance with [BCP178] ๐งพ.
- Loosened requirements on servers when closing connections, to be more aligned with existing practices ๐ฆโจ.
Appendix F. Other Recommended IMAP Extensions ๐
okay so these extensions are recommended for all IMAP clients and servers ๐ They seriously cut down on bandwidth and/or the number of round trips IMAP needs in certain situations. ๐ฆ But the EXTRA WG decided that making them required as part of IMAP4rev2 would set the bar too high for brand-new implementations ๐ญ And don't read anything into it if an IMAP extension isn't on this list. It's not deficient, and it's not "not recommended" for IMAP4rev2. It's just not on this list ๐
- Quick Mailbox Resynchronization (QRESYNC) and CONDSTORE extensions [RFC7162]. These make discovering changes to IMAP mailboxes way more efficient, at the expense of storing a bit more state โจ
- OBJECTID extension [RFC8474] helps preserve the IMAP client cache when messages are moved/copied or mailboxes are renamed. ๐ง
Acknowledgements ๐ซถ
Earlier draft versions of this document were edited by Mark Crispin. Sadly, he is no longer available to help with this work ๐ญ The editors of this revision are hoping that Mark would have approved ๐
Chris Newman contributed text on I18N and the use of UTF-8 in messages and mailbox names. ๐
Thank you to Tony Hansen for helping with the index generation ๐ Thank you also to Murray Kucherawy, Timo Sirainen, Bron Gondwana, Stephan Bosch, Robert Sparks, Arnt Gulbrandsen, Benjamin Kaduk, Daniel Migaul, Roman Danyliw, and รric Vyncke for extensive feedback. Iconic squad ๐
This document incorporates text from [RFC2342] (by Mike Gahrns and Chris Newman), [RFC3516] (by Lyndon Nerenberg), [RFC4315] (by Mark Crispin), [RFC4466] (by Cyrus Daboo), [RFC4731] (by Dave Cridland), [RFC4959] (by Rob Siemborski and Arnt Gulbrandsen), [RFC5161] (by Arnt Gulbrandsen), [RFC5465] (by Arnt Gulbrandsen and Curtis King), [RFC5530] (by Arnt Gulbrandsen), [RFC5819] (by Timo Sirainen), [RFC6154] (by Jamie Nicolson), [RFC6851] (by Arnt Gulbrandsen and Ned Freed), and [RFC8438] (by Stephan Bosch). The work of those authors and editors is so appreciated ๐ Note that the editors of this document were redacted from the above list ๐
The CHILDREN return option was originally proposed by Mike Gahrns and Raymond Cheng in [RFC3348]. Most of the information in Section 6.3.9.5 is taken directly from their original specification [RFC3348] ๐ธ
Thank you to Damian Poddebniak, Fabian Ising, Hanno Boeck, and Sebastian Schinzel for pointing out that the ENABLE command should be a member of "command-auth" and not "command-any" ABNF production. You also pointed out security issues associated with ALERT, PREAUTH, and other responses received before authentication. Security stuff is serious, bestie ๐ญ๐ฅ
Index ๐
$ + - \ A B C D E F H I K L M N O P R S T U
$
$Forwarded (predefined flag)
Section 2.3.2
$Junk (predefined flag)
Section 2.3.2
$MDNSent (predefined flag)
Section 2.3.2
$NotJunk (predefined flag)
Section 2.3.2
$Phishing (predefined flag)
Section 2.3.2, Paragraph 6.10.1
+
+FLAGS <flag list>
Section 6.4.6
+FLAGS.SILENT <flag list>
Section 6.4.6
-
-FLAGS <flag list>
Section 6.4.6
-FLAGS.SILENT <flag list>
Section 6.4.6
\
\All (mailbox name attribute)
Section 7.3.1
\Answered (system flag)
Section 2.3.2
\Archive (mailbox name attribute)
Section 7.3.1
\Deleted (system flag)
Section 2.3.2
\Draft (system flag)
Section 2.3.2
\Drafts (mailbox name attribute)
Section 7.3.1
\Flagged (mailbox name attribute)
Section 7.3.1
\Flagged (system flag)
Section 2.3.2
\HasChildren (mailbox name attribute)
Section 7.3.1
\HasNoChildren (mailbox name attribute)
Section 7.3.1
\Junk (mailbox name attribute)
Section 7.3.1
\Marked (mailbox name attribute)
Section 7.3.1
\Noinferiors (mailbox name attribute)
Section 7.3.1
\NonExistent (mailbox name attribute)
Section 7.3.1, Paragraph 4.2.1
\Noselect (mailbox name attribute)
Section 7.3.1
\Recent (system flag)
Section 2.3.2
\Remote (mailbox name attribute)
Section 7.3.1
\Seen (system flag)
Section 2.3.2
\Sent (mailbox name attribute)
Section 7.3.1
\Subscribed (mailbox name attribute)
Section 7.3.1
\Trash (mailbox name attribute)
Section 7.3.1
\Unmarked (mailbox name attribute)
Section 7.3.1
A
ALERT (response code)
Section 7.1
ALL (fetch item)
Section 6.4.5
ALL (search key)
Section 6.4.4
ALL (search result option)
Section 6.4.4, Paragraph 6.6.1
ALL (search return item name)
Section 7.3.4, Paragraph 7.6.1
ALREADYEXISTS (response code)
Section 7.1, Paragraph 4.4.1
ANSWERED (search key)
Section 6.4.4
APPEND (command)
Section 6.3.12
APPENDUID (response code)
Section 7.1, Paragraph 4.6.1
AUTHENTICATE (command)
Section 6.2.2
AUTHENTICATIONFAILED (response code)
Section 7.1, Paragraph 4.8.1
AUTHORIZATIONFAILED (response code)
Section 7.1, Paragraph 4.10.1
B
BAD (response)
Section 7.1.3
BADCHARSET (response code)
Section 7.1
BCC <string> (search key)
Section 6.4.4
BEFORE <date> (search key)
Section 6.4.4
BINARY.PEEK[<section-binary>]<<partial>> (fetch item)
Section 6.4.5
BINARY.SIZE[<section-binary>] (fetch item)
Section 6.4.5, Paragraph 9.6.1
BINARY.SIZE[<section-binary>] (fetch result)
Section 7.5.2, Paragraph 4.4.1
BINARY[<section-binary>]<<number>> (fetch result)
Section 7.5.2, Paragraph 4.2.1
BINARY[<section-binary>]<<partial>> (fetch item)
Section 6.4.5, Paragraph 9.2.1
BODY (fetch item)
Section 6.4.5
BODY (fetch result)
Section 7.5.2
BODY <string> (search key)
Section 6.4.4
BODY.PEEK[<section>]<<partial>> (fetch item)
Section 6.4.5
BODYSTRUCTURE (fetch item)
Section 6.4.5
BODYSTRUCTURE (fetch result)
Section 7.5.2, Paragraph 4.10.1
BODY[<section>]<<origin octet>> (fetch result)
Section 7.5.2, Paragraph 4.8.1
BODY[<section>]<<partial>> (fetch item)
Section 6.4.5, Paragraph 9.10.1
BYE (response)
Section 7.1.5
Body Structure (message attribute)
Section 2.3.6
C
CANNOT (response code)
Section 7.1, Paragraph 4.14.1
CAPABILITY (command)
Section 6.1.1
CAPABILITY (response code)
Section 7.1
CAPABILITY (response)
Section 7.2.2
CC <string> (search key)
Section 6.4.4
CLIENTBUG (response code)
Section 7.1, Paragraph 4.18.1
CLOSE (command)
Section 6.4.1
CLOSED (response code)
Section 7.1, Paragraph 4.20.1
CONTACTADMIN (response code)
Section 7.1, Paragraph 4.22.1
COPY (command)
Section 6.4.7
COPYUID (response code)
Section 7.1, Paragraph 4.24.1
CORRUPTION (response code)
Section 7.1, Paragraph 4.26.1
COUNT (search result option)
Section 6.4.4
COUNT (search return item name)
Section 7.3.4
CREATE (command)
Section 6.3.4
D
DELETE (command)
Section 6.3.5
DELETED (search key)
Section 6.4.4
DELETED (status item)
Section 6.3.11
DRAFT (search key)
Section 6.4.4
E
ENABLE (command)
Section 6.3.1
ENVELOPE (fetch item)
Section 6.4.5
ENVELOPE (fetch result)
Section 7.5.2, Paragraph 4.42.1
ESEARCH (response)
Section 7.3.4
EXAMINE (command)
Section 6.3.3
EXPIRED (response code)
Section 7.1, Paragraph 4.28.1
EXPUNGE (command)
Section 6.4.3
EXPUNGE (response)
Section 7.5.1
EXPUNGEISSUED (response code)
Section 7.1, Paragraph 4.30.1
Envelope Structure (message attribute)
Section 2.3.5
F
FAST (fetch item)
Section 6.4.5
FETCH (command)
Section 6.4.5
FETCH (response)
Section 7.5.2
FLAGGED (search key)
Section 6.4.4
FLAGS (fetch item)
Section 6.4.5
FLAGS (fetch result)
Section 7.5.2
FLAGS (response)
Section 7.3.5
FLAGS <flag list> (store command data item)
Section 6.4.6
FLAGS.SILENT <flag list> (store command data item)
Section 6.4.6
FROM <string> (search key)
Section 6.4.4
FULL (fetch item)
Section 6.4.5
Flags (message attribute)
Section 2.3.2
H
HASCHILDREN (response code)
Section 7.1, Paragraph 4.32.1
HEADER (part specifier)
Section 6.4.5.1, Paragraph 5
HEADER <field-name> <string> (search key)
Section 6.4.4
HEADER.FIELDS (part specifier)
Section 6.4.5.1, Paragraph 5
HEADER.FIELDS.NOT (part specifier)
Section 6.4.5.1, Paragraph 5
I
IDLE (command)
Section 6.3.13
INTERNALDATE ( fetch item)
Section 6.4.5
INTERNALDATE (fetch result)
Section 7.5.2
INUSE (response code)
Section 7.1, Paragraph 4.34.1
Internal Date (message attribute)
Section 2.3.3
K
KEYWORD <flag> (search key)
Section 6.4.4
Keyword (type of flag)
Section 2.3.2, Paragraph 4
L
LARGER <n> (search key)
Section 6.4.4
LIMIT (response code)
Section 7.1, Paragraph 4.36.1
LIST (command)
Section 6.3.9
LIST (response)
Section 7.3.1
LOGOUT (command)
Section 6.1.3
M
MAX (search result option)
Section 6.4.4, Paragraph 6.4.1
MAX (search return item name)
Section 7.3.4, Paragraph 7.4.1
MAY (specification requirement term)
Section 1.2
MESSAGES (status item)
Section 6.3.11
MIME (part specifier)
Section 6.4.5.1, Paragraph 7
MIN (search result option)
Section 6.4.4, Paragraph 6.2.1
MIN (search return item name)
Section 7.3.4, Paragraph 7.2.1
MOVE (command)
Section 6.4.8
MUST (specification requirement term)
Section 1.2
MUST NOT (specification requirement term)
Section 1.2
Message Sequence Number (message attribute)
Section 2.3.1.2
N
Okay that's the index so far, and we're going right on from here in the next part ๐
NAMESPACE (command)
Section 6.3.10
NAMESPACE (response)
Section 7.3.2
NO (response)
Section 7.1.2
NONEXISTENT (response code)
Section 7.1, Paragraph 4.38.1
NOOP (command)
Section 6.1.2
NOPERM (response code)
Section 7.1, Paragraph 4.40.1
NOT <search-key> (search key)
Section 6.4.4
NOT RECOMMENDED (specification requirement term)
Section 1.2
O
OK (response)
Section 7.1.1
ON <date> (search key)
Section 6.4.4
OPTIONAL (specification requirement term)
Section 1.2; Section 1.2
OR <search-key1> <search-key2> (search key)
Section 6.4.4
OVERQUOTA (response code)
Section 7.1, Paragraph 4.42.1
P
PARSE (response code)
Section 7.1
PERMANENTFLAGS (response code)
Section 7.1, Paragraph 4.46.1
PREAUTH (response)
Section 7.1.4
PRIVACYREQUIRED (response code)
Section 7.1, Paragraph 4.48.1
Permanent Flag (class of flag)
Section 2.3.2, Paragraph 9
Predefined keywords
Section 2.3.2, Paragraph 5
R
READ-ONLY (response code)
Section 7.1
READ-WRITE (response code)
Section 7.1
RECOMMENDED (specification requirement term)
Section 1.2
RENAME (command)
Section 6.3.6
REQUIRED (specification requirement term)
Section 1.2
RFC822.SIZE (fetch item)
Section 6.4.5
RFC822.SIZE (fetch result)
Section 7.5.2
RFC822.SIZE (message attribute)
Section 2.3.4
S
SAVE (search result option)
Section 6.4.4, Paragraph 6.10.1
SEARCH (command)
Section 6.4.4
SEEN (search key)
Section 6.4.4
SELECT (command)
Section 6.3.2
SENTBEFORE <date> (search key)
Section 6.4.4
SENTON <date> (search key)
Section 6.4.4
SENTSINCE <date> (search key)
Section 6.4.4
SERVERBUG (response code)
Section 7.1, Paragraph 4.54.1
SHOULD (specification requirement term)
Section 1.2
SHOULD NOT (specification requirement term)
Section 1.2
SINCE <date> (search key)
Section 6.4.4
SIZE (status item)
Section 6.3.11
SMALLER <n> (search key)
Section 6.4.4
STARTTLS (command)
Section 6.2.1
STATUS (command)
Section 6.3.11
STATUS (response)
Section 7.3.3
STORE (command)
Section 6.4.6
SUBJECT <string> (search key)
Section 6.4.4
SUBSCRIBE (command)
Section 6.3.7
Session Flag (class of flag)
Section 2.3.2, Paragraph 9
System Flag (type of flag)
Section 2.3.2, Paragraph 2
T
TEXT (part specifier)
Section 6.4.5.1, Paragraph 5
TEXT <string> (search key)
Section 6.4.4
TO <string> (search key)
Section 6.4.4
TRYCREATE (response code)
Section 7.1
U
UID (command)
Section 6.4.9
UID (fetch item)
Section 6.4.5
UID (fetch result)
Section 7.5.2
UID <sequence set> (search key)
Section 6.4.4
UIDNEXT (response code)
Section 7.1
UIDNEXT (status item)
Section 6.3.11
UIDNOTSTICKY (response code)
Section 7.1, Paragraph 4.60.1
UIDVALIDITY (response code)
Section 7.1
UIDVALIDITY (status item)
Section 6.3.11
UNANSWERED (search key)
Section 6.4.4
UNAVAILABLE (response code)
Section 7.1, Paragraph 4.64.1
UNDELETED (search key)
Section 6.4.4
UNDRAFT (search key)
Section 6.4.4
UNFLAGGED (search key)
Section 6.4.4
UNKEYWORD <flag> (search key)
Section 6.4.4
UNKNOWN-CTE (response code)
Section 7.1
UNSEEN (search key)
Section 6.4.4
UNSEEN (status item)
Section 6.3.11
UNSELECT (command)
Section 6.4.2
UNSUBSCRIBE (command)
Section 6.3.8
Unique Identifier (UID) (message attribute)
Section 2.3.1.1
Authors' Addresses โจ
Alexey Melnikov (editor)
Isode Ltd
14 Castle Mews
Hampton, Middlesex
TW12 2NP
United Kingdom
Email: Alexey.Melnikov@isode.com
Barry Leiba (editor)
Futurewei Technologies
Email: barryleiba@computer.org
URI: http://internetmessagingtechnology.org/
๐ฆ where this page comes from
- ietf: rfc9051 2021-08
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms