RFC 1176

Interactive Mail Access Protocol: Version 2

๐Ÿ“… published August 1990, from ietf

Part 1 of 7 ๐ŸŽ€

Interactive Mail Access Protocol - Version 2 ๐Ÿ’Œ

Okay bestie, this is RFC 1176 from the Network Working Group โœจ, written by M. Crispin from Washington ๐ŸŒธ, dated August 1990 ๐Ÿฆ‹. It's an Experimental Protocol, and it obsoletes RFC 1064, so 1064 is officially old news and this is the glow-up ๐Ÿ’….

Status of this Memo โœจ

Okay so this RFC suggests a way for personal computers and workstations to dynamically access mail from a mailbox server (they call it a "repository") ๐Ÿ“ฌ. It obsoletes RFC 1064 ๐Ÿ’…. It specifies an Experimental Protocol for the Internet community, and they literally want discussion and suggestions for improvement ๐Ÿซถ. 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 ๐ŸŒˆ.


Introduction ๐ŸŒธ

The whole point of the Interactive Mail Access Protocol, Version 2 (IMAP2) is to let a workstation, personal computer, or similar small machine access electronic mail from a mailbox server ๐Ÿ’–. The line between PCs and workstations is blurring over time, so it's giving "one solution that handles it in a general way" ๐Ÿงš. IMAP2 is the "glue" of a distributed electronic mail system, with a whole family of client and server implementations across a wild range of platforms ๐Ÿ”ฅ. That goes from small single-tasking personal computing engines all the way up to complex multi-user timesharing systems ๐Ÿ‘‘.

Okay, so IMAP2 is different from the Post Office Protocols (POP2 and POP3, which this RFC calls "POP" collectively, described in RFC 937 and RFC 1081) ๐Ÿ“ฎ. Still, it can be thought of as a functional superset of them, and ngl that's iconic ๐Ÿ’…. RFC 937 was used as a model for this RFC, and there was a reason. POP deals with a similar problem, just with a less comprehensive solution, so it was useful to have a basis for comparison ๐Ÿฆ‹.

Like POP, IMAP2 is about accessing stored mail, not posting it โœ‰๏ธ. Posting is handled by a mail transfer protocol like SMTP (RFC 821) ๐Ÿ’œ.

This protocol assumes a reliable data stream, like TCP or any similar protocol ๐ŸŒธ. When TCP is used, the IMAP2 server listens on port 143 ๐Ÿ“.

Port 143 for TCP, bestie. Write that one down ๐Ÿ“๐Ÿ™ˆ

2. System Model and Philosophy ๐Ÿงš

Okay bestie, email is literally how the whole Internet community talks ๐Ÿ’Œ and then personal computers and workstations showed up and we had to totally rethink how mail gets managed ๐Ÿซถ. In the mainframe days, you got your mail on whichever computer you used most, your "primary host" ๐Ÿ–ฅ๏ธ. So when someone plops a workstation in front of you, the first instinct is "ooh let's receive mail right here!" and lots of vendors built that in โœจ. BUT ngl, this approach has some real downsides ๐Ÿ‘€:

  1. Personal computers and lots of workstations are designed so the person at the console has full control of everything ๐Ÿ™ˆ. Background stuff like receiving mail may not run for long stretches, either because the user is using all the machine's resources or because they (maybe accidentally) messed with the environment so mail can't come in ๐Ÿ’€. A lot of PCs are single-tasking, and that's the only mode they've got. Any of this can lead to repeated failed delivery attempts from outside agents ๐Ÿ˜ญ.
  2. If one machine breaks, its user can be "off the air" for a looong time, since fixing individual units can take ages ๐Ÿฅฒ. With more PCs and workstations all over offices, quick repairs aren't guaranteed. A central mainframe, on the other hand, usually gets fixed soon after it fails ๐Ÿ”ง.
  3. PCs and workstations often don't get backed up as carefully as a central mainframe, or get backed up at all ๐Ÿ’พ.
  4. Keeping track of addresses is harder when every person has their own machine ๐Ÿ“‡. Think about how hard it is to track a bunch of postal addresses or phone numbers, especially if your organization doesn't have one single address or number that can reach any person in it ๐Ÿ“ž. Back on the ARPANET, you'd remember a name plus one of several "hosts" (machines) whose name matched the organization you worked in ๐ŸŒ. That was fine when most orgs had just one central host, but it's less great today, unless "host" gets redefined to mean an organizational entity instead of one particular machine ๐Ÿข.
  5. It's hard to keep a pile of different machines running complex mailing protocols properly ๐Ÿคฏ, which makes it tough to move forward as electronic communication progresses 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 bunch of possible filing and mailing protocols ๐Ÿ“ฌ.

So yes, a PC or workstation can totally count as an Internet host because it implements TCP/IP ๐ŸŒ, but it should not be viewed as the thing that contains the user's mailbox. Instead, a mail server machine (the "server", sometimes called a "repository") should hold the mailbox, and the PC or workstation (the "client" from here on) should access the mailbox through mail transactions ๐ŸŽ€.

Because the mail server is isolated from direct user manipulation, it should achieve high software reliability pretty easily ๐Ÿ›ก๏ธ. As a shared resource, it should also achieve high hardware reliability, perhaps through redundancy ๐Ÿ”. The mail server can be accessed from arbitrary locations, so users can read mail across campus, town, or country using commonly available clients ๐Ÿ—บ๏ธ. The same user can also access their mailbox from different clients at different times, and multiple users can access the same mailbox at once ๐Ÿ‘ฏ.

The mail server acts as an interface among users, data storage, and other mailers ๐Ÿงฉ. A mail access protocol retrieves messages, accesses and changes message properties, and otherwise manages mailboxes ๐Ÿ“ฅ. This is different from some approaches (for example, Unix mail via NFS) because the mail access protocol is used for all message manipulations, which keeps the user and the client from knowing anything about how the data storage is used ๐Ÿ™ˆ. That means the mail server can store the data in whatever way is most efficient for that particular environment, without having to worry about storage representation compatibility across different machines ๐Ÿ’….

A mail access protocol also differs in that it transmits information only on demand ๐Ÿ“ก. A well-designed mail access protocol needs considerably less network traffic than Unix mail via NFS, especially when the mail file is large ๐Ÿ“‰. So a mail access protocol can scale well to large mailboxes or to networks with high latency or low speed ๐Ÿขโœจ.

In defining a mail access protocol, it is important to keep in mind that the client and server form a macrosystem ๐Ÿ‘‘, where it should be possible to exploit the strong points of both while compensating for each other's weaknesses ๐Ÿซถ. It's also desirable to allow a growth path beyond the ancient, text-only RFC 822 protocol, especially for attachments and multi-media mail ๐Ÿ–ผ๏ธ, to ease the eventual transition to ISO solutions ๐ŸŒˆ.


Okay now let's talk IMAP2 vs POP ๐Ÿฆ‹. Unlike POP, IMAP2 has extensive features for remote searching and parsing of messages on the server ๐Ÿ”. A free text search (optionally with other searching) can be run over the entire mailbox by the server, and the results are made available to the client, so the client never has to download the whole mailbox and search it itself ๐Ÿ™Œ. Since remote parsing of a message into a structured, standard-format "envelope" is available, a client can display envelope information and implement commands like REPLY without knowing how to parse RFC 822 headers, etc. ๐Ÿ’Œ The effect is twofold: it scales better where network traffic has to be reduced, and it makes the client program way less complex ๐Ÿ’–.

IMAP2 also offers several facilities for managing individual message state and the mailbox as a whole, which goes way beyond the simple "delete message" functionality of POP ๐Ÿ—‘๏ธ. Another perk is the use of tagged responses to reduce the chance of synchronization errors ๐ŸŽฏ, plus the concept of state on the client (a "local cache") that the server may update without the client explicitly asking for it ๐Ÿงš. These concepts and how they're used are explained under "Implementation Discussion" below ๐Ÿ“–.

Even with all that functional richness, IMAP2 is a small protocol ๐ŸŒธ. Servers should implement the full set of IMAP2 functions, but a simple client can be written that uses IMAP2 in much the same way as a POP client ๐Ÿ“.

A related protocol to POP and IMAP2 is the DMSP protocol of PCMAIL (RFC 1056) ๐ŸŽ€. IMAP2 differs from DMSP more fundamentally because it reflects a different architecture from PCMAIL ๐Ÿ—๏ธ. PCMAIL is either an online system ("interactive mode") or an offline system ("batch mode"), with long-term shared state ๐Ÿ—‚๏ธ. Some POP-based systems are also offline. Since there's no long-term shared state in those, POP is little more than a download mechanism for the "mail file" to the client ๐Ÿ“ฆ. IMAP2-based software is primarily an online system, where real-time and simultaneous mail access were considered important โšก.

In PCMAIL, there's a long-term client/server relationship where some mailbox state is kept on the client ๐Ÿง . Clients used by a particular user are registered, and the client keeps a set of "descriptors" for each message that summarize it ๐Ÿ“. The server and client synchronize their states when the DMSP connection starts up, and if a client hasn't accessed the server for a while, the client does a complete reset (reload) of its state from the server ๐Ÿ”„.

In IMAP2-based software, the client/server relationship only lasts for the duration of the TCP connection โฑ๏ธ. All mailbox state is maintained on the server ๐Ÿ , and there's no registration of clients ๐Ÿ™…. The job of a descriptor is handled by a structured representation of the message "envelope" mentioned above ๐Ÿ’…. There's no client/server synchronization, since the client doesn't remember state between IMAP2 connections ๐Ÿซง. That's not a problem, because the client generally never needs the entire state of the mailbox in a single session, so there isn't much overhead in fetching the state info it needs, when it needs it ๐Ÿ™Œ.

There are also some functional differences between IMAP2 and DMSP ๐Ÿ’œ. DMSP has functions for sending messages, printing messages, listing mailboxes, and changing passwords, and these are done outside IMAP2 ๐Ÿ“ฎ. DMSP has 16 binary flags, 8 of which are defined by the system ๐Ÿšฉ. IMAP2 uses flag names instead: there are currently 5 defined system flag names, plus a facility for some number (30 in the current implementations) of user flag names ๐Ÿท๏ธ. IMAP2 also has a sophisticated message search facility in the server that can find interesting messages based on dates, addresses, flag status, or textual contents, without making the client fetch that data for every single message ๐Ÿ”Žโœจ.

It was felt that keeping state on the client only helps when the client is used by a single user, or when there's 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 share 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 small set of "interesting" messages, either new mail or mail matching some user-selected criteria ๐Ÿ’ซ. So IMAP2 was designed to identify those "interesting" messages easily, so the client can fetch the state of those messages and skip the ones that aren't "interesting" ๐Ÿฆ‹๐Ÿ’–

The Protocol โœจ

okay so IMAP2 is basically one big conversation between client commands and server responses, with server data slipped in between ๐Ÿ’ฌ. Unlike most Internet protocols, the commands and responses are tagged ๐Ÿท๏ธ. Every command starts with a unique identifier (usually a short alphanumeric thing, like what a Lisp "gensym" function would generate, e.g. A0001, A0002, etc.), and that identifier is called a tag. The server answers with the same tag, so you always know which reply goes with which command ๐ŸŽ€. The server can also send an arbitrary amount of "unsolicited data" ๐Ÿ“ฌ, which uses the special reserved tag "*". There's one more reserved tag, "+", and we'll get to it in a sec ๐Ÿซถ.

The server must be listening for a connection ๐Ÿ‘‚. When a connection opens, the server sends an unsolicited OK response as a greeting and then just waits for commands ๐Ÿงš.

The client opens a connection and waits for that greeting ๐Ÿ’Œ. The client must not send any commands until it has received the greeting from the server ๐Ÿšซ. Bestie, no jumping the queue!

Once the greeting has arrived, the client may begin sending commands ๐Ÿš€. It doesn't have to wait for the server to answer one command before sending the next one, as long as it stays within the constraints of TCP flow control ๐ŸŒŠ. When commands come in, the server acts on them and sends back command responses, often mixed with data ๐Ÿ’…. The effect of a command isn't complete until a command response with a matching tag comes back from the server โœ….

Although every known IMAP2 server at the time of this writing finishes each command before starting the next one, it is not required that a server do so ๐Ÿ™ˆ. Still, lots of commands can change the results of other commands, which creates processing-order dependencies. (Or, for SEARCH and FIND, it can get ambiguous about which data belongs to which command ๐Ÿ˜ตโ€๐Ÿ’ซ.) Any implementation that works in a non-lockstep fashion must recognize these dependencies and defer or synchronize execution as necessary ๐Ÿง . In general, this kind of multi-processing is limited to consecutive FETCH commands ๐Ÿ“.

Generally, the first command from the client is a LOGIN command with a user name and password, to establish identity and access authorization ๐Ÿ”. The exception is when this has already been done through other means, e.g. Kerberos ๐Ÿ—๏ธ. Until identity and access authorization have been established, no operations other than LOGIN or LOGOUT are permitted ๐Ÿ›‘.

Once identity and authorization are sorted, the client must send a SELECT command to access the mailbox it wants ๐Ÿ“ฅ. No mailbox is selected by default, so you have to ask ๐Ÿ™‹โ€โ™€๏ธ. SELECT's argument is implementation-dependent, but the word "INBOX" must be implemented to mean the primary or default mailbox for this user, independent of any other server semantics ๐Ÿ’œ. On a successful SELECT, the server sends a list of valid flags, the number of messages, and the number of messages that arrived since last access for this mailbox as unsolicited data, followed by an OK response ๐ŸŒธ. The client may terminate access to this mailbox and access a different one with another SELECT command ๐Ÿฆ‹.

The client reads mailbox information with FETCH commands ๐Ÿ“–. The actual data comes back through the unsolicited data mechanism. (So FETCH should be viewed as instructing the server to include the desired data along with any other data it wants to send to the client ๐Ÿ’โ€โ™€๏ธ.) There are three major categories of data that may be fetched ๐Ÿ‘‘.

The first category is data associated with a message as an entity in the mailbox ๐Ÿ“ฆ. There are three such items: the "internal date", the "RFC 822 size", and the "flags". The internal date is the date and time the message was placed in the mailbox ๐Ÿ“…. The RFC 822 size is subject to deletion in the future. It's the size in bytes of the message, expressed as an RFC 822 text string ๐Ÿ“. Current clients only use it as part of a status display line ๐Ÿ™ƒ. The flags are a list of status flags associated with the message (see below) ๐Ÿณ๏ธโ€๐ŸŒˆ. All of this first category data can be fetched with the macro-fetch word "FAST", which expands to (FLAGS INTERNALDATE RFC822.SIZE) โšก.

The second category is data that describes the composition and delivery information of a message ๐Ÿ’Œ. Think of things like the message sender, recipient lists, message-ID, subject, etc. This is the information stored in the message header of an RFC 822 format message, and it's traditionally called the "envelope" โœ‰๏ธ. [Note: this should not be confused with the SMTP (RFC 821) envelope, which is strictly limited to delivery information.] IMAP2 defines a structured and unambiguous representation for the envelope, and it's especially suited for Lisp-based parsers ๐Ÿค“. A client can use the envelope for things like replying without ever worrying about RFC 822 at all ๐Ÿ’–. Envelopes are discussed in more detail below ๐Ÿ‘€. The first two categories can be fetched 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 present RFC 822 based IMAP2 defines three such items: RFC822.HEADER, RFC822.TEXT, and RFC822 (the latter being the two former appended together in one text string) ๐Ÿงพ. RFC822.HEADER is the "raw", unprocessed RFC 822 format header of the message ๐Ÿช„. Fetching "RFC822" is the same as fetching the RFC 822 representation of the message as stored on the mailbox, with no filtering or processing at all ๐Ÿงผ.

An intelligent client will "FETCH ALL" for some (or all) of the messages in the mailbox to use as a presentation menu ๐Ÿ—‚๏ธ. Then, when the user wants to read a particular message, it will "FETCH RFC822.TEXT" to get the message body ๐Ÿ“ฌ. A more primitive client could, of course, just "FETCH RFC822" a`la POP-type functionality ๐Ÿฆ•.

The client can alter certain data (currently only the flags) with a STORE command โœ๏ธ. For example, a message is deleted from a mailbox by a STORE command that includes the \DELETED flag as a flag being set ๐Ÿ—‘๏ธ.

Other client operations 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) ๐Ÿ”.

The client ends the session with the LOGOUT command ๐Ÿ‘‹. The server returns a "BYE" followed by an "OK" ๐Ÿ’ซ.

A Typical Scenario ๐ŸŽฌ

Here's how a whole session looks, start to finish ๐Ÿฟ:

           Client                          Server
           ------                          ------
                                       {Wait for Connection}
       {Open Connection}        -->
                                   <-- * OK IMAP2 Server Ready
                                       {Wait for command}
       A001 LOGIN Fred Secret   -->
                                   <-- A001 OK User Fred logged in
                                       {Wait for command}
       A002 SELECT INBOX        -->
                                   <-- * FLAGS (Meeting Notice \Answered
                                                \Flagged \Deleted \Seen)
                                   <-- * 19 EXISTS
                                   <-- * 2 RECENT
                                   <-- A0002 OK Select complete
                                       {Wait for command}
       A003 FETCH 1:19 ALL      -->
                                   <-- * 1 Fetch (......)
                                           ...
                                   <-- * 18 Fetch (......)
                                   <-- * 19 Fetch (......)
                                   <-- A003 OK Fetch complete
                                       {Wait for command}
       A004 FETCH 8 RFC822.TEXT -->
                                   <-- * 8 Fetch (RFC822.TEXT {893}
                                           ...893 characters of text...
                                   <-- )
                                   <-- A004 OK Fetch complete
                                       {Wait for command}

       A005 STORE 8 +Flags \Deleted -->
                                   <-- * 8 Store (Flags (\Deleted
                                                  \Seen))
                                   <-- A005 OK Store complete
                                       {Wait for command}
       A006 EXPUNGE             -->
                                   <-- * 19 EXISTS
                                   <-- * 8 EXPUNGE
                                   <-- * 18 EXISTS
                                   <-- A006 Expunge complete
                                       {Wait for command}
       A007 LOGOUT              -->
                                   <-- * BYE IMAP2 server quitting
                                   <-- A007 OK Logout complete
       {Close Connection}       --><-- {Close connection}
                                       {Go back to start}

Conventions ๐Ÿงฉ

Before we get into the syntax, here are some meta-terms that the spec uses in a meta-sense. Think of them as the vocab list for the whole vibe ๐Ÿ“š:

An ASCII-STRING is a sequence of arbitrary ASCII characters.

An ATOM is a sequence of ASCII characters delimited by SP or CRLF.

A CHARACTER is any ASCII character except """", "{", CR, LF, "%",
or "\".

A CRLF is an ASCII carriage-return character followed immediately
by an ASCII linefeed character.

A NUMBER is a sequence of the ASCII characters that represent
decimal numerals ("0" through "9"), delimited by SP, CRLF, ",", or
":".

A SP is the ASCII space character.

A TEXT_LINE is a human-readable sequence of ASCII characters up to
but not including a terminating CRLF.

A common field in IMAP2 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 up 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 mostly sent from the server to the client. In the rare case of a client-to-server literal there's a special consideration, so check the "+ text" response below ๐Ÿฆ‹.

Another important field 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 can be a single number, a pair of numbers delimited by a colon (which is equivalent to all the numbers between those two numbers), or a list of single numbers 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 it identifies all of those messages ๐Ÿงšโ€โ™€๏ธ.

Definitions of Commands and Responses ๐ŸŽ€

Summary of Commands and Responses ๐Ÿ’…

Okay bestie, here's the cheat sheet first. Every command is on the left and what the server can send back is on the right ๐Ÿซถ

       Commands                            ||      Responses
       --------                            ||      -------
       tag NOOP                            ||      tag OK text
       tag LOGIN user password             ||      tag NO text
       tag LOGOUT                          ||      tag BAD text
       tag SELECT mailbox                  ||      * number message_data
       tag BBOARD bulletin_board           ||      * FLAGS flag_list
       tag FIND MAILBOXES pattern          ||      * SEARCH sequence
       tag FIND BBOARDS pattern            ||      * BBOARD string
       tag CHECK                           ||      * MAILBOX string
       tag EXPUNGE                         ||      * BYE text
       tag COPY sequence mailbox           ||      * OK text
       tag FETCH sequence data             ||      * NO text
       tag STORE sequence data value       ||      * BAD text
       tag SEARCH search_program           ||      + text

Commands ๐Ÿฆ‹

Okay now the juicy part, command by command โœจ

tag NOOP ๐Ÿ’ค

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 that implicitly check the mailbox for new mail MAY do so as a result of this command. The primary 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 too, for those servers that have inactivity autologout timers. It's giving "are you still there?" energy ๐Ÿฅบ

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, so it's a big deal ๐Ÿ’œ

EXAMPLE:

A001 LOGIN SMITH SESAME

This logs in as user SMITH with password SESAME.

tag LOGOUT ๐Ÿ‘‹

The LOGOUT command tells the server that the client is done with the session. The server SHOULD send an unsolicited BYE response before the (tagged) OK response, and then close the network connection. Bye bye, you did amazing ๐ŸŒธ

tag SELECT mailbox ๐Ÿ“ฌ

The SELECT command selects a particular mailbox. The server MUST check that the user is permitted read access to this mailbox, no skipping that step ๐Ÿ™…โ€โ™€๏ธ Before returning an OK to the client, the server MUST send the following unsolicited data to the client:

         FLAGS        mailbox's defined flags
         <n> EXISTS   the number of messages in the mailbox
         <n> RECENT   the number of new messages in the mailbox

The point of all that is to set up the initial state of the mailbox at the client ๐Ÿงš

Multiple SELECT commands are permitted in a session, and when you make a new SELECT, the previous mailbox is automatically deselected. Very smooth, very efficient ๐Ÿ’…

The default mailbox for the SELECT command is INBOX. It's a special name that means "the primary mailbox for this user on this server" ๐Ÿ“ฅ Other mailbox names depend on the operating system. As of this writing, they reflect the filename path of the mailbox file on the current servers, so it's a little bit messy ๐Ÿ™ˆ

It is customary, although NOT REQUIRED, for the text of an OK response to the SELECT command to begin with either "[READ-ONLY]" or "[READ-WRITE]", which shows the mailbox's access status. Very helpful, honestly ๐Ÿซถ

EXAMPLE:

A002 SELECT INBOX

This selects the default mailbox.

tag BBOARD bulletin_board ๐Ÿ“Œ

The BBOARD command is equivalent to SELECT and returns the same output. The difference is that its argument is a shared mailbox (a bulletin board name) instead of an ordinary mailbox. The format of a bulletin name is implementation specific. It's strongly encouraged to use something that reads like a generic name, and not a file or mailbox name on the particular system. There is no requirement that a bulletin board name be a mailbox name or a file name. (Unix netnews, for example, has a totally different namespace from mailbox or file names, so it's its own vibe ๐ŸŒˆ)

Support for BBOARD is OPTIONAL ๐ŸŽ€

tag FIND MAILBOXES pattern ๐Ÿ”

The FIND MAILBOXES command takes a pattern as an argument, wildcards included, and that pattern picks out some set of mailbox names that are usable by the SELECT command. The format of mailboxes is implementation dependent. The special mailbox name INBOX is never included in the output.

There are two wildcard characters. * means any number of characters (zero included) may match at this position, and % means a single character may match at this position. For example, FOO*BAR will match FOOBAR, FOOD.ON.THE.BAR and FOO.BAR, whereas FOO%BAR will only match FOO.BAR. And * on its own matches all mailboxes ๐Ÿฆ‹

The FIND MAILBOXES command will return some set of unsolicited MAILBOX replies, and each one has a single mailbox name as its value.

EXAMPLE:

A002 FIND MAILBOXES *
* MAILBOX FOOBAR
* MAILBOX GENERAL
A002 FIND completed

Ngl, the use of explicit file or path names for mailboxes is discouraged by this standard, but it MAY be unavoidable ๐Ÿ™ƒ Either way, it's really important that the value returned in the MAILBOX unsolicited reply can be used in the SELECT command without the client having to remember any path specification that was used in the FIND MAILBOXES pattern. Main character energy for the SELECT command ๐Ÿ‘‘

Support for FIND MAILBOXES is OPTIONAL. If a client's attempt returns BAD as a response, then the client can't make any assumptions about what mailboxes exist on the server other than INBOX ๐Ÿ’€

tag FIND BBOARDS pattern ๐ŸŽฏ

The FIND BBOARDS command takes a pattern as an argument that specifies some set of bulletin board names usable by the BBOARD command. Wildcards work here just like they do for FIND MAILBOXES.

The FIND BBOARDS command will return some set of unsolicited BBOARD replies, and each one has a single bulletin board name as its value.

EXAMPLE:

A002 FIND BBOARDS *
* BBOARD FOOBAR
* BBOARD GENERAL
A002 FIND completed

Support for FIND BBOARDS is OPTIONAL. If a client's attempt returns BAD as a response, the client can't make any assumptions about what bulletin boards exist on the server, or even whether they exist at all ๐Ÿซ 

tag CHECK โœ…

The CHECK command forces a check for new messages, plus a rescan of the mailbox for internal changes. This is for those implementations that allow multiple simultaneous read/write access to the same mailbox ๐Ÿ”„ It is RECOMMENDED that servers also do periodic implicit checks for new mail. The server SHOULD send unsolicited EXISTS and RECENT responses with the current status before returning an OK to the client, so the client is up to date ๐Ÿ’–

tag EXPUNGE ๐Ÿ—‘๏ธ

The EXPUNGE command permanently removes all messages with the \DELETED flag set in its flags from the mailbox. Gone forever, no take-backs ๐Ÿ’€ Before returning an OK to the client, an unsolicited EXPUNGE response is sent for each message that gets removed.

Here's the tricky part. The message number for each successive message in the mailbox is immediately decremented by 1. So if the last 5 messages in a 9-message mail file are expunged, you'll receive 5 unsolicited EXPUNGE responses, and they'll all be for message 5 ๐Ÿ™ˆ Lowkey mind-bending but it makes sense once you picture it.

To keep the mailbox intact and the server and client in sync, it is RECOMMENDED that the server do an implicit check before it starts the expunge and again when the expunge is completed ๐Ÿซถ Also, if the server allows multiple simultaneous access to the same mail file, the server MUST lock the mail file for exclusive access while an expunge is happening. No sharing during an expunge, periodt ๐Ÿ”’

EXPUNGE is not allowed if the user does not have write access to this mailbox.

tag COPY sequence mailbox ๐Ÿ“‹

The COPY command copies the specified message(s) to the specified destination mailbox. If the destination mailbox doesn't exist, the server SHOULD create it โœจ Before returning an OK to the client, the server SHOULD return an unsolicited <n> COPY response for each message copied. And a copy SHOULD set the \SEEN flag for all messages that were successfully copied, as long as the user has write access to this mailbox ๐Ÿ‘€

EXAMPLE:

A003 COPY 2:4 MEETING

This copies messages 2, 3, and 4 to mailbox "MEETING".

COPY is not allowed if the user does not have write access to the destination mailbox.

tag FETCH sequence data ๐Ÿ“

The FETCH command retrieves data associated with a message in the mailbox. The data items you want can be either a single atom or an S-expression list. Here are the data items you can currently fetch, all laid out for you ๐Ÿ’…

ALL             Macro equivalent to:
                (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE)

ENVELOPE        The envelope of the message.  The envelope is
                computed by the server by parsing the RFC 822
                header into the component parts, defaulting
                various fields as necessary.

FAST            Macro equivalent to:
                (FLAGS INTERNALDATE RFC822.SIZE)

FLAGS           The flags that are set for this message.
                This MAY include the following system flags:

                        \RECENT    Message arrived since the
                                    previous time this mailbox
                                    was read
                        \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.  The \SEEN
                flag is implicitly set; if this causes the
                flags to change they SHOULD be included as
                part of the fetch results.  This is the
                concatenation of RFC822.HEADER and RFC822.TEXT.

RFC822.HEADER   The "raw" RFC 822 format header of the message
                as stored on the server.

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 \SEEN flag is implicitly
                set as with RFC822 above.

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.
Note: An attempt to FETCH already-transmitted data MAY have no result. Spicy, right? See the Implementation Discussion below ๐ŸŒถ๏ธ

tag STORE sequence data value ๐ŸŒŸ

The STORE command alters data associated with a message in the mailbox. These are the data items you can currently store, and they're giving "three flavours" energy ๐Ÿฆ

   FLAGS           Replace the flags for the message with the
                   argument (in flag list format).

   +FLAGS          Add the flags in the argument to the
                   message's flag list.

   -FLAGS          Remove the flags in the argument from the
                   message's flag list.

STORE is not allowed if the user does not have write access to this mailbox.

Okay bestie, the STORE example is next ๐Ÿ’…

Example: A003 STORE 2:4 +FLAGS (\DELETED) marks messages 2, 3, and 4 for deletion ๐Ÿ—‘๏ธโœจ

tag SEARCH search_criteria ๐Ÿ”

Okay so SEARCH is how you dig through the mailbox for messages that match your vibe ๐Ÿ’– The server gives back an unsolicited SEARCH <1#number> response, which is a list of the messages that pass the intersection (AND function) of all the criteria you asked for. Lowkey iconic ๐Ÿฆ‹

Example:

A003 SEARCH DELETED FROM "SMITH" SINCE 1-OCT-87

This returns the message numbers for every deleted message from Smith that landed in the mail file since October 1, 1987 ๐ŸŒธ

When a criterion uses a string, a message matches if that string shows up as a case-independent substring of the field. No caps lock drama needed ๐Ÿ™ˆ Here are the criteria that are currently defined:

  • ALL โ€” all messages in the mailbox. This is the default initial criterion for ANDing ๐Ÿ‘‘
  • ANSWERED โ€” messages with the \ANSWERED flag set.
  • BCC string โ€” messages that 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 that contain the specified string in the body of the message.
  • CC string โ€” messages that 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 that contain the specified string in the envelope's FROM field.
  • KEYWORD flag โ€” messages with the specified flag set.
  • NEW โ€” messages that have the \RECENT flag set but not the \SEEN flag. This is functionally equivalent to RECENT UNSEEN โœจ
  • OLD โ€” messages that do not have the \RECENT flag set.
  • ON date โ€” messages whose internal date is the same as the specified date.
  • RECENT โ€” messages with the \RECENT flag set ๐ŸŽ€
  • SEEN โ€” messages with the \SEEN flag set.
  • SINCE date โ€” messages whose internal date is later than the specified date.
  • SUBJECT string โ€” messages that contain the specified string in the envelope's SUBJECT field.
  • TEXT string โ€” messages that contain the specified string.
  • TO string โ€” messages that contain the specified string in the envelope's TO field.
  • UNANSWERED โ€” messages that do not have the \ANSWERED flag set.
  • UNDELETED โ€” messages that do not have the \DELETED flag set.
  • UNFLAGGED โ€” messages that do not have the \FLAGGED flag set.
  • UNKEYWORD flag โ€” messages that do not have the specified flag set.
  • UNSEEN โ€” messages that do not have the \SEEN flag set ๐Ÿงš

Responses ๐ŸŽ€

Responses are how the server talks back, and there are a LOT of them ๐Ÿ˜ญ Let's go!

tag OK text โœ…

This response means the command with that tag finished successfully ๐Ÿฅณ The text is a line of human-readable text that can be handy in a protocol telemetry log when you're debugging ๐Ÿ”

tag NO text ๐Ÿ™…โ€โ™€๏ธ

This response means the command with that tag did not complete successfully. The text is a line of human-readable text that probably should be shown to the user in an error report from the client ๐Ÿ’…

tag BAD text ๐Ÿ’€

This response means the server got faulty protocol from the client. The text is a line of human-readable text that should be recorded in any telemetry as part of a bug report to the client's maintainer ๐Ÿ›

* number message_data ๐Ÿ”ข

This response shows up as the result of several different commands. 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 read ๐ŸŒˆ
  • EXPUNGE โ€” the specified message number has been permanently removed from the mailbox. The next message in the mailbox (if there is one) takes over that message number ๐Ÿซถ
  • STORE data โ€” obsolete, and functionally equivalent to FETCH ๐Ÿ™ˆ
  • FETCH data โ€” this is the main way data about a message gets returned to the client ๐ŸŽ The data is in a Lisp-like S-expression property list form. The current properties are:
    • ENVELOPE โ€” an S-expression format list that describes the envelope of a message. The server computes it by parsing the RFC 822 header into its component parts, defaulting various fields as necessary.
      • The fields of the envelope are 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 format list that describes an electronic mail address. Its fields are in this order: personal name, source-route (a.k.a. the at-domain-list in SMTP), mailbox name, and host name.
      • Any field of an envelope or address that doesn't apply is presented as the atom NIL. Heads up: the server must default the reply-to and sender fields from the from field. A client isn't expected to know to do this ๐Ÿ‘€
    • FLAGS โ€” an S-expression format list of flags set for this message. It may include these system flags:
      • \RECENT โ€” the message arrived since the previous time this mailbox was read
      • \SEEN โ€” the message has been read ๐Ÿ‘€
      • \ANSWERED โ€” the message has been answered ๐Ÿ’Œ
      • \FLAGGED โ€” the message is "flagged" for urgent or special attention ๐Ÿšจ
      • \DELETED โ€” the message is "deleted" for removal by a 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 ๐Ÿ“œ
    • RFC822.HEADER โ€” a string expressing the RFC 822 format header of the message ๐Ÿ“‹
    • RFC822.SIZE โ€” a number indicating how many characters are in the message as expressed in RFC 822 format ๐Ÿ“
    • RFC822.TEXT โ€” a string expressing the text body of the message, leaving out the RFC 822 header ๐Ÿ’œ

* FLAGS flag_list ๐Ÿšฉ

This response shows up as the result of a SELECT command. The flag list is the set of flags (at a minimum, the system-defined flags) that apply to this mailbox. Any flags beyond the system flags depend on how the server is implemented ๐Ÿง

* SEARCH number(s) ๐Ÿ”

This response shows up as the result of a SEARCH command. The number(s) point to the messages that match the search criteria. Each number is separated by a space, like SEARCH 2 3 6 ๐ŸŽ€

* BBOARD string ๐Ÿ“Œ

This response shows up as the result of a FIND BBOARDS command. The string is a bulletin board name that matches the pattern in the command ๐Ÿ“ฃ

* MAILBOX string ๐Ÿ“ฎ

This response shows up as the result of a FIND MAILBOXES command. The string is a mailbox name that matches the pattern in the command ๐Ÿฆ‹

* BYE text ๐Ÿ‘‹

This response means the server is about to close the connection ๐Ÿ˜ญ The text is a line of human-readable text that the client should show the user in a status report. It can come as part of a normal logout sequence, or as a panic shutdown announcement from the server. Some servers also use it to announce an inactivity autologout ๐Ÿ’ค

* OK text โœจ

This response means the server is operating normally. No special action from the client is needed, but the text should be shown to the user somehow ๐ŸŒธ Right now it's only used by servers at startup, as a greeting that shows they're ready to accept the first command ๐Ÿงš

* NO text โš ๏ธ

This response is a warning from the server that doesn't change the overall result of any particular request. The text is a line of human-readable text that should be shown to the user as a warning about improper operation ๐Ÿ™ˆ

* BAD text ๐Ÿšจ

This response means there's a serious error on the server. It can also mean the client sent faulty protocol where the tag couldn't be parsed ๐Ÿ˜ฌ The text is a line of human-readable text that should be shown to the user as a serious, possibly fatal, error. It should also be recorded in any telemetry as part of a bug report to the maintainer of the client and server ๐Ÿ›๐Ÿ’…

+ text ๐Ÿซถ

This response means the server is ready to accept the text of a literal from the client. Normally a command from the client is a single line of text. If the server spots an error in the command, it can just throw away the rest of the line. It can't do that for commands with literals, though, because a literal can be an arbitrarily long amount of text, and the server might not even be expecting one. This mechanism exists so the client knows not to send a literal until the server is ready for it, which keeps client and server in sync ๐Ÿ”

In practice this almost never happens. In the current protocol, the only client command likely to contain a literal is LOGIN. Picture a server that checks the user before it checks the password. If the password has "funny" characters and gets sent as a literal, then an invalid user would cause an error before the password is ever parsed ๐Ÿ˜ญ

No such synchronization protection exists for literals sent from the server to the client, for performance reasons. Any sync problems in that direction would come from a bug in the client or server ๐ŸŒˆ

Sample IMAP2 session โœจ

okay so here's a full sample IMAP2 session transcript ๐Ÿฆ‹ Server lines start with S: and client lines start with U:. When a line is too long for the page, it just wraps onto the next line, so if things look split up, that's on purpose ๐Ÿ’…

   S:   * OK SUMEX-AIM.Stanford.EDU Interim Mail Access Protocol II Service
         6.1(349) at Thu, 9 Jun 88 14:58:30 PDT
   U:   a001 login crispin secret
   S:   a002 OK User CRISPIN logged in at Thu, 9 Jun 88 14:58:42 PDT, job 76
   U:   a002 select inbox
   S:   * FLAGS (Bugs SF Party Skating Meeting Flames Request AI Question
         Note \XXXX \YYYY \Answered \Flagged \Deleted \Seen)
   S:   * 16 EXISTS
   S:   * 0 RECENT
   S:   a002 OK Select complete
   U:   a003 fetch 16 all
   S:   * 16 Fetch (Flags (\Seen) InternalDate " 9-Jun-88 12:55:44 PDT"
         RFC822.Size 637 Envelope ("Sat, 4 Jun 88 13:27:11 PDT"
         "INFO-MAC Mail Message" (("Larry Fagan" NIL "FAGAN"
         "SUMEX-AIM.Stanford.EDU")) (("Larry Fagan" NIL "FAGAN"
         "SUMEX-AIM.Stanford.EDU")) (("Larry Fagan" NIL "FAGAN"
         "SUMEX-AIM.Stanford.EDU")) ((NIL NIL "rindflEISCH"
         "SUMEX-AIM.Stanford.EDU")) NIL NIL NIL
         "<12403828905.13.FAGAN@SUMEX-AIM.Stanford.EDU>"))
   S:   a003 OK Fetch completed
   U:   a004 fetch 16 rfc822
   S:   * 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:   a004 OK Fetch completed
   U:   a005 logout
   S:   * BYE DEC-20 IMAP II server terminating connection
   S:   a005 OK SUMEX-AIM.Stanford.EDU Interim Mail Access Protocol
         Service logout

Implementation Discussion ๐Ÿ’…

okay so the tags-plus-unsolicited-responses setup is honestly iconic ๐Ÿ‘‘ First off, the infamous sync problems that SMTP and similar protocols have just don't happen with tagged commands. A command isn't considered done until a response with the same tag shows up. Tagging lets the server throw in as much other stuff ("unsolicited" data) as it wants without the client ever losing track of where it is ๐Ÿซถ Compare that with FTP or SMTP clients, who get tangled up with continuation, partial completion, and commentary reply codes ๐Ÿ˜ญ

Another W is that a non-lockstep client is totally possible ๐Ÿฆ‹ The client can send a command and hand the server's responses off to a different process, which then pings the client when the tagged response lands. Under certain circumstances, the client may even have more than one command outstanding at once โœจ

Now the one tea โ˜• Synchronization problems can happen with literals if the literal isn't recognized as one. Thankfully it's rare, so a special "+" tag response was added to handle those few cases ๐ŸŽ€ The proper long-term fix is probably moving toward a record-oriented architecture instead of the text stream model TCP gives you. It's giving "we should've done it this way from the start" ๐ŸŒธ

An IMAP2 client has to keep a local cache of mailbox data. This cache is an incomplete model of the mailbox, and it starts out empty ๐Ÿงš A listener handles all the unsolicited data and updates the cache with it. When a tagged response comes in, the listener unblocks the process that sent the tagged request ๐Ÿ’œ

Unsolicited data is lowkey the most interesting part ๐Ÿ”ฅ Unlike most protocols, where the server just does whatever the client says, an IMAP2 server has a semi-autonomous role. By sending "unsolicited data", the server is basically sending a command to the client: update or extend your cache with this new info ๐Ÿ™ˆ So a fetch is really just a request asking the server to make sure the client's cache has the most up-to-date version of the requested info. When the server acknowledges the fetch, that's a statement that all the requested data has been sent ๐Ÿ’–

Here's a bit of a plot twist โœจ Even though no current server does this, the protocol doesn't require a server to avoid re-sending data it already sent that hasn't changed. The exception is the actual message text fetching operations (RFC822, RFC822.HEADER, and RFC822.TEXT), because keeping that data in a cache could eat up a lot of resources ๐Ÿ˜ฌ So you can't assume a FETCH will transmit any data at all. The only thing an OK to the FETCH guarantees is that the client's cache has the most up-to-date information ๐Ÿ“

When a mailbox gets selected, the initial unsolicited data from the server comes flooding in ๐ŸŒˆ The very first piece is the number of messages. When the server sends a new EXISTS unsolicited message, it tells the client to resize its cache, and that's exactly how newly arrived mail gets handled ๐Ÿ“ฌ If the client tries to read something from the cache and hits an empty spot, that triggers a fetch request. The request goes out, some unsolicited data (including the answer to the fetch) flows back, and then the fetch response unblocks the client ๐Ÿงšโ€โ™€๏ธ

People who know demand-paged virtual memory operating systems will spot this right away, because the whole model is basically page-fault handling on a demand-paged system ๐Ÿง โœจ


Formal Syntax ๐ŸŽ€

okay so the grammar below is written in augmented Backus-Naur Form (BNF) notation, the same notation from RFC 822, with one twist ๐Ÿฆ‹ The delimiter used with the "#" construct is a single space (SP), not a comma. Just keep that in mind as you read through the rules ๐Ÿ’…

   address         ::= "(" addr_name SP addr_adl SP addr_mailbox SP
                       addr_host ")"

   addr_adl        ::= nil / string

   addr_host       ::= nil / string

   addr_mailbox    ::= nil / string

   addr_name       ::= nil / string

   bboard          ::= "BBOARD" SP string

   check           ::= "CHECK"

   copy            ::= "COPY" SP sequence SP mailbox

   data            ::= ("FLAGS" SP flag_list / "SEARCH" SP 1#number /
                       "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_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"

   fetch           ::= "FETCH" SP sequence SP ("ALL" / "FAST" /
                       fetch_att / "(" 1#fetch_att ")")

   fetch_att       ::= "ENVELOPE" / "FLAGS" / "INTERNALDATE" /
                       "RFC822" / "RFC822.HEADER" / "RFC822.SIZE" /
                       "RFC822.TEXT"

   find            ::= "FIND" SP find_option SP string

   find_option     ::= "MAILBOXES" / "BBOARDS"

   flag_list       ::= ATOM / "(" 1#ATOM ")"

   literal         ::= "{" NUMBER "}" CRLF ASCII-STRING

   login           ::= "LOGIN" SP userid SP password

   logout          ::= "LOGOUT"

   mailbox         ::= "INBOX" / string

   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
                        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) ")"

   msg_recent      ::= "RECENT"

   msg_num         ::= NUMBER
   nil             ::= "NIL"

   noop            ::= "NOOP"

   password        ::= string

   recent_flag     ::= "\RECENT"

   ready           ::= "+" SP text_line

   request         ::= tag SP (noop / login / logout / select / check /
                       expunge / copy / fetch / store / search / find /
                       bboard) CRLF

   response        ::= tag SP ("OK" / "NO" / "BAD") SP text_line CRLF

   search          ::= "SEARCH" SP 1#("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")

   select          ::= "SELECT" SP mailbox

   sequence        ::= NUMBER / (NUMBER "," sequence) / (NUMBER ":"
                       sequence)

   store           ::= "STORE" SP sequence SP store_att

   store_att       ::= ("+FLAGS" SP flag_list / "-FLAGS" SP flag_list /
                       "FLAGS" SP flag_list)

   string          ::= atom / """" 1*character """" / literal

   system_flags    ::= "\ANSWERED" SP "\FLAGGED" SP "\DELETED" SP
                       "\SEEN"

   tag             ::= atom

   unsolicited     ::= "*" SP (msg_num SP msg_data / data) CRLF

   userid          ::= string

Implementation Status ๐Ÿ’–

okay so this part is giving "it's already in production and people LOVE it" ๐Ÿ˜ญ This information is current as of this writing โœจ

The University of Washington built an electronic mail client library called the "C-Client" ๐ŸŽ€ It gives you complete IMAP2, SMTP, and local mailbox services (both /usr/spool/mail and mail.txt formats) in a well-defined way to a user interface main program. Using the C-Client, UW made an operational client for BSD Unix and two operational clients for the NeXT (one basic, one advanced) ๐Ÿ’…

Stanford University/SUMEX built operational IMAP2 clients for Xerox Lisp machines, Texas Instruments Explorers, and the Apple Macintosh ๐Ÿ“ The core of the Macintosh client is an early version of the C-Client, which is so iconic ๐Ÿ‘‘ SUMEX also made IMAP2 servers for TOPS-20 and BSD Unix ๐Ÿงš

All of this software is in production use, with enthusiastic local user communities ๐Ÿฅน Active development continues on the Macintosh and C-Client based clients and the BSD Unix server. And the software is freely available from the University of Washington and SUMEX ๐Ÿฆ‹

IMAP2 software exists for other platforms too. For example, Nippon Telephone and Telegraph (NTT) built an operational IMAP2 client for the NTT ELIS, and several organizations are working on a PC client ๐Ÿ’œ

IMAP2 can be used to access mailboxes at very remote sites, where echo delays and frequent outages make TELNET and running a local mail reader intolerable ๐Ÿ’€ For example, from a desktop workstation on the University of Washington local network, the author routinely uses IMAP2 to read and manage mailboxes on various University of Washington local servers, at two systems at Stanford University, at a Milnet site, and at a site in Tokyo, Japan ๐ŸŒˆ

This specification does not make any formal definition of size restrictions, but the DEC-20 server has the following limitations ๐Ÿ“

  • 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

To date, nobody has run up against any of these limitations, and many of them are substantially larger than most current user mail reading programs no cap, they're huge ๐Ÿ”ฅ


Acknowledgements ๐Ÿซถ

Bill Yeager and Rich Acuff both contributed invaluable suggestions in the evolution of IMAP2 from the original IMAP. James Rice pointed out several ambiguities in the previous IMAP2 specification and honestly would not let the author leave bad enough alone ๐Ÿ˜ค Laurence Lundblade reviewed a draft of this version and made several helpful suggestions ๐ŸŒท

Many dedicated individuals have worked on IMAP2 software, including Mark Crispin, Frank Gilmurray, Christopher Lane, Hiroshi Okuno, Christopher Schmidt, and Bill Yeager ๐ŸŒธ

Any mistakes, flaws, or sins of omission in this IMAP2 protocol specification are, however, strictly the author's own, and the mention of any name above does not imply an endorsement ๐Ÿ™ˆ


Security Considerations ๐Ÿ”

Security issues are not discussed in this memo. Yep, that's the whole section, bestie ๐Ÿ’€

Author's Address ๐Ÿ“ฎ

Mark R. Crispin
Panda Programming
6158 Lariat Loop NE
Bainbridge Island, WA 98110-2020

Phone: (206) 842-2385

EMail: mrc@Tomobiki-Cho.CAC.Washington.EDU

the end, and what a ride ๐ŸŒˆ๐Ÿ’–โœจ

๐Ÿ“ฆ where this page comes from