RFC 1203
Interactive Mail Access Protocol: Version 3
INTERACTIVE MAIL ACCESS PROTOCOL - VERSION 3 ๐
okay bestie, the title block is giving "who wrote this, when, and what did it replace" ๐ . It's RFC 1203, written by J. Rice from Stanford ๐ง, dated February 1991. It obsoletes RFC 1064, which is the IMAP2 spec ๐ธ. The Status section says it's a standard for the SUMEX-AIM community and an Experimental Protocol for the Internet community โจ.
Status of this Memo โจ
this RFC suggests a way for workstations to access mail dynamically from a mailbox server (the "repository") ๐ฌ. it specifies a standard for the SUMEX-AIM community and an Experimental Protocol for the Internet community ๐งช. they're asking for discussion and suggestions for improvement, so speak up ๐ฃ๏ธ. for the standardization state and status of this protocol, check the current edition of the "IAB Official Protocol Standards" ๐. distribution of this memo is unlimited ๐.
Scope ๐
okay so this is a modified version of RFC 1064, which defines IMAP2 ๐. it was written specifically as a counter proposal to RFC 1176, which itself proposes modifications to IMAP2 ๐ค. ngl the drama is real: RFC 1176 was made without internal consultation with the IMAP community ๐. so the authors feel like they have to push back, because if they don't act, RFC 1176 becomes a de facto standard ๐ญ. the reasons mostly fall into these categories:
- IMAP2 is insufficiently powerful for a number of server/client interactions that they think matter. RFC 1176 negligibly enhances IMAP2 ๐ฅฑ.
- IMAP2 makes what they believe is an erroneous definition of unsolicited vs. solicited data. IMAP3, as specified here, tries to fix that. RFC 1176 makes no effort to remedy these problems ๐ .
- RFC 1176 explicitly modified the intent of RFC 1064 by letting the server make assumptions about the client's caching architecture. they think this is a grave error, so they don't support it here ๐ซ.
- RFC 1176 specifies a bunch of "optional" features without a suitable metaprotocol for servers and clients to negotiate over the features they implement. this proposal adds a mechanism so both sides can unambiguously know which features are usable by each party ๐ค.
- RFC 1176 pays lip-service to being network protocol independent and actually assumes TCP/IP. neither RFC 1064 nor this proposal makes that assumption ๐ซ .
there are plenty of other detailed objections to RFC 1176, but the list above shows how strongly the authors believe in mailbox abstraction level mail protocols ๐. after a couple of years of using IMAP2 under RFC 1064, they feel they understand the issues well enough to take the next step ๐ฆ.
this next step matters because mail systems and user interface development are moving super fast ๐. for IMAP to not die in its infancy, IMAP has to be ready to respond to emerging ISO and RFC standards in mail, like multi-media mail ๐๏ธ. RFC 1176 gives a very small bump in functionality over RFC 1064 but also adds a bunch of bugs, which would be detrimental to the IMAP cause ๐. so, here's the proposed definition for IMAP3 ๐.
Compatibility notes ๐
they tried to make upwards compatible changes wherever possible when revising IMAP2 into IMAP3 ๐. some spots had to change incompatibly anyway, to compensate for ambiguities in IMAP2 as defined by RFC 1064, or for behaviour that turned out to be undesirable in the light of experience ๐ง.
the goal is that existing IMAP2 clients should still be supported, and that, at least for the foreseeable future, all IMAP3 servers will support IMAP2 behaviour as their default mode ๐ซถ.
the major differences between this proposal, RFC 1176, and RFC 1064 are:
- this proposal specifies a difference between "solicited" and "unsolicited" data sent from the server ๐. data the server is required to send as the result of a request is solicited, and it carries the same tag as the request that provoked it ๐ท๏ธ. any data the server sends that the protocol doesn't require is unsolicited and carries the special
*tag โจ. RFC 1176 keeps the original RFC 1064 terminology, which calls all of that server data "unsolicited" even when it's actually solicited ๐. - this proposal introduces the experimental concept of distinguishing Generic, Canonical and Concrete keys ๐งช. that lets the mailbox be viewed as a relational database indexed by these keys ๐๏ธ. the idea is to help IMAP evolve away from its current reliance on RFC 822 ๐ฑ. RFC 1176 doesn't have a unifying model like this ๐ฌ.
- the SEARCH command has been changed so you can run multiple simultaneous searches, and so the server can send unsolicited search messages ๐. that's essential for smarter servers that process commands asynchronously, possibly delaying searches a lot over slow backing storage media, for example ๐ข. it also lets servers send unsolicited search messages that can tell the client about interesting patterns, like new and unseen mail ๐ฉ.
- this proposal introduces a specific protocol for negotiating protocol versions and server features ๐ค. this matters because it lets client/server pairs agree on what behaviour is really available ๐ก. RFC 1176 introduces "optional" commands, which are somewhat analogous to the "feature-introduced" commands here. the main difference is that in RFC 1176, a client has no way to discover the set of optional commands, and no way to check whether a specific command is actually supported, because RFC 1176 requires the
BADresponse when a feature isn't supported ๐ต. so the client can't tell why the attempted command didn't work ๐คทโโ๏ธ. that also means a client can't disable certain user commands or make them invisible on menus when they aren't supported, since the only way to find out is to try running the command ๐. - this proposal introduces a mechanism for clients to create and delete user flags (keywords) ๐ณ๏ธโ๐. neither RFC 1176 nor RFC 1064 supports this, so the user has to add keys manually on the server, generally by editing some form of "init" file ๐ฉ.
- RFC 1064 has no mechanism for determining whether a mailbox is readonly ๐. RFC 1176 introduces a non-enforced convention of encoding the readonly status of a mailbox in the comment field of the
OKresponse toSELECT๐ค. that isn't regular with the rest of the protocol, where the comment field is used for no purpose other than documentation ๐. this proposal adds specific protocol additions for dynamically determining and modifying the readonly/readwrite status of mailboxes ๐.
Introduction ๐ซ
the intent of the Interactive Mail Access Protocol, Version 3 (IMAP3), is to let a possibly unreliable workstation or similar machine access electronic mail from a reliable mailbox server, and to do it efficiently โก.
although IMAP3 is different from POP2 (RFC 937) in many ways, you can think of it as a functional superset of POP2 ๐ง. the POP2 RFC was used as the model for this RFC, and there was a good reason: RFC 937 deals with an identical problem, so it was desirable to have a basis for comparison ๐.
like POP2, IMAP3 specifies a means of accessing stored mail and not of posting mail ๐ฎ. posting is handled by a mail transfer protocol like SMTP (RFC 821) ๐. a comparison with the DMSP protocol of PCMAIL can be found at the end of the "System Model and Philosophy" section ๐.
this protocol assumes a reliable data stream, like the one TCP or any similar protocol provides ๐. when TCP is used, the IMAP server listens on port 220 ๐. when CHAOS is used, the IMAP server listens for the logical contact name "IMAP3" ๐งธ.
communication in IMAP is defined to use the ASCII character interpretation of data ๐ค. communication using other conventions may be possible if some servers select features for it ๐๏ธ.
System Model and Philosophy ๐ง
electronic mail is a primary means of communication for the widely spread SUMEX-AIM community ๐. distributed workstations are forcing a significant rethink of how that mail gets managed ๐ฅ๏ธ. with mainframes, each user tends to receive and process mail on the computer they use most of the time, their "primary host" ๐ . when an independent workstation shows up in front of someone, their first instinct is to start receiving mail at the workstation, and plenty of vendors have built facilities to do exactly that ๐โโ๏ธ. however, this approach has some real downsides ๐:
- workstations (especially Lisp workstations) have a software design that gives the user at the console full control of every aspect of the system ๐ฎ. so background tasks, like receiving mail, could be kept from running for long periods, either because the user is using all of the machine's resources, or because the user has (maybe accidentally) changed the environment in a way that stops mail reception ๐ฌ. that could lead to repeated failed delivery attempts by outside agents ๐ญ.
- the hardware failure of a single workstation could keep its user "off the air" for a considerable time, since repairing individual workstation units might be delayed ๐ ๏ธ. with the growing number of workstations spread throughout office environments, quick repair isn't assured ๐ค, whereas a centralized mainframe is generally repaired very soon after failure ๐ช.
- okay bestie, reason #3 is where it gets messy ๐ญ It's way harder to keep track of mailing addresses when every single person is tied to their own separate machine ๐. Think about juggling a huge pile of postal addresses or phone numbers, especially if there wasn't one address or phone number for an organization that could reach anybody in it ๐ข. Back on the ARPANET, sending email meant remembering a name plus one of several "hosts" (machines) whose name matched the organization you worked for. That was totally fine when most orgs had just one central host, but it's giving outdated today ๐ unless "host" gets redefined to mean an organizational entity instead of one particular machine ๐ซถ.
- Okay, reason #4 is a whole mood ๐ช๏ธ It is super hard to keep a bunch of different workstations running properly with complicated mailing protocols. That makes it tough to move forward as electronic communication gets better and new standards show up โจ. Every system has to deal with receiving incoming mail, routing and delivering outgoing mail, formatting, storing, and keeping mailboxes stable across a whole pile of possible filing and mailing protocols ๐ฅด.
So yeah ๐ the workstation can totally be called an Internet host, since it implements IP, but it should not be treated as the thing that holds the user's mailbox ๐ญ. Instead, a mail server machine (sometimes called a "repository") should hold the mailbox, and the workstation (from here on, a "client") should access it through mail transactions ๐ฌ. Since nobody's poking around on the mail server directly ๐, it can get high software reliability pretty easily. And since it's a shared resource, it could hit high hardware reliability too, maybe through redundancy ๐ก๏ธ. The mail server can be reached from basically anywhere ๐, so you can read mail across campus, town, or even the whole country, using clients that are getting more and more common ๐ฑ. Also, the same person can open their mailbox from different clients at different times, and multiple people can get into the same mailbox at once ๐ฏ.
The mail server is basically the middleman ๐ค between users, data storage, and other mailers. The mail access protocol is what gets messages, reads and changes message properties, and manages mailboxes ๐ฅ. This is different from some setups (like Unix mail over NFS ๐๏ธ) because the mail access protocol handles all message manipulation. That means the user and the client know nothing about how the data storage actually works ๐ โโ๏ธ. Which means the mail server can use storage however works best to organize mail in that environment ๐ง , without stressing about storage representation compatibility across different machines ๐ .
When defining a mail access protocol, remember that the client and server together make up a macrosystem ๐ค. So it should be possible to use the strengths of both while covering for each other's weak spots ๐ช. It's also desirable to leave room to grow beyond the ancient text-only RFC 822 protocol ๐ตโจ. Unlike POP2, IMAP3 has tons of features for remote searching and parsing of messages on the server ๐. The server can run a free text search across the whole mailbox (optionally combined with other searches) and just hand the results to the client ๐ฏ. The client doesn't have to download the entire mailbox and search through it itself ๐. And since the server can parse a message remotely into a structured, standard-format "envelope" ๐จ, a client can show envelope info and do stuff like REPLY without knowing how to parse RFC 822 headers, etc. ๐ฅณ
Plus, IMAP3 has several tools for managing a mailbox beyond POP2's simple "delete message" ๐๏ธ. Even with all that, IMAP3 is still pretty simple ๐ฅฐ. Servers should implement the full set of IMAP3 functions, but a simple client can be written that uses IMAP3 pretty much like a POP2 client.
IMAP3 is different from the DMSP protocol of PCMAIL (RFC 1056) in a more fundamental way ๐งฉ, because the architectures of IMAP and PCMAIL are different. PCMAIL is either online ("interactive mode") or offline ("batch mode") ๐ถ. IMAP is mainly online, where real-time and simultaneous mail access were seen as super important โก.
In PCMAIL, there is a long-term client/server relationship in which some mailbox state is preserved on the client ๐๏ธ. There is a registration of clients used by a particular user, and the client keeps a set of "descriptors" for each message that summarize the message. The server and client synchronize their states when the DMSP connection starts up. And if a client has not accessed the server for a while, the client does a complete reset (reload) of its state from the server ๐.
In IMAP, the client/server relationship lasts only for the duration of the IMAP3 connection โณ. All mailbox state is maintained on the server, and there is no registration of clients ๐ โโ๏ธ. The function of a descriptor is handled by a structured representation of the message "envelope" ๐. This structure makes it unnecessary for a client to know anything about RFC 822 parsing. There is no synchronization, since the client does not remember state between IMAP3 connections. That's not a problem, because in general the client never needs the entire state of the mailbox in a single session. So there isn't much overhead in fetching the state information that is needed, as it is needed ๐งโโ๏ธ.
There are also some functional differences between IMAP3 and DMSP ๐. DMSP has functions for sending messages, printing messages, and changing passwords, all of which are done outside of IMAP3. DMSP has 16 binary flags, of which 8 are defined by the system. IMAP has flag names: there are currently 5 defined system flag names, plus a facility for some number (29 in the current implementations) of user flag names ๐ท๏ธ. IMAP3 has a sophisticated message search facility in the server, so it can identify interesting messages based on dates, addresses, flag status, or textual contents. The client doesn't have to be forced to fetch this data for every message ๐ฏ.
It was felt that maintaining state on the client is only advantageous when the client is used by a single user, or when there is some means on the client to restrict access to another user's data ๐. It can be a serious disadvantage in an environment where multiple users routinely use the same client, the same user routinely uses different clients, and there are no access restrictions on the client ๐ฌ. It was also observed that most user mail access is to a relatively small set of "interesting" messages. Those were either "new" mail or mail based on some user-selected criteria ๐. So IMAP3 was designed to easily identify those "interesting" messages, so the client could fetch the state of those messages and skip the ones that weren't "interesting" ๐ฆ.
One crucial philosophical difference between IMAP and other common mail protocols is that IMAP is a mailbox access protocol, not a protocol for manipulating mail files ๐ง . In the IMAP model, other mail system models store mail in a linear mail file. IMAP doesn't specify an implementation architecture for mail storage. Servers may choose to implement mailboxes as files, but that's a detail the client can be totally unaware of ๐ซ .
What is more, in the IMAP model, mailboxes are viewed as mappings from keys into values ๐บ๏ธ. There are broadly three types of keys: generic, canonical and concrete. Generic keys are generic, mail-protocol-independent keys defined by IMAP that are meaningful across multiple mail encoding formats. An example of such a generic key might be TO, which would be associated with the To: field of an RFC 822 format message ๐.
Canonical keys represent the way in which the server can associate values that are generally "about" a certain key concept. They might integrate several mail-format-specific fields, without having to worry the client with the particular details of any particular message format ๐ช. So the canonical TO key (called $TO) could denote anything that could reasonably be construed as being directed towards someone ๐. That means in an RFC 822 message, the server could find the union of the To:, Resent-To, Apparently-To: and CC: fields to be the appropriate value associated with the canonical $TO key ๐งฉ.
Concrete keys allow the client to gain access to certain mail-format-specific concepts, which are not pre-specified by the IMAP protocol, in a well-defined manner ๐. For example, if the client asks for the value associated with the APPARENTLY-TO key, then (if the message is in RFC 822 format) the server would look for a header field called Apparently-To: ๐. If no such field is found, or the field is not implemented or meaningful for the particular message format, then the server will respond with the null value, called NIL, indicating the non-existence of the field ๐.
So IMAP servers are at liberty to implement mailboxes as relational databases if it seems convenient ๐๏ธ. In fact, we anticipate that future mail systems will tend to use database technology for storing and indexing mailboxes, because mailboxes keep getting bigger ๐.
Although IMAP is currently somewhat closely associated with RFC 822 for historical reasons, we anticipate that future IMAP developments will remove these mail-format-specific components and move toward the generic model mentioned above ๐. That will make it much easier for IMAP to incorporate things like multi-media mail ๐จโจ.
The Protocol โจ
okay bestie, so IMAP3 is basically a conversation ๐ฌ where the client sends commands and the server sends responses back. The server can also drop extra info whenever it wants, asynchronously, and that info is totally independent from the responses to your commands. Unlike most Internet protocols, these are tagged ๐ท๏ธ. Every command starts with a unique identifier, called a tag, and it's usually a short alphanumeric thing like what a Lisp "gensym" function would generate (e.g., A0001, A0002, etc.). The server replies with that same tag. It's giving organization ๐ค๐
We need names for two kinds of server data. Data the server sends because the client asked for it is SOLICITED. Data the server sends without being asked is UNSOLICITED ๐ฆ. The server can send unsolicited data any time, as long as it doesn't chop up another piece of data on the same stream and make it unreadable ๐. Solicited data is a different story. The server is contractually required to return all of it before it sends the completion signal for that command. In other words, all solicited data has to show up inside the request/completion acknowledgement wrapper. This doesn't stop the client from running several requests at once. It just means the client needs to be sure it has all the data it asked for once a request is finished. That's what makes both synchronous and asynchronous clients possible ๐
Solicited data gets identified by the tag of the client's original request. Unsolicited data uses the special reserved tag *. There's one more special reserved tag, +, which we'll get to later ๐ธ
Note: the tagging of SOLICITED data is only permitted for a selected server version other than 2.0.
A correct client can't make any assumptions about whether the server processes things one at a time or all in one go ๐ โโ๏ธ. The server is free to handle multiple requests from the same client in any order. This lets servers chew through expensive searches on slow backing storage in the background while still keeping things snappy for the user โก. Clients can still count on the request/data/completion behavior I mentioned above being serialized, though ๐
When a connection opens, the server sends an unsolicited OK response as a greeting and then just waits. Once commands start coming in, the server acts on them and sends back responses, often with some data mixed in ๐
The client opens a connection, waits for that greeting, and then sends a LOGIN command with a user name and password to get authorized ๐. After the server says OK, the client sends a SELECT command to open the mailbox it wants. Every user's default mailbox is called INBOX, and that name is reserved and the same no matter what operating system the server runs on ๐ฌ. Usually the server sends back a list of valid flags, the number of messages, and how many messages have arrived since the last time someone accessed that mailbox. It sends all that as solicited data, followed by an OK response โจ. If the client wants to leave that mailbox and check out a different one, it can just send another SELECT command ๐ง
Here's the thing that makes SELECT so special: it changes the server's state in a huge way. So the server has to process every outstanding command for a mailbox before it sends the OK tag for the SELECT command ๐ฅ. That way the client always knows that anything before the OK SELECT response is about the old mailbox, and anything after it is about the new one. Clean, no mix-ups, iconic ๐
Now for the versioning drama ๐ญ. In the real world, local needs and experimental work will push servers to support both supersets of the defined behavior and incompatible changes. So servers will support a SELECT.VERSION command and a SELECT.FEATURES command. Their whole job is letting clients pick the overall behavior and the specific features they want from a server ๐. By default, any server processes commands and uses the same interaction syntax as IMAP2 in RFC 1064. A server isn't allowed to behave any other way unless someone uses SELECT.VERSION or SELECT.FEATURES to choose different behavior ๐
โโ๏ธ
Over time, when groups of generally useful changes to the default behavior are found, they'll get bundled together. Then you can turn on all of those features just by selecting a specific major version number of the protocol ๐. The version numbers (both major and minor) that SELECT.VERSION picks are versions of the IMAP protocol, not versions of the server itself, so keep that straight ๐ง . Changes to the protocol are usually made to be upwards compatible, but nobody can promise that. So no client should rely on a test like if major_version > 2 then... being valid for every protocol version, because incompatible changes might show up later ๐
The client reads mailbox information with FETCH commands. The actual data comes back through the solicited data mechanism. Think of FETCH as poking the server to include the data you want, along with whatever else it wants to send you ๐๐. There are three major categories of data you can fetch ๐
The first category is data attached to a message as an entity in the mailbox. Right now there are three items here: the "internal date", the "RFC 822 size", and the "flags" ๐ท๏ธ. The internal date is when the message landed in the mailbox. The RFC 822 size is on the chopping block for future removal. It's the size of the message in bytes, expressed as an RFC 822 text string, and current clients mostly just use it in a status display line ๐. The flags are a list of status flags tied to the message (more on those below). You can grab all of this first-category data at once with the macro-fetch word FAST, which expands to (FLAGS INTERNALDATE RFC822.SIZE) โก
The second category is the composition and delivery info of a message: stuff like the sender, recipient lists, message-ID, subject, and so on. This info lives in the message header in RFC 822 format, and people traditionally call it the "envelope" ๐.
[Note: this should not be confused with the SMTP (RFC 821) envelope, which is strictly limited to delivery information.]
IMAP3 gives the envelope a structured, unambiguous representation that's especially lovely for Lisp-based parsers ๐ฅฐ. A client can use the envelope for things like replying and never has to think about RFC 822 at all ๐. We'll dig into envelopes more below. You can fetch the first and second categories together with the macro-fetch word ALL, which expands to (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) ๐ซถ
The third category is data meant for direct human viewing. The current RFC 822 based IMAP3 defines three items here: RFC822.HEADER, RFC822.TEXT, and RFC822. The last one is just the first two stuck together in one text string ๐. Fetching RFC822 gives you the RFC 822 representation of the message exactly as it's stored in the mailbox, with no filtering or processing at all. Raw and unfiltered, periodt ๐
Here's how a typical client moves through all this ๐ง. It'll FETCH ALL for some or all of the messages in the mailbox to build a presentation menu. Then, when the user wants to read a specific message, it'll FETCH RFC822.TEXT to get the body. A more basic client could also just FETCH RFC822 and call it a day, kind of like POP2-style functionality ๐ค
The client can change certain data with a STORE command. For example, you delete a message by sending a STORE command that sets the \DELETED flag ๐๏ธโจ
Other things a client can do include copying a message to another mailbox (COPY command), permanently removing deleted messages (EXPUNGE command), checking for new messages (CHECK command), and searching for messages that match certain criteria (SEARCH command) ๐๐
To end the session, the client sends a LOGOUT command, and the server replies with a BYE followed by an OK ๐๐ธ
A Typical Scenario ๐
okay bestie, let's watch a whole session play out from start to finish ๐ The client opens the connection, the server says hi, and then they just trade commands and replies back and forth like a group chat ๐ฌ
Client Server
------ ------
{Wait for Connection}
{Open Connection} -->
<-- * OK IMAP3 Server Ready
{Wait for command}
A001 SUPPORTED.VERSIONS -->
<-- * SUPPORTED.VERSIONS ((2 0 )
(3 0 EIGHT.BIT.TRANSPARENT
AUTO.SET.SEEN
TAGGED.SOLICITED))
A001 OK Supported Versions returned.
{Wait for command}
A002 SELECT.VERSION (3 0) -->
<-- A002 OK Version 3.0 Selected.
{Wait for command}
A002 SELECT.FEATURES TAGGED.SOLICITED -->
<-- A002 OK Features selected.
{Wait for command}
A003 LOGIN Fred Secret -->
<-- A003 OK User Fred logged in
{Wait for command}
A004 SELECT INBOX -->
<-- A004 FLAGS (Meeting Notice \Answered
\Flagged \Deleted \Seen)
<-- A004 19 EXISTS
<-- A004 2 RECENT
<-- A004 OK Select complete
{Wait for command}
A005 FETCH 1:19 ALL -->
<-- A005 1 Fetch (......)
...
<-- A005 18 Fetch (......)
<-- A005 19 Fetch (......)
<-- A005 OK Fetch complete
{Wait for command}
A006 FETCH 8 RFC822.TEXT -->
<-- A006 8 Fetch (RFC822.TEXT {893}
...893 characters of text...
<-- )
<-- A006 OK Fetch complete
{Wait for command}
A007 STORE 8 +Flags \Deleted -->
<-- A007 8 Store (Flags (\Deleted
\Seen))
<-- A007 OK Store complete
{Wait for command}
A008 EXPUNGE -->
<-- A008 19 EXISTS
<-- A008 8 EXPUNGE
<-- A008 18 EXISTS
<-- A008 Expunge complete
{Wait for command}
A009 LOGOUT -->
<-- A009 BYE IMAP3 server quitting
<-- A009 OK Logout complete
{Close Connection} --><-- {Close connection}
{Go back to start}
Now for a spicier one ๐ง This version comes from a pipelining multiprocess client, so the traffic gets a lot busier โจ
Client Server
------ ------
{Wait for Connection}
{Open session as above}
<-- A004 19 EXISTS
<-- A004 2 RECENT
<-- A004 OK Select complete
{Wait for command}
A005 SEARCH RECENT -->
<-- A005 SEARCH (18 19) (RECENT)
<---A005 OK Search complete
A006 FETCH 18:19 ALL RFC822.TEXT
A007 STORE 18:19 +FLAGS (\SEEN)
A008 FETCH 1:17 ALL -->
<-- A006 18 Fetch (... RFC822.TEXT ...)
A009 STORE 18 +FLAGS (\DELETED)
<-- A006 19 Fetch (... RFC822.TEXT ...)
<-- A006 OK Fetch complete
<-- A007 18 STORE (Flags (\Seen))
A010 STORE 19 +FLAGS (\DELETED)
<-- A007 19 STORE (Flags (\Seen))
<-- A007 OK Store complete
<-- A008 1 Fetch (......)
...
<-- A008 16 Fetch (......)
<-- A008 17 Fetch (......)
<-- A008 OK Fetch complete
<-- A009 18 STORE (Flags (\Seen
\Deleted))
<-- A009 OK Store complete
<-- A010 19 STORE (Flags (\Seen
\Deleted))
<-- A010 OK Store complete
{Wait for command}
<-- * EXISTS 23
<-- * RECENT 4
<-- * SEARCH (20 21 22 23) (RECENT)
A011 FETCH 20:23 ALL RFC822.TEXT
Conventions โจ
These are the meta-terms the syntax part uses, so you can read the grammar without getting lost ๐ซถ
- An
ASCII-STRINGis a sequence of arbitrary ASCII characters. - An
ATOMis a sequence of ASCII characters delimited bySPorCRLF. - A
CHARACTERis any ASCII character except"""", "{", CR, LF, "%", or "\". - A
CRLFis an ASCII carriage-return character followed immediately by an ASCII linefeed character. - A
NUMBERis a sequence of the ASCII characters which represent decimal numerals ("0"through"9"), delimited bySP,CRLF,",", or":". - A
SPis the ASCII space character. - A
TEXT_LINEis a human-readable sequence of ASCII characters up to but not including a terminatingCRLF.
One of the most common fields in IMAP3 is a STRING ๐ It can be an ATOM, a QUOTED-STRING (a sequence of CHARACTERs inside double-quotes), or a LITERAL. A literal is made of an open brace ("{"), a number, a close brace ("}"), a CRLF, and then an ASCII-STRING of n characters, where n is the value of the number inside the brace. In general, a string SHOULD be represented as an ATOM or QUOTED-STRING if at all possible. The semantics for QUOTED-STRING or LITERAL are checked before those for ATOM, so an ATOM used in a STRING MAY only contain CHARACTERs. Literals are most often sent from the server to the client. In the rare case of a client to server literal there is a special consideration (see the + text response below).
Another big one is the SEQUENCE โจ It identifies a set of messages by consecutive numbers from 1 to n, where n is the number of messages in the mailbox. A sequence MAY consist of a single number, a pair of numbers delimited by colon that means all the numbers between those two, or a list of single numbers and/or number pairs. For example, the sequence 2,4:7,9,12:15 is equivalent to 2,4,5,6,7,9,12,13,14,15 and identifies all of those messages. ๐
Definitions of Commands and Responses ๐
Summary of Commands and Responses
Commands:
tag NOOP
tag LOGIN user password
tag LOGOUT
tag SELECT mailbox
tag CHECK
tag EXPUNGE
tag COPY sequence mailbox
tag FETCH sequence data
tag STORE sequence data value
tag SEARCH criteria
tag BBOARD bboard
tag FIND (BBOARDS / MAILBOXES) pattern
tag READONLY
tag READWRITE
tag SELECT.VERSION (major_version minor_version)
tag SELECT.FEATURES features
tag SUPPORTED.VERSIONS
tag FLAGS
tag SET.FLAGS
Responses (can be either solicited or unsolicited):
*/tag FLAGS flag_list
*/tag SEARCH (numbers) (criteria)
*/tag EXISTS
*/tag RECENT
*/tag EXPUNGE
*/tag STORE data
*/tag FETCH data
*/tag BBOARD bboard_name
*/tag MAILBOX non_inbox_mailbox_name
*/tag SUPPORTED.VERSIONS version_data
*/tag READONLY
*/tag READWRITE
*/tag OK text
*/tag NO text
*/tag BAD text
*/tag BYE text
Responses (can only be solicited):
tag COPY message_number
Responses (can only be unsolicited):
+ text
Commands
tag NOOP ๐ง
NOOP is the chill one ๐ฆ The NOOP command returns an OK to the client. By itself it does nothing, but certain things MAY happen as side effects. For example, server implementations which implicitly check the mailbox for new mail MAY do so as a result of this command. The main use of this command is for the client to see if the server is still alive (and to let the server know the client is still alive, for those servers which have inactivity autologout timers) ๐
tag LOGIN user password ๐
The LOGIN command identifies the user to the server and carries the password that authenticates this user. The server uses this info to control access to the mailboxes. ๐
EXAMPLE: A001 LOGIN SMITH SESAME logs in as user SMITH with password SESAME.
tag LOGOUT ๐
The LOGOUT command tells the server the client is done with the session. The server sends a solicited BYE response before the (tagged) OK response, and then closes the connection. bye bye, bestie ๐ซถ
tag SELECT mailbox ๐ฌ
The SELECT command selects a particular mailbox. The server MUST check that the user is permitted read access to this mailbox. Before returning an OK to the client, the server MUST send a solicited FLAGS and <n> EXISTS response to the client. That response gives the flags list for this mailbox (just the system flags if this mailbox doesn't have any special flags) and the number of messages in the mailbox. It is also RECOMMENDED that the server send a <n> RECENT unsolicited response to the client, for the benefit of clients which make use of the number of new messages in a mailbox. It is further RECOMMENDED that servers SHOULD send an unsolicited READONLY message if the mailbox that has been selected is not writable by the user.
Multiple SELECT commands are permitted in a session, in which case the prior mailbox is deselected first.
The default mailbox for the SELECT command is INBOX, a special name reserved to mean "the primary mailbox for this user on this server". The format of other mailbox names is operating system dependent (as of this writing, it reflects the path of the mailbox on the current servers), though it could reflect any server-specific naming convention for the namespace of mailboxes. That namespace need not and SHOULD NOT be viewed as equivalent to, or linked with, the server machine's file system ๐ธ
EXAMPLES:
A002 SELECT INBOX ;; selects the default mailbox.
A002 197 EXISTS ;; server says 197 messages in INBOX
A002 5 RECENT ;; server says 5 are recent.
A002 OK Select complete.
or
A003 SELECT /usr/fred/my-mail.txt
;; select a different user specified mailbox.
...
tag CHECK ๐
The CHECK command forces a check for new messages and a rescan of the mailbox for internal changes. It's for those implementations which allow multiple simultaneous read/write access to the same mailbox (e.g., TOPS-20). It is RECOMMENDED that periodic implicit checks for new mail be done by servers as well. The server MUST send a solicited <n> EXISTS response prior to returning an OK to the client. ๐
tag EXPUNGE โจ
okay so EXPUNGE is the moment the mailbox gets its glow-up ๐งนโจ It permanently removes every message that has the \DELETED flag set in its flags from the mailbox. Before the server says OK to the client, it sends a solicited <n> EXPUNGE response for each message that got removed, so the client knows exactly which one is gone ๐ Every later message's message number drops by 1 right away. So if the last 5 messages in a 9-message mailbox get expunged, you'll receive 5 "5 EXPUNGE" responses for message 5. Yes, the same number five times. It's giving dรฉjร vu ๐
To keep the mailbox healthy and the server and client on the same page ๐ซถ, it is recommended that the server do an implicit check before the expunge starts and again once it's done. And if the server lets more than one person into the same mailbox at once, the server must guarantee both the integrity of the mailbox and the views of it held by the clients. no pressure ๐ญ
EXPUNGE is not allowed if the user doesn't have write access to this mailbox ๐ซ (rip). If a user doesn't have write access to the mailbox, the server is required to signal this by replying with a NO response, plus a suitable text string that can be presented to the user explaining that the mailbox is read-only ๐ It is further recommended that servers send an unsolicited READONLY message to clients that try an expunge on a read only mailbox ๐ข
next up is COPY ๐
tag COPY sequence mailbox
COPY copies the specified message(s) to the specified destination mailbox. If the destination mailbox doesn't exist, the server should create it ๐๏ธ Before the server says OK to the client, the server must return a solicited <n> COPY response for each message copied.
EXAMPLE: A003 COPY 2:4 MEETING copies messages 2, 3, and 4 to mailbox "MEETING".
COPY is not allowed if the user doesn't have write access to the destination mailbox ๐ If a user doesn't have write access to the destination mailbox, the server is required to signal this by replying with a NO response with a suitable text string that can be presented to the user, explaining that the mailbox is read-only. It is further recommended that servers send an unsolicited READONLY message to clients that try to copy into a read only mailbox ๐ข IMAP3 does not specify "where" the message will be put in the mailbox it has been copied to ๐คท
now FETCH ๐ this one's the main event.
tag FETCH sequence fetch_att
The data items to be fetched may be either a single atom or an S-expression list. You can fetch any of the attributes mentioned specifically below, along with any generic, canonical or concrete key ๐ง The predefined generic keys are {BCC, BODY, CC, FROM, HEADER, SIZE, SUBJECT, TEXT, TO}, and the predefined canonical keys are {$CC, $FROM, $SUBJECT, $TO}. If a key doesn't exist or isn't meaningful for the message, the server gives back the null value, NIL ๐ซฅ
ALL Equivalent to:
(FLAGS INTERNALDATE RFC822.SIZE ENVELOPE)
ENVELOPE The envelope of the message. The envelope is
computed by the server by parsing the header,
i.e., the RFC 822 header for an RFC822 format
message, into the component parts, defaulting
various fields as necessary.
FAST Macro equivalent to:
(FLAGS INTERNALDATE RFC822.SIZE)
FLAGS The flags which are set for this message.
This may include the following system flags:
\RECENT Message arrived since
last read of this mailbox
\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
INTERNALDATE The date and time the message was written to
the mailbox.
RFC822 The message in RFC 822 format.
RFC822.HEADER The RFC 822 format header of the message.
RFC822.SIZE The number of characters in the message as
expressed in RFC 822 format.
RFC822.TEXT The text body of the message, omitting the
RFC 822 header.
the examples are where it gets fun ๐
EXAMPLES:
A003 FETCH 2:4 ALL
fetches the flags, internal date, RFC 822 size, and envelope
for messages 2, 3, and 4.
A004 FETCH 3 RFC822
fetches the RFC 822 representation for message 3.
A005 FETCH 4 (FLAGS RFC822.HEADER)
fetches the flags and RFC 822 format header for message 4.
A006 FETCH 42 $SUBJECT
A006 FETCH $SUBJECT "Some subject text..."
A006 OK FETCH completed ok.
fetches the canonical subject field.
A007 FETCH 42 APPARENTLY-TO
A007 FETCH APPARENTLY-TO NIL
A007 OK FETCH found no value.
fetches the concrete apparently-to field.
and now STORE ๐ง
tag STORE sequence data value
STORE alters the values associated with particular keys for a message in the mailbox. Just like FETCH, any generic, canonical or concrete key can be used to index the value provided. On top of those, these pre-defined keys are provided ๐
FLAGS Replace the flags for the message with the
argument (in flag list format).
The server must respond with a solicited STORE FLAGS
message, showing the new state of the flags after
the store.
+FLAGS Add the flags in the argument to the
message's flag list.
The server must respond with a solicited STORE FLAGS
message, showing the new state of the flags after
the store.
-FLAGS Remove the flags in the argument from the
message's flag list.
The server must respond with a solicited STORE FLAGS
message, showing the new state of the flags after
the store.
RFC822.HEADER Replace the header of the message(s) with that
specified. This allows users to use their mailboxes
as databases with header fields as keys.
The server must respond with solicited
STORE RFC822.HEADER, STORE RFC822.SIZE and
STORE ENVELOPE messages, showing the new state
of the reparsed header after the store.
RFC822.TEXT Replace the body of the messages with that specified.
The server must respond with solicited
STORE RFC822.TEXT and STORE RFC822.SIZE messages,
showing the new state of the message after the store.
STORE is not allowed if the user doesn't have write access to this mailbox ๐ซ
The server is required to send a solicited STORE response for each store operation that results in a format transformation by the server. For example, the server is required to send a STORE FLAGS response when the client performs a STORE +FLAGS or a STORE -FLAGS, since the client may not easily be able to know what the result of this command will be ๐ค Similarly, if the client emits a STORE FROM command then the server should respond with a suitable STORE FROM response, because the client would be sending a string value to be stored and the server should transform this into a set of addresses. In general, though, it is legal for the server to send a solicited STORE response for each STORE operation, but this is discouraged ๐ since it might result in the retransmission of very large and unnecessary amounts of data that have been stored.
EXAMPLE: A003 STORE 2:4 +FLAGS (\DELETED) marks messages 2, 3, and 4 for deletion.
last but not least, SEARCH ๐
tag SEARCH search_criteria
SEARCH searches the mailbox for messages which match the given set of criteria. The server response SEARCH (criteria) (numbers) gives the set of messages which match the conjunction of the criteria specified ๐ซ In addition to each of the search criteria there is its logical inverse. The logical inverse criterion is denoted by the ~ (tilda) sign.
Thus, no message that matches the criterion:
FROM crispin
will match the criterion:
~FROM crispin
The criteria for the search can be any generic, canonical or concrete key. In addition to these, the following pre-defined keys are also provided โจ
ALL All messages in the mailbox; the default
initial criterion for ANDing.
ANSWERED Messages with the \ANSWERED flag set.
BCC string Messages which contain the specified string
in the envelope's BCC field.
BEFORE date Messages whose internal date is earlier than
the specified date.
BODY string Messages which contain the specified string
in the body of the message.
CC string Messages which contain the specified string
in the envelope's CC field.
DELETED Messages with the \DELETED flag set.
FLAGGED Messages with the \FLAGGED flag set.
FROM string Messages which contain the specified string
in the envelope's FROM field.
HEADER string Messages which contain the specified string
in the message header.
KEYWORD flag Messages with the specified flag set.
NEW Messages which have the \RECENT flag set but
not the \SEEN flag. This is functionally
equivalent to "RECENT UNSEEN".
OLD Messages which do not have the \RECENT flag
set.
ON date Messages whose internal date is the same as
the specified date.
RECENT Messages which have the \RECENT flag set.
SEEN Messages which have the \SEEN flag set.
SINCE date Messages whose internal date is later than
the specified date.
SUBJECT string Messages which contain the specified string
in the envelope's SUBJECT field.
TEXT string Messages which contain the specified string.
TO string Messages which contain the specified string in
the envelope's TO field.
here's the example, and it's so satisfying ๐ฅฐ
EXAMPLE: A003 SEARCH DELETED FROM "SMITH" SINCE 1-OCT-87
returns the message numbers for all deleted messages from Smith
that were placed in the mailbox since October 1, 1987.
Implementation note: The UNANSWERED, UNDELETED, UNFLAGGED, UNKEYWORD and UNSEEN criteria, described below, are preserved in IMAP3 for IMAP2 compatibility. They are, however, considered obsolete, and new Client programs are encouraged to use the ~ notation for the logical inverses of search criteria, with a view to dropping this outmoded syntax in later versions ๐
UNANSWERED Messages which do not have the \ANSWERED flag
set.
UNDELETED๐ gets you every message that does not have the\DELETEDflag set. Basically the "not in the trash" squad ๐๏ธ๐ซUNFLAGGED๐ฉ gets you every message that does not have the\FLAGGEDflag set.UNKEYWORD flag๐ท๏ธ gets you every message that does not have the specified flag set. You pick the flag, so you're in control ๐UNSEEN๐ gets you every message that does not have the\SEENflag set. No peeking allowed, lol ๐
tag READONLY ๐
The READONLY command says the client wants to make the mailbox read-only. Think "I just wanna look, I'm not touching anything" ๐ซถ. The server is required to reply with a solicited READONLY or READWRITE response.
tag READWRITE โ๏ธ
The READWRITE command is the opposite energy. It says the client wants to make the mailbox read-write, so edits are on the table ๐ The server is required to reply with a solicited READONLY or READWRITE response.
tag SUPPORTED.VERSIONS ๐
The SUPPORTED.VERSIONS command asks the server for a SUPPORTED.VERSIONS message. That message is like the server's little rรฉsumรฉ ๐ผ It tells you which versions and features the server supports โจ
tag SELECT.VERSION (major_version minor_version) ๐
The SELECT.VERSION command says the client wants to select certain behavior on the part of the server. The major and minor versions tell the server exactly which version of the protocol is being selected ๐ฆ
A002 SELECT.VERSION (3 0)
Okay, so here's the tea โ A client may not request a server version that is not supported by the server. That means a version that isn't specifically mentioned in the response to a SUPPORTED.VERSIONS command. If a client tries anyway, the server will send back a NO response, and that's a big nope ๐ โโ๏ธ
It is an error for the SELECT.VERSION command to be used after a mailbox has been selected. Why? Because some server implementations might need to spawn separate programs to handle really different protocol versions ๐ง So the client can't expect any server state to be preserved after using SELECT.VERSION. Fresh start, every time ๐ธ
The default version of all servers is 2.0, i.e., IMAP2 as defined by RFC 1064. That's the baseline, bestie ๐
tag SELECT.FEATURES 1#features โญ
The SELECT.FEATURES command says the client wants to select certain specific features on the part of the server. A client may not request a feature that is not supported by the server. In other words, one that isn't explicitly mentioned in the set of features for the selected version returned by the SUPPORTED.VERSIONS command. If a client tries, the server sends back a NO response ๐
A002 SELECT.FEATURES AUTO.SET.SEEN ~TAGGED.SOLICITED
EIGHT.BIT.TRANSPARENT
So that's giving: select the set of features called AUTO.SET.SEEN and EIGHT.BIT.TRANSPARENT, and deselect the feature called TAGGED.SOLICITED. Using SELECT.FEATURES completely resets the set of selected features, so start clean every time ๐ซง
Note: these are only example feature names, and they are not necessarily supported by any server. Check the appendix on features for more info ๐
Note: some features, when present in the server, will cause the upwards compatible extension of the grammar, i.e., by adding extra commands. The server is at liberty not to remove these upwards compatible extensions to the command tables when a feature is disabled. So it is an error for a client to rely on getting a NO or BAD response in any way, for instance to determine the selectedness or presence of a feature. Don't do it, bestie ๐ซ
tag BBOARD bboard ๐ฃ
The BBOARD command is equivalent to SELECT, except its argument is a bulletin board (BBoard) name. The format of a BBoard name is implementation specific. It is strongly encouraged to use something that resembles a name in a generic sense, and not a file or mailbox name on the particular system ๐ There is no requirement that a BBoard name be a mailbox name or a file name. (Unix netnews, for example, has a completely different namespace from mailbox or file names. Wild, right? ๐คฏ)
The result from the BBOARD command is identical to that of the SELECT command. For example, in the TOPS-20 server implementation, this:
A0002 BBOARD FOO
is exactly equivalent to this:
A0002 SELECT POBOX:<BBOARD>FOO.TXT
Note: the equivalence in this example is not required by the protocol. It just reflects the fuzzy line between mailboxes and BBoards on TOPS-20 ๐
tag FIND (BBOARDS / MAILBOXES) pattern ๐
The FIND command takes the keywords BBOARDS or MAILBOXES, plus a pattern. That pattern picks out a set of BBoard or mailbox names that you can use with the BBOARD or SELECT command. There are two wildcards ๐ * means any number of characters (zero included) can match at that spot. % means a single character can match at that spot.
Here's how it plays out: FOO*BAR matches FOOBAR, FOOD.ON.THE.BAR and FOO.BAR. FOO%BAR only matches FOO.BAR. And * on its own matches all BBoards or mailboxes ๐
For wildcards, there's a quoting convention too: \* is the literal * character, \% is the literal % character, and \\ is the literal \ character. Escaping is giving precision ๐
Some notes: the format of mailboxes is server implementation dependent. Also, the special mailbox name INBOX is not included in the output to the FIND MAILBOXES command. Sorry INBOX, not this time ๐ฅบ
The FIND command solicits any number of BBOARD or MAILBOX responses from the server, as appropriate โจ
Examples:
A0002 FIND BBOARDS *
A0002 BBOARD FOOBAR
A0002 BBOARD GENERAL
A0002 OK FIND completed
or
A0002 FIND MAILBOXES FOO%BA*
A0002 MAILBOX FOO.BAR
A0002 MAILBOX FOO.BAZZAR
A0002 OK FIND completed
Note: even though the use of explicit file or path names for mailboxes is discouraged by this standard, it may be unavoidable ๐ซ It's important that the value returned in the MAILBOX solicited reply be usable in the SELECT command without you having to remember any path specification that may have been used in the FIND MAILBOXES pattern. Main character energy: the answer should just work ๐ฌ
tag FLAGS ๐ณ๏ธ
The FLAGS command solicits a FLAGS response from the server. Simple and iconic ๐
tag SET.FLAGS flag_list ๐ท๏ธ
The SET.FLAGS command defines the user specifiable flags for this mailbox, i.e., the keywords. If this set doesn't include flags that the server previously sent to the client in a FLAGS message, then that counts as a request to delete the flag ๐๏ธ Any new flags should be created. This command does not affect the system defined flags, so any system flags included in the flag_list will be ignored ๐
The server must respond to this command with a solicited FLAGS message. And if deleting a flag ends up invalidating the flag sets of any messages, then the server is required to send solicited STORE FLAGS messages to the client for each modified message. Everybody gets updated, no one gets left out ๐ซถ
Responses:
*/tag OK text โ
In its solicited form, this response identifies successful completion of the command with the indicated tag. The text is a line of human-readable text which may be useful in a protocol telemetry log for debugging purposes. Debugging buddy energy ๐งฐ
In its unsolicited form, this response simply indicates that the server is alive. No special action on the part of the client is called for. Right now this is only used by servers at startup, as a greeting that says they're ready to accept the first command. This usage is legal, but by no means required. The text is a line of human-readable text which may be logged in protocol telemetry ๐
*/tag NO text ๐
โโ๏ธ
In its solicited form, this response identifies unsuccessful completion of the command with the indicated tag. The text is a line of human-readable text which probably should be displayed to the user in an error report by the client. Tell the user the tea ๐ซ
In its unsolicited form, this response indicates some operational error at the server that can't be traced to any protocol command. The text is a line of human-readable text which should be logged in protocol telemetry for the maintainer of the server and/or the client ๐ ๏ธ
*/tag BAD text ๐
In its solicited form, this response indicates faulty protocol received from the client, and it indicates a bug. The text is a line of human-readable text which should be recorded in any telemetry as part of a bug report to the maintainer of the client. Someone's gotta fix that bug ๐ญ
In its unsolicited form, this response indicates some protocol error at the server that can't be traced to any protocol command. The text is a line of human-readable text which should be logged in protocol telemetry for the maintainer of the server and/or the client. This generally indicates a protocol synchronization problem, and examining the protocol telemetry is advised to determine the cause of the problem ๐
*/tag BYE text ๐
This indicates that the server is about to close the connection. The text is a line of human-readable text which should be displayed to the user in a status report by the client. IMAP2 requires that the server emit a solicited BYE response as part of a normal logout sequence. This solicited form is not required under IMAP3, though it is still legal for compatibility ๐งณ
In its unsolicited form, the BYE response is used as a panic shutdown announcement by the server ๐จ It is required to be used by any server that performs autologouts due to inactivity. Inactive too long? Bye bye, bestie ๐ค
*/tag number message_data ๐ฌ
The solicited (tag number message_data) response is generated as the result of a number of client requests. The server may also emit any of the following at any time as unsolicited data (i.e., * number message_data). The message_data is one of the following:
EXISTS๐ข The specified number of messages exists in the mailbox.RECENT๐ The specified number of messages have arrived since the last time this mailbox was selected with the SELECT command or equivalent.EXPUNGE๐จ The specified message number has been permanently removed from the mailbox, and the next message in the mailbox (if any) becomes that message number. The server must send a solicited EXPUNGE response for each message that it expunges as the result of an EXPUNGE command. Note: future versions of the protocol may allow the use of a message sequence as a value returned by the EXPUNGE response, to allow more efficient compaction of client representations of mailboxes ๐งนSTORE data๐๏ธ Functionally equivalent to FETCH, only it is sent by the server when the state of a mailbox changes. The server must send solicited STORE responses as the result of any change caused by a STORE command. Every change gets announced, periodt ๐ฃ
FETCH data ๐ okay so this is THE main way the server tells the client stuff about a message. The data comes in a Lisp-like S-expression property list, aka nested parens, very main-character โจ. Just like the client's FETCH request can ask for any generic, canonical or concrete key, the FETCH response can return values for any of those keys PLUS the pre-defined attributes listed below ๐. The server is also permitted to send any unsolicited FETCH or STORE messages that it SHOULD choose, whether those are values for generic, canonical or concrete keys ๐ฆ. Clients are REQUIRED to ignore any such FETCH responses that they cannot interpret ๐ซถ. Like, clients are not REQUIRED to be able to understand (aka use fruitfully) the canonical $TO key, but they are REQUIRED to be able to ignore an unsolicited $TO message correctly ๐ญ.
ENVELOPE ๐ฌ an S-expression list that describes the envelope of a message. The server builds it by parsing the RFC 822 header into its component parts, filling in various fields with defaults as needed ๐ง.
The fields of the envelope 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 lists of addresses ๐.
An address is an S-expression list that describes an electronic mail address. Its fields go in this order: personal name, source-route (aka the at-domain-list in SMTP), mailbox name, host name, and comments. Implementation note ๐ค: the comment field is an incompatible extension from IMAP2, so the server is REQUIRED not to provide this field when running in IMAP2 mode. Hard pass on that one ๐ โโ๏ธ.
Any field of an envelope or address that isn't applicable gets presented as the atom NIL ๐ซฅ. And the server MUST default the reply-to and sender fields from the from field, because a client is not expected to know to do this ๐ง . Not your job, bestie, the server's got it.
FLAGS ๐ฉ an S-expression list of flags that are set for this message. It may include these system flags:
\RECENT Message arrived since last
read of this mailbox
\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
INTERNALDATE ๐๏ธ a string containing the date and time the message was written to the mailbox.
RFC822 ๐ a string expressing the message in RFC 822 format.
Heads up ๐จ Some implementations of IMAP2 servers had the (undocumented) behavior of setting the \SEEN flag as a side effect of fetching the body of a message. This was giving erroneous behavior for clients that prefetch messages the user might not get around to reading, so this behavior is explicitly disallowed in IMAP3. Not cute, not allowed ๐.
Also, this is not a significant performance restriction, because it is always possible for IMAP3 clients to use an interaction with the server of the following type ๐ง:
A001 FETCH 42 RFC822
A002 STORE 42 +FLAGS (\SEEN)
A001 42 FETCH RFC822 {637} ......
A001 OK Fetch completed
A002 42 STORE FLAGS (\SEEN \FLAGGED...)
A002 OK Store Completed.
The rest of the attributes are giving organised energy ๐:
RFC822.HEADER: a string expressing the RFC 822 format header of the message ๐จRFC822.SIZE: a number indicating the number of characters in the message as expressed in RFC 822 format ๐ขRFC822.TEXT: a string expressing the text body of the message, omitting the RFC 822 header. See also the note forRFC822.
*/tag FLAGS flag_list ๐ณ๏ธ a solicited FLAGS response MUST occur as a result of a SELECT command. The flag list is the list of flags (at a minimum, the IMAP defined flags) that are applicable for this mailbox. Flags other than the system flags are a function of the server implementation, so that's between the server and its vibes ๐ธ.
*/tag SEARCH (numbers) (search_criteria) ๐ this response occurs as a result of a SEARCH command. The number(s) refer to those messages which match the search criteria. In its solicited form, this message lets clients find interesting groups of messages, e.g., unseen messages from Crispin ๐. In its unsolicited form, it lets the server tip the client off about interesting patterns, e.g., when new mail arrives that's recent and from Crispin ๐ฌ.
Compatibility note ๐งฉ: the search_criteria are sent by the server along with the matching numbers, so unsolicited SEARCH messages MAY be interpreted. This syntax is not upwards compatible with IMAP2, so the new syntax is intended to make it simple for clients that can't take advantage of unsolicited SEARCH messages to still interpret solicited SEARCH messages. They just ignore everything that follows the list of numbers, with minimal parsing ๐ซ . Such clients may not, however, simply discard the rest of the line, because there might be LITERALs in the search pattern. Plot twist, bestie ๐ณ.
Examples:
A00042 SEARCH (2 3 6) (FROM Crispin ~SEEN)
and
* SEARCH (42) (FROM Crispin RECENT)
*/tag READONLY ๐ this indicates that the mailbox is read-only. The server is REQUIRED to respond to a READONLY or READWRITE command with either a solicited READONLY or a solicited READWRITE response. Note ๐: if the client attempts a mutation operation, such as STORE, on a mailbox it doesn't have write access to, then the server is REQUIRED to reply with a solicited READONLY response on the first such attempted mutation. The server MAY also choose to send solicited READONLY responses for each subsequent attempted mutation, so it can keep reminding you ๐.
*/tag READWRITE โ๏ธ this indicates that the mailbox is read-write. The server is REQUIRED to respond to a READONLY or READWRITE command with either a solicited READONLY or a solicited READWRITE response. Full access, no drama ๐
.
*/tag BBOARD bboard_name ๐ this message is produced in its solicited form as a response to a FIND BBOARDS command. In its unsolicited form, it's the server's notification that a new BBoard has been added ๐. Bboard_name MUST be a name that can be supplied to the BBOARD command so as to select the appropriate bboard.
*/tag MAILBOX non_inbox_mailbox_name ๐ this message is produced in its solicited form as a response to a FIND MAILBOXES command. In its unsolicited form, it's the server's notification that a new mailbox has been added, perhaps as the result of a COPY command creating a new mailbox ๐ช. Non_inbox_mailbox_name MUST be a name that can be supplied to the SELECT command so as to select the appropriate mailbox. Note: non_inbox_mailbox_name is never the string "INBOX". Inbox is its own whole era ๐ฅ.
*/tag SUPPORTED.VERSIONS (version_specs) ๐งพ this message is used either as a response to the SUPPORTED.VERSIONS command or, in its unsolicited form, to indicate the dynamic addition or removal of support for features or protocol versions ๐. Each version_spec is of the form (4 2 EIGHT.BIT.TRANSPARENT AUTO.SET.SEEN ...), i.e., a major version number and a minor version number for the protocol, plus the set of features supported under the server's implementation of that protocol version ๐งฉ. A server may not dynamically remove support for any version or feature that has been selected by any currently logged-in client through use of the VERSION command. So no yanking things out from under people mid-session ๐ค.
Example:
A00005 SUPPORTED.VERSIONS ((2 0 )
(2 2 TAGGED.SOLICITED)
(3 0 EIGHT.BIT.TRANSPARENT TAGGED.SOLICITED))
This indicates that two major versions are supported and one minor version is supported, and that tagged solicited messages are supported in versions 2.2 and 3.0, with eight bit characters being supported under version 3 ๐. For each feature mentioned in the list of features, there is also always the negation of that feature. For example, if the server supports the TAGGED.SOLICITED feature, then it also supports the ~TAGGED.SOLICITED feature, which disables this feature ๐. Note: these are only example feature names and are not necessarily supported by any server. See the appendix on features for more information on features ๐.
+ text โ this response indicates that the server is ready to accept the text of a literal from the client. Normally, a command from the client is a single text line. If the server detects an error in the command, it can simply discard the remainder of the line. It cannot do this for commands that contain literals, since a literal can be an arbitrarily long amount of text, and the server may not even be expecting a literal ๐ตโ๐ซ. This mechanism is provided so the client knows not to send a literal until the server definitely expects it, which keeps client and server in sync ๐ซถ.
In actual practice, this situation is rarely encountered. In the current protocol, the only client commands likely to contain literals are the LOGIN command and the STORE RFC822.HEADER or STORE RFC822.TEXT commands ๐. Consider a situation in which a server validates the user before checking the password. If the password contains "funny" characters and so is sent as a literal, then if the user is invalid, an error would occur before the password is parsed. Oof ๐.
No such synchronization protection is provided for literals sent from the server to the client, for performance reasons ๐๏ธ. Any synchronization problems in this direction would be due to a bug in the client or server, not some operational problem ๐ ๏ธ.
Sample IMAP3 session ๐ฌโจ
okay so this is a real transcript of an actual IMAP3 session, bestie ๐ server lines start with "S:" and client lines start with "U:". when a line was too long for the page, it got wrapped onto the next line with a tab in front, so that's a continuation and not a brand new line ๐
S: * OK SUMEX-AIM.Stanford.EDU Interactive Mail Access Protocol
III Service 6.1(349) at Mon, 14 May 90 14:58:30 PDT
U: a001 SUPPORTED.VERSIONS
S: * SUPPORTED.VERSIONS ((2 0 ) (3 0 EIGHT.BIT.TRANSPARENT
AUTO.SET.SEEN TAGGED.SOLICITED))
S: A001 Supported Versions returned.
U: a002 SELECT.VERSION (3 0)
S: a002 OK Version 3.0 Selected.
U: a003 SELECT.FEATURES TAGGED.SOLICITED
S: a003 OK Features selected.
U: a004 login crispin secret
S: a004 OK User CRISPIN logged in at Thu, 9 Jun 90 14:58:42 PDT,
job 76
U: a005 select inbox
S: a005 FLAGS (Bugs SF Party Skating Meeting Flames Request AI
Question Note \XXXX \YYYY \Answered \Flagged \Deleted
\Seen)
S: a005 16 EXISTS
S: a005 0 RECENT
S: a006 OK Select complete
U: a006 fetch 16 all
S: a006 16 Fetch (Flags (\Seen) InternalDate " 9-Jun-88 12:55:
RFC822.Size 637 Envelope ("Sat, 4 Jun 88 13:27:11 PDT"
"INFO-MAC Mail Message" (("Larry Fagan" NIL "FAGAN"
"SUMEX-AIM.Stanford.EDU" NIL)) (("Larry Fagan" NIL "FAGAN"
"SUMEX-AIM.Stanford.EDU" NIL)) (("Larry Fagan" NIL "FAGAN"
"SUMEX-AIM.Stanford.EDU" NIL)) ((NIL NIL "rindflEISCH"
"SUMEX-AIM.Stanford.EDU" NIL)) NIL NIL NIL
"<12403828905.13.FAGAN@SUMEX-AIM.Stanford.EDU>"))
S: a006 OK Fetch completed
U: a007 fetch 16 rfc822
S: a007 16 Fetch (RFC822 {637}
S: Mail-From: RINDFLEISCH created at 9-Jun-88 12:55:43
S: Mail-From: FAGAN created at 4-Jun-88 13:27:12
S: Date: Sat, 4 Jun 88 13:27:11 PDT
S: From: Larry Fagan <FAGAN@SUMEX-AIM.Stanford.EDU>
S: To: rindflEISCH@SUMEX-AIM.Stanford.EDU
S: Subject: INFO-MAC Mail Message
S: Message-ID: <12403828905.13.FAGAN@SUMEX-AIM.Stanford.EDU>
S: ReSent-Date: Thu, 9 Jun 88 12:55:43 PDT
S: ReSent-From: TC Rindfleisch <Rindfleisch@SUMEX-AIM.Stanford.EDU>
S: ReSent-To: Yeager@SUMEX-AIM.Stanford.EDU,
Crispin@SUMEX-AIM.Stanford.EDU
S: ReSent-Message-ID:
<12405133897.80.RINDFLEISCH@SUMEX-AIM.Stanford.EDU>
S:
S: The file is <info-mac>usenetv4-55.arc ...
S: Larry
S: -------
S: )
S: a007 OK Fetch completed
U: a008 logout
S: a008 BYE UNIX IMAP III server terminating connection
S: a008 OK SUMEX-AIM.Stanford.EDU Interim Mail Access Protocol
Service logout
Implementation Discussion ๐ง
okay the implementation stuff is my absolute fave ๐ซถ as of this writing, SUMEX has finished an IMAP2 client for Xerox Lisp machines, written in hybrid Interlisp/CommonLisp, and it's starting to hand out a client for TI Explorer Lisp machines ๐ฅ. they also finished a portable IMAP2 client protocol library module written in C. add a small main program (mostly the user interface) and a TCP/IP driver, and that library turned into a scrappy remote system mail-reading program under Unix ๐ป. the first real production use of the library is inside a MacII client that's been in daily use by real users at Stanford for quite some time now โจ
as of this writing, SUMEX has also finished IMAP2 servers for TOPS-20, written in DEC-20 assembly language, and for 4.2/3 BSD Unix, written in C ๐ . the TOPS-20 server is fully compatible with MM-20, the standard TOPS-20 mailsystem, and it doesn't need any special action or setup from the user. under TOPS-20, the INBOX is the user's MAIL.TXT. that server also supports multiple simultaneous access to the same mailbox, including simultaneous access between the IMAP3 server and MM-20 ๐. the 4.2/3 BSD Unix server needs the user to be using either Unix Mail format or mail.txt format, which is compatible with SRI MM-32 or Columbia MM-C. it allows simultaneous read access, but write access has to be exclusive ๐. there's also an experimental IMAP3 server running on the TI Explorer class of machine. it uses MM mailbox format and can communicate over both TCP and Chaos ๐
the Xerox Lisp client and DEC-20 server have been in production use for over two years, and the Unix server has been in production use for over a year ๐. IMAP3 has been used to reach mailboxes at remote sites from a local workstation over the Internet. for example, from the Stanford local network, one of the authors has read his mailbox at a Milnet site ๐ซ
a bunch of IMAP clients have been developed or are in the works now, and they run on these machines:
- Xerox Lisp machines
- Apple Macintosh
- NeXT
- IBM PC
- TI Explorer Lisp machines
- "Glass teletype" version that runs under Unix
- GNU Emacs
- X Windows
- NTT ELIS
each of these clients is carefully tuned so the performance and user interface match the user interface model of the native machine โจ. like, the Macintosh client has a "messy-desk" interface that lets you cut and paste text with the clipboard, plus a menu driven interface with keyboard accelerators. very iconic ๐
this specification doesn't make any formal definition of size restrictions, but some of the existing servers have these limits:
- DEC-20
- length of a mailbox: 7,077,888 characters
- maximum number of messages: 18,432 messages
- length of a command line: 10,000 characters
- length of the local host name: 64 characters
- length of a "short" argument: 39 characters
- length of a "long" argument: 491,520 characters
- maximum amount of data output in a single fetch: 655,360 characters
- TI-Explorer
- length of a mailbox: limited by the Minimum of the size of the virtual address space and the size of the file system
- maximum number of messages: limited by the size of the virtual address space
- length of a command line: limited by the size of the virtual address space
- length of the local host name: limited by the size of the virtual address space
- length of a "short" argument: limited by the size of the virtual address space
- length of a "long" argument: limited by the size of the virtual address space
- maximum amount of data output in a single fetch: not limited
typical values for these limits are 30Mb for file systems and 128Mb for virtual address space ๐ง . so far nobody has run up against any of these limits, and a lot of them are way bigger than most current user mail reading programs ๐
there are a few big perks to the scheme of tags, solicited responses, and unsolicited data ๐. first, the infamous synchronization problems of SMTP and similar protocols don't happen with tagged commands. a command isn't considered satisfied until a completion acknowledgement with the same tag shows up ๐ฏ. tagging lets the server send an arbitrary amount of other responses ("solicited" data) with zero chance of the client losing synchronization. compare that with the mess FTP and SMTP clients deal with around continuation, partial completion, and commentary reply codes ๐
another perk is that a non-lockstep client is possible. the client can send a command and hand off the handling of the server responses to a different process, which signals the client when the tagged response comes in. some clients might even be thoroughly asynchronous, with maybe multiple outstanding commands at any given time ๐ฆ. note: this does not require the server to process these commands in anything other than a lock-step manner. it just lets clients take advantage of servers that can do that kind of asynchronous operation โจ
synchronization problems can happen with literals if the literal isn't recognized as one ๐ญ. luckily, those cases are pretty rare, so a mechanism (the special "+" tag response) was added to handle the few cases that could happen. the proper way to fix this in every case is probably to move toward a record-oriented architecture, instead of the text stream model TCP gives you ๐ง
now, unsolicited data needs its own moment ๐. unlike most protocols, where the server just does the client's bidding, an IMAP3 server has a semi-autonomous role. by sending "unsolicited data," the server is effectively sending a command to the client, telling it to update and/or extend its (incomplete) model of the mailbox with new info from the server ๐ซง. in this view, a "fetch" command is a request for specific info from the client, but the server is always free to include more than the desired data as "unsolicited." a server acknowledgement to the "fetch" is a statement that at least all the requested data has been sent ๐
in terms of implementation, a simple lock-step client may keep a local cache of data from the mailbox. that cache is incomplete in general, and at select time it's empty. a listener on the IMAP connection in the client processes all solicited and unsolicited data symmetrically and updates the cache based on it. basically, the client faults on a cache miss and asks the server to fill that cache slot synchronously. when a tagged completion response arrives, the listener unblocks the process that sent the tagged request ๐ฅ
clearly, with this model it isn't strictly necessary to tell most solicited data apart from unsolicited data. doing so, though, is clearer, and it also lets simplistic lock-step clients pull the specific value of a response to a command by trapping the tagged response. that way the client doesn't have to block on some complex predicate about watching for an update in a cache cell ๐
for example, maybe after opening a mailbox, solicited data arrives from the server. the first piece of data is the number of messages. this is used to size the cache. if new mail arrives, the server will cause the cache to be re-sized by sending a new "number of messages" unsolicited data message ๐ฌ. if the client tries to access info from the cache and hits empty spots, those trigger "fetch" requests. the request gets sent, some solicited data (including the answer to the fetch) flows back, and then the "fetch" response unblocks the client ๐ฅน
people who know demand-paged virtual memory design will recognize this model as being really similar to page-fault handling on a demand-paged system ๐งโจ
Formal Syntax โจ
okay bestie, the grammar is written in augmented Backus-Naur Form (BNF) notation as specified in RFC 822, with one tiny twist: the delimiter used with the "#" construct is a single space (SP), not a comma ๐
address ::= "(" addr_name SP addr_adl SP addr_mailbox SP
addr_host addr_comment ")"
addr_adl ::= nil / string
addr_comment ::= nil / string
addr_host ::= nil / string
addr_mailbox ::= nil / string
addr_name ::= nil / string
bboard ::= "BBOARD" SP bboard_name
bboard_name ::= string
bboard_notify ::= "BBOARD" sp bboard_name
canonical_key ::= "$CC" / "$FROM" / "$SUBJECT" / "$TO"
check ::= "CHECK"
concrete_key ::= string
copy ::= "COPY" SP sequence SP mailbox
criterion ::= "ALL" / "ANSWERED" /
"BCC" SP string / "BEFORE" SP string /
"BODY" SP string / "CC" SP string / "DELETED" /
"FLAGGED" / "KEYWORD" SP atom / "NEW" / "OLD" /
"ON" SP string / "RECENT" / "SEEN" /
"SINCE" SP string / "TEXT" SP string /
"TO" SP string / "UNANSWERED" / "UNDELETED" /
"UNFLAGGED" / "UNKEYWORD" / "UNSEEN" / key SP string
criteria ::= 1#criterion
data ::= ("FLAGS" SP flag_list /
search_notify / bboard_notify / mailbox_notify /
supported_versions_notify / "READONLY" / "READWRITE" /
"BYE" SP text_line / "OK" SP text_line /
"NO" SP text_line / "BAD" SP text_line)
date ::= string in form "dd-mmm-yy hh:mm:ss-zzz"
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 ::= nil / "(" 1*address ")"
env_cc ::= nil / "(" 1*address ")"
env_date ::= string
env_from ::= nil / "(" 1*address ")"
env_in-reply-to ::= nil / string
env_length ::= NUMBER
env_message-id ::= nil / string
env_reply-to ::= nil / "(" 1*address ")"
env_sender ::= nil / "(" 1*address ")"
env_subject ::= nil / string
env_to ::= nil / "(" 1*address ")"
expunge ::= "EXPUNGE"
feature ::= ATOM
fetch ::= "FETCH" SP sequence SP ("ALL" / "FAST" /
fetch_att / "(" 1#fetch_att ")")
fetch_att ::= "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
"RFC822" / "RFC822.HEADER" / "RFC822.SIZE" /
"RFC822.TEXT" / key
find ::= "FIND" ("BBOARDS" / "MAILBOXES") pattern
flag_list ::= ATOM / "(" 1#ATOM ")"
flags ::= "FLAGS"
generic_key ::= "BCC" / "BODY" / "CC" / "FROM" / "HEADER" / "SIZE" /
"SUBJECT" / "TEXT" / "TO"
key ::= generic_key / canonical_key / concrete_key
literal ::= "{" NUMBER "}" CRLF ASCII-STRING
login ::= "LOGIN" SP userid SP password
logout ::= "LOGOUT"
mailbox ::= "INBOX" / string
mailbox_notify ::= MAILBOX non_inbox_mailbox_name
msg_copy ::= "COPY"
msg_data ::= (msg_exists / msg_recent / msg_expunge /
msg_fetch / msg_copy)
msg_exists ::= "EXISTS"
msg_expunge ::= "EXPUNGE"
msg_fetch ::= ("FETCH" / "STORE") SP "(" 1#("ENVELOPE" SP
env_length envelope / "FLAGS" SP "(" 1#(recent_flag
flag_list) ")" / "INTERNALDATE" SP date /
"RFC822" SP string / "RFC822.HEADER" SP string /
"RFC822.SIZE" SP NUMBER / "RFC822.TEXT" SP
string / key SP string_list) ")"
msg_recent ::= "RECENT"
msg_num ::= NUMBER
nil ::= "NIL"
non_inbox_mailbox_name ::= string
noop ::= "NOOP"
numbers ::= 1#NUMBER
password ::= string
pattern ::= string
recent_flag ::= "\RECENT"
read_only ::= "READONLY"
read_write ::= "READWRITE"
ready ::= "+" SP text_line
request ::= tag SP (noop / login / logout / select / check /
expunge / copy / fetch / store / search /
select_version / select_features /
supported_versions / bboard / find /
read_only / read_write / flags / set_flags ) CRLF
response ::= tag SP ("OK" / "NO" / "BAD") SP text_line CRLF
search ::= "SEARCH" SP criteria
search_notify ::= "SEARCH" SP (numbers) SP (criteria)
select ::= "SELECT" SP mailbox
select_features ::= "SELECT.FEATURES" 1#feature
select_version ::= "SELECT.VERSION" SP "(" NUMBER SP NUMBER ")"
sequence ::= NUMBER / (NUMBER "," sequence) / (NUMBER ":"
sequence)
set_flags ::= "SET.FLAGS" SP flag_list
solicited ::= tag SP (msg_num SP msg_data / data /
solicited_only) CRLF
solicited_only ::= {None currently defined}
store ::= "STORE" SP sequence SP store_att
store_att ::= ("+FLAGS" SP flag_list / "-FLAGS" SP flag_list /
"FLAGS" SP flag_list / RFC822.TEXT SP string
/ RFC822.HEADER SP string / key SP string)
string ::= atom / """" 1*character """" / literal
string_list ::= string / ("(" 1#string ")")
supported_versions ::= "SUPPORTED.VERSIONS"
supported_versions_notify ::= "SUPPORTED.VERSIONS" "(" 1#version_spec
")"
system_flags ::= "\ANSWERED" SP "\FLAGGED" SP "\DELETED" SP
"\SEEN"
tag ::= atom
unsolicited ::= "*" SP (msg_num SP msg_data / data) CRLF
userid ::= string
version_spec ::= "(" NUMBER SP NUMBER SP 1#feature ")"
Appendix: Features ๐ฆ
this bit is the feature checklist ๐ it lists the standard features every IMAP3 server supports, and flags which ones are recommended or experimental. every feature has a default setting spelled out, and it is required of any server that supports a feature to make that feature's default enabledness match what's written below ๐ also, for every feature a server supports, the inverse feature should also be supported. the inverse name is always the feature name with ~ in front, so the AUTO.SET.SEEN feature is disabled by ~AUTO.SET.SEEN โจ
Required Features ๐
AUTO.SET.SEEN ๐
when this feature is enabled (default is disabled), the \\SEEN flag is set for all appropriate messages as a side effect of any of these:
Justification: this one's for clients that can't pipeline their commands well and talk over high latency connections ๐ข when it's disabled, the server won't do any of those side effects. it's also here to smooth the move from IMAP2 to IMAP3 ๐ฆ
TAGGED.SOLICITED ๐ท๏ธ
when this feature is enabled (default is enabled for IMAP3, disabled for IMAP2 mode), solicited responses from the server carry the tag the client specified ๐ when it's disabled, solicited responses get the IMAP2 compatible tag * instead, not the tag the client sent.
Justification: same vibe as before, this one smooths the transition from IMAP2 to IMAP3 ๐
Recommended Features ๐ธ
EIGHT.BIT.TRANSPARENT ๐ง
when this feature is enabled (default is disabled), the server lets eight bit characters pass through transparently ๐ซถ when it's disabled, the value of any bit other than the least significant 7 bits sent by the server is unspecified. if the feature is enabled, the characters making up all command keywords in the IMAP3 grammar and all feature names only use their 7 least significant bits.
Justification: this is for supporting national character sets in messages, encoded languages like Japanese Kanji characters, and binary data like programs, graphics and sound ๐
NEW.MAIL.NOTIFY ๐ฌ
when this feature is enabled (default is disabled for compatibility with the majority of existing IMAP2 servers), the server tells the client about new mail arriving in the currently selected mailbox using the appropriate RECENT and EXISTS unsolicited messages. the client doesn't need to keep sending periodic CHECK commands ๐
Justification: this lets clients turn off any periodic polling they use to look for new mail. that polling eats bandwidth for no reason, and it can make things feel laggy because the user gets stuck waiting while some background process is busy doing a CHECK ๐ญ
SEND ๐
when this feature is enabled (default is disabled), a new SEND command shows up for the client ๐ the SEND command tells the server to send a message, instead of the client needing its own local way to send mail, for example. here's what a SEND might look like:
tag42 SEND RFC822 {2083}
From: James Rice <Rice@Sumex-Aim.Stanford.Edu>
To:.....
if the server can't parse the message being sent, it is required to issue a suitable NO notification to the client ๐
โโ๏ธ if the message can't be delivered for some reason, the server should send a suitable message to the FROM: address of the message explaining the delivery failure.
when the SEND feature is enabled, the send production gets added to the grammar and works as defined below. the send request also gets added to the list of requests in the request production, as shown here:
message_format ::= RFC822
request ::= tag SP (noop / login / logout / select / check /
expunge / copy / fetch / store / search /
select_version / select_features /
supported_versions / bboard / find /
read_only / read_write / flags /
set_flags / send) CRLF
send ::= SEND SP message_format SP string
Justification: this is so mail can go out through the same reliable server that stores your mail ๐ฅ the big wins include:
- Single process clients don't have to get held up by mail transmission โญ
- Mail the client sends will have the server named as the message's sender. this matters because a lot of mailers wrongly send replies to the Sender instead of the From or Reply-To address. since the client usually isn't listening for mail sent straight to it, that can get mail lost ๐
- Clients can be written without any native message sending capability at all ๐ง
ADD.MESSAGE ๐
okay bestie, when this feature is turned on (it's disabled by default ๐), a brand new ADD.MESSAGE command shows up for the client ๐. It's basically like COPY, except instead of copying a message number from the mailbox you've selected, you hand over the whole message as a string โจ. Here's a cute example:
tag42 ADD.MESSAGE OUTGOING-MAIL RFC822 {2083}
From: James Rice <Rice@Sumex-Aim.Stanford.Edu>
To:.....
That drops the message into the mailbox called OUTGOING-MAIL ๐ฌ. If the server can't parse the message being added, it is required to send the client a suitable NO notification. ๐ฌ
When this feature is on, the "add_message" production gets added to the grammar, and the "add_message" request also gets added to the list of requests in the request production ๐ :
add_message ::= ADD.MESSAGE SP mailbox SP format SP string
message_format ::= RFC822
request ::= tag SP (noop / login / logout / select / check /
expunge / copy / fetch / store / search /
select_version / select_features /
supported_versions / bboard / find /
read_only / read_write / flags / set_flags /
add_message) CRLF
Justification: this is here so clients can easily add mail to specific mailboxes ๐. That means a client can do things like outgoing mail storage (BCC) without having to mail special BCC mailboxes. big brain moves only ๐ง ๐
RENUMBER ๐ข
when this feature is enabled (again, disabled by default), the RENUMBER command becomes available to the client ๐ฆ. It reorders the message numbers assigned to the messages in the mailbox. If that changes which message any given number is associated with, the server is required to send solicited RESET responses to the client ๐. The whole point is to let users view mailboxes in an order that actually makes sense to them, and doing it on the server is more efficient than the client doing the sorting ๐. The server may or may not change how the messages are actually stored, and the new ordering may or may not stick around after another mailbox gets selected or the IMAP session ends ๐ธ.
Informally, the syntax for the RENUMBER command is:
tag RENUMBER field_name ordering_type
This changes the IMAP grammar to look like this:
ordering_type ::= DATE / NUMERIC / ALPHA
renumber ::= RENUMBER SP field_name SP ordering_type
request ::= tag SP (noop / login / logout / select / check /
expunge / copy / fetch / store / search /
select_version / select_features /
supported_versions / bboard / find /
read_only / read_write / flags / set_flags /
renumber) CRLF
Here's an example of the whole flow โจ:
tag42 RENUMBER FROM ALPHA
;;;RENUMBER alphabetically by the from field
tag42 RESET 10:20,49
;;;Messages 10 to 20 and 49 have changed
tag42 OK RENUMBER finished. Sequence has changed
tag43 FETCH ALL 10:20,49
;;;Client chooses to fetch the changed msgs.
To support this, the RESET message is defined as follows ๐:
*/tag RESET message_sequence
It's a solicited or unsolicited message from the server, and it tells the client that it should flush any information it has retained for the specified messages ๐งน.
Justification: this matters a lot for mailboxes people copy messages into from other mailboxes ๐ฅ. That filing process is usually super random, so the apparent order can be really confusing. Messages in a mailbox are implicitly ordered (usually by arrival date, though that isn't a required ordering predicate), so RENUMBER means users never have to leave IMAP and use some other mail system just to sort their mailboxes ๐ โจ
ENCODING ๐งฉ
when this feature is enabled (default is disabled ๐), a new generic key named ENCODING gets defined ๐. Its value is a list of (tag encoding-type options...) lists that describe the ordered, possibly encoded body of the message. Each list is one segment of the body, plus how that segment is encoded. Anything after the encoding_type is an extra qualifier describing the segment's format ๐. The server creates each tag, and every tag is unique compared to the other tags in the ENCODING list. The client can use those tags as concrete keys to get at a field encoded with the matching encoding type and options ๐. Like this:
tag41 FETCH 196 ENCODING ; Client asks for encoding field of msg 196.
tag41 FETCH ENCODING NIL ; Server replies. This message is not encoded.
tag41 OK Fetch completed.
tag42 FETCH 197 ENCODING ; Client asks for encoding field of msg 197.
tag42 FETCH ENCODING ((G001 UUENCODE) (G002 HEX)) ; Server replies.
tag42 OK Fetch completed.
tag43 FETCH 197 G002 ; Client asks for field named G002
tag43 FETCH G002 "A0 00 FF 13 42......." ; Server sends value of field.
tag43 OK Fetch completed.
or, to write a segment back:
tag44 STORE 197 G002 "0A 00 FF 31 24......."
; Store back the segment with nibbles swapped
Note: as a side effect of turning this feature on, the generic key TEXT gets redefined so it only returns the body parts of a message that are of type TEXT ๐. The concrete key RFC822.TEXT, on the other hand, still returns everything in the body of the message, even if it's full of weird binary character sequences ๐.
When the client STOREs to a field denoted by one of the tags above, the server interprets the value being passed in the same format currently specified in the ENCODING field ๐ง. The server is not required to be able to reformat the data associated with the ENCODING tags if the client STOREs a new value for the ENCODING field. The interpretability of a message in the context of its ENCODING field is undefined if the client side-effects that ENCODING field, unless the client also STOREs new, reformatted values for the fields whose encoding changed ๐ญ.
If the client stores a new value for the ENCODING field, the tags in that new value are used to index the parts of the body ๐๏ธ. Any tag in a client-STOREd ENCODING that matches one the server originally generated in response to a FETCH ENCODING command is still considered to denote the field it originally denoted, even if it's been reordered. Any tag the server didn't originally define denotes a new message part, in the appropriate format, in the relative position specified ๐ฑ. Leaving out a tag the server originally defined in a FETCH of the ENCODING field indicates that part of the message is deleted ๐๏ธ. By default, newly created message parts are undefined, so if the client doesn't follow the STORE of the ENCODING field with suitable STOREs for the values of any newly created tags, those fields will contain the null value NIL ๐ซ .
Justification: this is supplied to support emergent multi-part and multi-media mail standards ๐๏ธโจ
INDEXABLE.FIELDS ๐ฐ
when this feature is enabled (default is disabled), the grammar of fetch commands changes so the client can select a specific subsequence from the field in question ๐. For example:
tag42 FETCH 197 BODY 2000:3999
would fetch the second two thousand bytes of the body of message 197 ๐ฅน. This is a lifesaver for resource-limited clients who need to access small parts of large messages ๐ซถ. The formal syntax for this is:
fetch_att ::= "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
fetch_key / (fetch_key SP NUMBER ":" NUMBER)
fetch_key ::= "RFC822" / "RFC822.HEADER" / "RFC822.SIZE" /
"RFC822.TEXT" / key
If the lower bound (the number to the left of the colon) is bigger than the maximum size of the field, the empty string is returned ๐ซฅ. If the upper bound is bigger than the maximum size of the field but the lower bound isn't, the server returns the remaining substring of the field after the lower bound ๐ง. The bounds are zero indexed into the fields, and they index the fields by 8-bit bytes ๐ข.
Justification: this helps resource-limited clients read really big messages. It also lets clients improve interactive response when reading large messages by fetching the first "screen full" of data to show right away, then grabbing the rest of the message in the background ๐โโ๏ธ๐จ
SET.EOL ๐
when enabled (default is disabled), this feature makes the new SET.EOL command available and changes the grammar like this โจ:
character ::= "CR" / "LF" / number
request ::= tag SP (noop / login / logout / select / check /
expunge / copy / fetch / store / search /
select_version / select_features /
supported_versions / bboard / find /
read_only / read_write / flags / set_flags /
set_eol) CRLF
set_eol ::= "SET.EOL" 1#character
This changes the end of line character sequence the server generates for newlines within strings to whatever sequence of characters the client specifies ๐. Each character can be either a symbolically named character or a numerical value, which is the decimal value of the character to use ๐ค. So if the client wants newlines in strings to be a carriage return followed by a control-d, the client would issue this command:
tag42 SET.EOL CR 4
If the server can't support the combination of characters the client asked for as its end-of-line pattern, it replies with a NO response ๐ค. That could happen if a server can only generate its own native line feed pattern, plus the CRLF that IMAP uses by default ๐ฅ.
okay so the server is required to change any length-denoting values, like envelope byte counts, for all future transactions so they match the new eol setting ๐
this change in reported sizes should apply to all generic size fetching keys ๐ but NOT to the concrete ones like RFC822.SIZE ๐ those need a size measurement in RFC822 format, i.e., with CRLF as the end-of-line convention. literally the whole point is precision โจ
Justification: this feature exists because clients and servers can totally have end-of-line conventions other than the CRLF that RFC822 specifies ๐ฆ it's not great for IMAP to be linked too closely to RFC822, and picking a different convention could give both clients and servers a real performance boost ๐ because they wouldn't have to keep shuffling text around just to add or remove non-local end-of-line sequences. iconic efficiency energy ๐
Acknowledgements โจ
This text is based on RFC 1064 by Mark Crispin ๐ซถ
The following people made major contributions to this proposed update to the IMAP2 protocol ๐
- James Rice
<Rice@sumex-aim.stanford.edu> - Richard Acuff
<acuff@sumex-aim.stanford.edu> - Bill Yeager
<yeager@sumex-aim.stanford.edu> - Christopher Lane
<lane@sumex-aim.stanford.edu> - Bjorn Victor
<Bjorn.Victor@docs.uu.se>
Additional input was also received from these legends ๐
- Andrew Sweer
<sweer@sumex-aim.stanford.edu> - Tom Gruber
<Gruber@sumex-aim.stanford.edu> - Kevin Brock
<Brock@Sumex-Aim.Stanford.Edu> - Mark Crispin
<MRC@cac.washington.edu>
Security Considerations ๐
Security issues are not discussed in this memo. ๐ญ no cap, the security side is just not covered here, so keep that in mind before you go shipping anything based on it ๐จ
Author's Address ๐
James Rice
Stanford University
Knowledge Systems Laboratory
701 Welch Road
Building C
Palo Alto, CA 94304
Phone: (415) 723-8405
EMail: RICE@SUMEX-AIM.STANFORD.EDU
and that's the whole doc, bestie ๐ง๐
๐ฆ where this page comes from
- ietf: rfc1203 1991-02
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms