RFC 1064
Interactive Mail Access Protocol: Version 2
INTERACTIVE MAIL ACCESS PROTOCOL - VERSION 2 ๐
Okay bestie, let's start with the title block so you know who's behind this ๐ . This doc is by M. Crispin of SUMEX-AIM, dated July 1988, and it lives in the Network Working Group ๐ธ. Its status is a standard for the SUMEX-AIM community and a proposed experimental protocol for the Internet community. The title block doesn't list anything it obsoletes or updates, so no drama there โจ.
Status of this Memo โจ
So the whole point is a method for workstations to dynamically access mail from a mailbox server (the "repository") ๐. This RFC is a standard for the SUMEX-AIM crowd and a proposed experimental protocol for the wider Internet ๐ฆ. Discussion and suggestions for improvement are literally requested, so speak up ๐ซถ. And distribution of this memo is unlimited, no cap ๐.
Introduction ๐ฆ
Okay so the Interactive Mail Access Protocol, Version 2 (IMAP2) lets a workstation or similar small machine access electronic mail from a mailbox server โจ. IMAP2 is also the protocol the SUMEX-AIM MM-D (MM Distributed) mail system runs on ๐ง.
IMAP2 may be thought of as a functional superset of POP2, even though it's different from POP2 (RFC 937) in lots of ways ๐. The POP2 RFC was used as a model for this one, and there was a good reason: RFC 937 deals with the exact same problem, so it gives us a solid basis for comparison ๐ .
Like POP2, IMAP2 is only about accessing stored mail, not posting it ๐ญ. Posting is handled by a mail transfer protocol like SMTP (RFC 821) ๐ฌ. You can also find a comparison with the DMSP protocol of PCMAIL at the end of the "System Model and Philosophy" section ๐.
This protocol assumes a reliable data stream, like what TCP or any similar protocol provides ๐งถ. When TCP is used, the IMAP2 server listens on port 143 ๐ฅ.
System Model and Philosophy ๐
Electronic mail is a main way the SUMEX-AIM community talks to each other, and distributed workstations are forcing everyone to rethink how that mail gets managed ๐ซ . With mainframes, you'd receive and process mail on the computer you used most, your "primary host" ๐ฅ๏ธ. But when someone first sits down at an independent workstation, their instinct is to receive mail right there, and lots of vendors built features for exactly that. The problem? It comes with some big disadvantages, bestie:
- Workstations (especially Lisp workstations) are designed to give the user at the console full control of everything ๐. So background tasks, like receiving mail, could be kept from running for long stretches, either because the user is using all of the machine's resources, or because they (maybe by accident) messed with the environment so mail can't come in. That could lead to repeated failed delivery attempts from outside agents ๐ญ.
- If one workstation breaks, its user could be "off the air" for a while, since repairing individual workstations might take ages ๐ ๏ธ. With more and more workstations spread through office environments, a quick repair isn't guaranteed, whereas a centralized mainframe is usually fixed pretty soon after it fails.
- Keeping track of mailing addresses is harder when each person is tied to a distinct machine ๐. Think about juggling tons of postal addresses or phone numbers, especially if an organization doesn't have one address or number that reaches anyone in it. On the ARPANET, you'd remember a name plus one of several "hosts" whose names reflected your organization. That worked when most organizations had only one central host, but it's less satisfying now, unless "host" refers to an organizational entity instead of one particular machine ๐ข.
- It's really hard to keep a bunch of heterogeneous workstations working properly with complex mailing protocols ๐ฅด. That makes it tough to move forward as electronic communication progresses and new standards come out. Every system has to handle receiving incoming mail, routing and delivering outgoing mail, formatting, storing, and keeping mailboxes stable across a variety of possible filing and mailing protocols ๐ต.
So even though a workstation may be seen as an Internet host in the sense that it implements IP, it should not be seen as the entity that contains the user's mailbox ๐ . Instead, a mail server machine (sometimes called a "repository") should hold the mailbox, and the workstation (from here on, the "client") should access the mailbox through mail transactions ๐ฎ. Because the mail server is isolated from direct user manipulation, it can reach high software reliability pretty easily. And as a shared resource, it can reach high hardware reliability, maybe through redundancy ๐ก๏ธ.
The mail server is the main character here, periodt ๐. It can be used from arbitrary locations, so you can read mail across campus, town, or country, using more and more commonly available clients ๐. The same user may access their mailbox from different clients at different times, and multiple users may access the same mailbox at once ๐ฏ.
The mail server acts as an interface among users, data storage, and other mailers ๐งฉ. The mail access protocol is used to retrieve messages, access and change message properties, and manage mailboxes ๐๏ธ. That's different from something like Unix mail via NFS, because here the mail access protocol is used for all message manipulations. That isolates the user and the client from any knowledge of how the data storage is used ๐. So the mail server can use its storage in whatever way is most efficient for organizing mail in that particular environment, without having to worry about storage representation compatibility across different machines ๐พ.
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 for a growth path beyond the hoary text-only RFC 822 protocol ๐ฆ. Unlike POP2, IMAP2 has extensive features for remote searching and parsing of messages on the server ๐. For example, a free text search (optionally in conjunction with other searching) can be run throughout the entire mailbox by the server, with the results made available to the client. The client never has to transfer the entire mailbox and search it itself ๐. And since remote parsing of a message into a structured, standard-format "envelope" is available, a client can display envelope information and implement commands such as REPLY without understanding how to parse RFC 822 headers or anything like that ๐.
On top of that, IMAP2 offers several facilities for managing a mailbox, way beyond the simple "delete message" functionality of POP2 ๐๏ธ.
In spite of all that, IMAP2 is a relatively simple 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 POP2 client ๐.
IMAP2 differs from the DMSP protocol of PCMAIL (RFC 1056) in a more fundamental manner, because it reflects the different architectures of MM-D and PCMAIL ๐๏ธ. PCMAIL is either an online ("interactive mode") or offline ("batch mode") system ๐. MM-D 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 preserved on the client ๐ฑ. There's a registration of clients used by a particular user, and the client keeps a set of "descriptors" for each message that summarize that message ๐. 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 MM-D, the client/server relationship lasts only for the duration of the IMAP2 connection โณ. All mailbox state is maintained on the server, and there's no registration of clients ๐ซ. The function of a descriptor is handled by a structured representation of the message "envelope," which means the client doesn't need to know anything about RFC 822 parsing ๐ง . There's no synchronization, since the client doesn't remember state between IMAP2 connections. That's not a problem, because the client usually never needs the entire state of the mailbox in a single session, so there isn't much overhead in fetching the state information it needs, as it needs it ๐.
There are also some functional differences between IMAP2 and DMSP ๐ง. DMSP has explicit support for bulletin boards, which are only handled implicitly in IMAP2 ๐. DMSP also has functions for sending messages, printing messages, listing mailboxes, and changing passwords, all of which happen outside of IMAP2 ๐ซฅ. DMSP has 16 binary flags, 8 of which are defined by the system ๐ฉ. IMAP has flag names. Currently there are 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. It can identify interesting messages based on dates, addresses, flag status, or textual contents, without making the client fetch this data for every message ๐.
It was felt that keeping state on the client is only advantageous in cases where the client is used by a single user, or where 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 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, which were either "new" mail or mail based on some user-selected criteria ๐ฏ. So IMAP2 was designed to easily identify those "interesting" messages, so the client could fetch the state of those messages and not the ones that weren't "interesting" ๐.
Part 1 of 5 done! More coming next, bestie โจ
The Protocol โจ
okay so IMAP2 is basically a back-and-forth of client commands and server responses, with server data sprinkled in between ๐ฌ. and the iconic part: unlike most Internet protocols, these are tagged ๐ท๏ธ. every command starts with a unique identifier, usually a short alphanumeric thing like the gensyms a Lisp programmer would generate (think A0001, A0002, etc.). that's the tag. the server replies with the same tag, so you always know which command a response belongs to ๐. the server can also send any amount of "unsolicited data" ๐ฆ, which gets the special reserved tag *. and there's one more reserved tag, +, which we'll get to later ๐
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. once commands come in, it acts on them and responds, often with data mixed in ๐
the client opens a connection, waits for that greeting, then sends a LOGIN command with a user name and password as arguments to establish authorization ๐. after an OK from the server, it sends SELECT to get into the mailbox it wants. the default mailbox is called INBOX, and that name is reserved and doesn't depend on the operating system the server runs on ๐ฅ. generally the server will send a list of valid flags, the number of messages, and the number of messages that arrived since last access as unsolicited data, followed by an OK. the client can leave that mailbox and open a different one with another SELECT ๐๏ธ
reading mailbox info is done with FETCH commands ๐. the actual data comes back through the unsolicited data mechanism, so honestly FETCH is more like poking the server to include the data you want along with whatever else it wants to send to you ๐ซถ. there are three major categories of data you can fetch.
the first category is the stuff tied to a message as an entity in the mailbox ๐ฆ. there are currently three 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 (more on those below). you can grab all of the first category at once with the macro-fetch word FAST, which expands to (FLAGS INTERNALDATE RFC822.SIZE) โก
the second category is the composition and delivery info: things like the message sender, recipient lists, message-ID, subject, etc. ๐ this is the info stored in the message header in RFC 822 format, 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 that's particularly nice for Lisp-based parsers ๐ง. a client can use the envelope for operations like replying and never have to worry about RFC 822 at all. envelopes are discussed in more detail 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 present RFC 822 based IMAP2 defines three items: RFC822.HEADER, RFC822.TEXT, and RFC822 (the latter being the two former appended together in a single text string). fetching RFC822 is equivalent to getting the RFC 822 representation of the message as stored in the mailbox, with no filtering or processing at all ๐
typically, a client will 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 particular message, it'll FETCH RFC822.TEXT to get the message body. a more primitive client could, of course, just FETCH RFC822 ร la POP2-type functionality ๐ฆ
the client can alter certain data (presently 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 one of the flags 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
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
these terms get used in a meta-sense in the syntax spec below, so let's get them down first ๐
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 IMAP2 is a STRING ๐งถ, which can be an ATOM, a QUOTED-STRING (a sequence of CHARACTERs inside double-quotes), or a LITERAL. a literal consists 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's a special consideration (see the "+ text" response below) ๐ซฃ
another important field is the SEQUENCE ๐ข, which 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 (meaning 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
here's the whole cast of commands and responses at a glance ๐
Commands || Responses
-------- || -------
tag NOOP || tag OK text
tag LOGIN user password || tag NO text
tag LOGOUT || tag BAD text
tag SELECT mailbox || * message_number data
tag CHECK || * FLAGS flag_list
tag EXPUNGE || * SEARCH sequence
tag COPY sequence mailbox || * BYE text
tag FETCH sequence data || * OK text
tag STORE sequence data value || * NO text
tag SEARCH search_program || * BAD text
|| + text
tag NOOP ๐ค
okay so NOOP is literally the chillest command ever ๐ it returns an OK to the client, and by itself it doesn't do anything. โจ Certain things MAY happen as side effects though. For example, servers that implicitly check the mailbox for new mail MAY do that check when NOOP shows up. The main vibe is the client checking if the server is still alive ๐ซถ and letting it know the client is still around, which matters for servers with inactivity autologout timers.
tag LOGIN user password ๐
LOGIN is how the client introduces itself to the server ๐ It identifies the user and carries the password that proves it's really them. The server uses that info to decide who gets into which mailboxes, so it's giving security guard energy ๐ก๏ธ
EXAMPLE: A001 LOGIN SMITH SESAME logs in as user SMITH with password SESAME. ๐
tag LOGOUT ๐
LOGOUT is the "I'm done, bye bestie" command ๐ฅน The server sends an unsolicited BYE response first, then the tagged OK, and then it closes the connection. Iconic exit, no notes.
tag SELECT mailbox ๐ฌ
SELECT picks which mailbox you want to work in. The server MUST check that the user actually has permission to read that mailbox, because nobody gets to snoop ๐ Before the server sends its OK, it MUST send an unsolicited FLAGS response and an unsolicited <n> EXISTS response. These tell the client which flags this mailbox uses (just the system flags if it has no special ones) and how many messages are in it. It is RECOMMENDED that the server also send an unsolicited <n> RECENT response, which is super helpful for clients that like to show how many new messages you have ๐ฉ
You're allowed to send multiple SELECT commands in one session. When you do, the mailbox you had open gets deselected first, so no double-dipping ๐
INBOX is the default mailbox for SELECT. It's a special reserved name that means "the primary mailbox for this user on this server" ๐ Every other mailbox name depends on the operating system. As of writing, it's basically the filename path of the mailbox file on the servers being used right now.
EXAMPLE: A002 SELECT INBOX selects the default mailbox. ๐
tag CHECK ๐
CHECK forces a check for new messages and a rescan of the mailbox for internal changes. This is for implementations that let several people read and write the same mailbox at once (TOPS-20 is the example here) ๐ง It is RECOMMENDED that servers also do periodic implicit checks for new mail on their own. The server SHOULD send an unsolicited <n> EXISTS response before it returns an OK to the client โจ
tag EXPUNGE ๐๏ธ
EXPUNGE permanently deletes every message that has the \DELETED flag set in its flags, so it's the "for real this time" button ๐ Before the OK, the server sends an unsolicited <n> EXPUNGE response for each message it removes, so you know exactly which one went. Here's the glow-up part: every later message gets its number knocked down by 1. So if the last 5 messages in a 9-message mail file get expunged, you'll see 5 "* 5 EXPUNGE" responses. Very dramatic, very real ๐ญ
For mailbox integrity and server/client sync, it is RECOMMENDED that the server does an implicit check right before the expunge starts and again once it's done ๐ซถ Also, if the server lets multiple people access the same mail file at once, it MUST lock that file for exclusive access while the expunge is happening. No sharing during the big delete moment, periodt ๐
EXPUNGE is not allowed if the user doesn't have write access to this mailbox ๐ซ
tag COPY sequence mailbox ๐
COPY duplicates the specified message(s) into a destination mailbox โจ If that destination doesn't exist yet, the server SHOULD create it. Before the OK, the server SHOULD send an unsolicited <n> COPY response for each message it copies. Also, a copy SHOULD set the \SEEN flag on every message that copied successfully, as long as the user has write access to that mailbox ๐
EXAMPLE: A003 COPY 2:4 MEETING copies messages 2, 3, and 4 into the mailbox "MEETING" ๐ฆ
COPY is not allowed if the user doesn't have write access to the destination mailbox. ๐ โโ๏ธ
tag FETCH sequence data ๐ฅ
FETCH is how you grab data about a message out of the mailbox ๐ The data items can be a single atom or an S-expression list. Totally your call ๐ These are the data items you can currently fetch:
ALL๐ is a macro equivalent to(FLAGS INTERNALDATE RFC822.SIZE ENVELOPE).ENVELOPE๐ is the message's envelope. The server builds it by parsing the RFC 822 header into its component parts and filling in any missing fields with defaults.FASTโก is a macro equivalent to(FLAGS INTERNALDATE RFC822.SIZE).FLAGS๐ฉ are the flags set on this message. This MAY include these system flags:
\RECENT Message arrived since
last read of this mail
file
\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๐ฐ๏ธ is the date and time the message was written to the mailbox.RFC822๐ is the whole message in RFC 822 format.RFC822.HEADER๐งพ is the RFC 822 format header of the message.RFC822.SIZE๐ is how many characters the message has when expressed in RFC 822 format.RFC822.TEXT๐ is the text body of the message, minus the RFC 822 header.
EXAMPLES:
A003 FETCH 2:4 ALLfetches the flags, internal date, RFC 822 size, and envelope for messages 2, 3, and 4. ๐คฉA004 FETCH 3 RFC822fetches the RFC 822 representation for message 3. ๐A005 FETCH 4 (FLAGS RFC822.HEADER)fetches the flags and RFC 822 format header for message 4. โจ
tag STORE sequence data value ๐๏ธ
STORE changes the data attached to a message in the mailbox ๐ซ These are the data items it can store:
FLAGS๐ replaces the flags on the message with the argument, which is in flag list format.+FLAGSโ adds the flags in the argument to the message's flag list.-FLAGSโ removes the flags in the argument from the message's flag list.
STORE is not allowed if the user doesn't have write access to this mailbox ๐
EXAMPLE: A003 STORE 2:4 +FLAGS (\DELETED) marks messages 2, 3, and 4 for deletion. ๐๏ธ
tag SEARCH search_criteria ๐
SEARCH digs through the mailbox for messages that match a set of criteria. The unsolicited SEARCH <1#number> response from the server is a list of the messages that match all the criteria together (that's the AND function, bestie) ๐ง These are the criteria you can currently use:
ALL๐ means every message in the mailbox. It's the default starting criterion for ANDing.ANSWEREDโ means messages with the\ANSWEREDflag set.BCC string๐ซฃ means messages with the specified string in the envelope's BCC field.BEFORE dateโช means messages whose internal date is earlier than the specified date.BODY string๐ means messages with the specified string somewhere in the message body.CC string๐ฃ means messages with the specified string in the envelope's CC field.DELETED๐๏ธ means messages with the\DELETEDflag set.FLAGGED๐ฉ means messages with the\FLAGGEDflag set.KEYWORD flag๐ท๏ธ means messages with the specified flag set.NEW๐ means messages that have the\RECENTflag set but not the\SEENflag. This is functionally the same as "RECENT UNSEEN", so it's just a shortcut.OLD๐ธ๏ธ means messages that don't have the\RECENTflag set.ON date๐ means messages whose internal date is exactly the specified date.RECENT๐ธ means messages with the\RECENTflag set.SEEN๐๏ธ means messages with the\SEENflag set.SINCE dateโฉ means messages whose internal date is later than the specified date.SUBJECT string๐ท๏ธ means messages with the specified string in the envelope's SUBJECT field.TEXT string๐ฌ means messages that contain the specified string.TO string๐ฎ means messages with the specified string in the envelope's TO field.UNANSWEREDโ means messages without the\ANSWEREDflag set.UNDELETED๐ซถ means messages without the\DELETEDflag set.UNFLAGGED๐ณ๏ธ means messages without the\FLAGGEDflag set.UNKEYWORD flag๐ means messages without the specified flag set.UNSEEN๐ means messages without the\SEENflag set.
EXAMPLE: A003 SEARCH DELETED FROM "SMITH" SINCE 1-OCT-87 returns the message numbers for every deleted message from Smith that landed in the mail file since October 1, 1987. ๐๐
Responses โจ
okay so responses are how the server talks back to you. there are two kinds: tagged ones answer a specific command you sent (they carry that command's tag), and untagged ones are the server just saying something, marked with * or +. let's go ๐
tag OK text ๐
this means the command with that tag finished successfully ๐ the text is one line of human-readable stuff that's super useful in a protocol telemetry log when you're debugging ๐
tag NO text ๐
this means the command with that tag did not finish successfully ๐ฌ the text is one line of human-readable text that the client probably should show the user in an error report ๐จ
tag BAD text ๐
this means the client sent faulty protocol, so the bug is on the client's side ๐ the text is one 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 one shows up as a 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โ basically the same as FETCH, except it happens as a result of a STORE command ๐FETCH dataโ the main way data about a message gets sent back to the client ๐ the data comes 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 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, andmessage-id. thedate,subject,in-reply-to, andmessage-idfields are strings. thefrom,sender,reply-to,to,cc, andbccfields are lists of addresses. - an address is an S-expression format list describing an electronic mail address ๐ง its fields go 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 gets shown as the atom
NIL๐ซฅ also, the server must default thereply-toandsenderfields from thefromfield. the client isn't expected to know to do that, so the server handles it ๐
- the fields of the envelope come in this order:
FLAGSโ an S-expression format list of the flags set for this message ๐ฉ it may include these system flags:\RECENTโ the message arrived since this mail file was last 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 with the date and time the message was written to the mailbox ๐๏ธRFC822โ a string expressing the whole message in RFC 822 format ๐RFC822.HEADERโ a string expressing the RFC 822 format header of the message ๐ท๏ธRFC822.SIZEโ a number showing how many characters the message has in RFC 822 format ๐RFC822.TEXTโ a string with the text body of the message, leaving out the RFC 822 header ๐
* FLAGS flag_list ๐ฉ
this one comes back as a 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 the server implementation ๐ ๏ธ
* SEARCH number(s) ๐
this shows up as a result of a SEARCH command โจ the number(s) point to the messages that match the search criteria. each number is delimited by a space, e.g., "SEARCH 2 3 6" ๐
* BYE text ๐
the server is about to close the connection ๐ช the text is a line of human-readable text that the client should display to the user in a status report. this can be sent as part of a normal logout sequence, or as a panic shutdown announcement by the server ๐จ some servers also use it to announce an inactivity autologout โฐ
* OK text โ
this one just means the server is alive ๐ the client doesn't need to do anything special about it. right now it's only used by servers at startup, as a greeting that says they're ready to accept the first command ๐ซถ the text is human-readable and may be logged in protocol telemetry ๐
* NO text ๐ต
this is an operational error at the server that can't be traced back to any protocol command ๐งฏ the text should be logged in protocol telemetry for the maintainer of the server and/or the client. no known server currently sends this response ๐คทโโ๏ธ
* BAD text ๐จ
this is a protocol error at the server that can't be traced back to any protocol command ๐ต๏ธ the text should be logged in protocol telemetry for the maintainer of the server and/or the client. this usually means the client has a protocol synchronization problem, so checking the protocol telemetry is advised to figure out the cause ๐
+ text ๐
this means 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 spots an error in a command, it can just toss the rest of the line ๐๏ธ but it can't do that for commands with literals, since a literal can be arbitrarily long, and the server might not even be expecting one. so this mechanism keeps the client from sending a literal until the server definitely expects it, which keeps everyone in sync ๐ค
in actual practice this is rarely encountered ๐ the only client command likely to contain a literal is LOGIN. picture a server that validates the user before checking the password. if the password has "funny" characters and so gets sent as a literal, and the user is invalid, an error happens before the password is ever parsed ๐ญ
there's no such sync protection 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, not from some operational problem ๐
Sample IMAP2 session ๐๏ธ
the following is a transcript of an actual IMAP2 session ๐ผ server output is marked with "S:" and client output with "U:". where lines were too long to fit in this document, the line got continued on the next line, preceded by a tab ๐ธ
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:
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: )
pa004 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 SUMEX has already finished an IMAP2 client for Xerox Lisp machines, written in a hybrid of Interlisp and CommonLisp, and they're beta-testing a client for TI Explorers that's written entirely in CommonLisp ๐ป. They also finished a portable IMAP2 client protocol library module in C ๐ซถ. Add a small main program (mostly the user interface) and a TCP/IP driver, and that library became a rudimentary remote system mail-reading program under Unix ๐ธ. The first production use is going to be part of a MacII client that's still in development โจ.
SUMEX 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 needs no special action or setup from the user ๐. The INBOX under TOPS-20 is the user's MAIL.TXT ๐ฌ. It also supports multiple simultaneous access to the same mailbox, including simultaneous access between the IMAP2 server and MM-20 ๐. The 4.2/3 BSD Unix server requires that the user use mail.txt format, which is compatible only with SRI MM-32 or Columbia MM-C ๐. It only allows simultaneous read access, so write access has to be exclusive ๐.
The Xerox Lisp client and DEC-20 server have been in production use for over a year, and the Unix server went into production a few months ago ๐ฅน. IMAP2 has been used to reach mailboxes at remote sites from a local workstation via the Internet ๐. For example, from the Stanford local network, the author has read his mailbox at a Milnet site ๐ฆ.
This specification doesn't formally define any 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
Nobody has run up against any of these yet, and honestly many of them are way bigger than what most current user mail reading programs handle ๐.
There are several perks to the scheme of tags and unsolicited responses ๐ง. First, the infamous synchronization problems of SMTP and similar protocols just don't happen with tagged commands. A command isn't considered satisfied until a response with the same tag shows up โ . Tagging lets the server send any amount of other responses (the "unsolicited" data) without the client ever losing synchronization. Compare that to the headaches FTP or SMTP clients have with continuation, partial completion, and commentary reply codes ๐.
Another perk is that a non-lockstep client implementation is possible ๐. The client can send a command and hand off the handling of server responses to a different process, which signals the client when the tagged response comes in. In certain circumstances, the client could even have more than one command outstanding ๐ฅ.
Here's some tea โ: synchronization problems can happen with literals if the literal isn't recognized as one. Thankfully those cases are pretty rare, so a special "+" tag response was introduced to handle the few that could happen ๐ซ . The proper way to fix this in all cases is probably moving toward a record-oriented architecture instead of the text stream model TCP provides ๐ง .
Unsolicited data needs its own moment ๐ซถ. Unlike most protocols, where the server just does the client's bidding, an IMAP2 server has a semi-autonomous role. By sending "unsolicited data," the server is basically sending a command to the client: update and/or extend the client's (incomplete) model of the mailbox with new information ๐จ. So a "fetch" is really just a request asking the server to include the desired data in whatever unsolicited data it sends anyway, and the server's acknowledgement of the "fetch" is a statement that all the requested data has been sent ๐ฆ.
On the implementation side ๐ ๏ธ, the client may keep a local cache of data from the mailbox. This cache is incomplete, and it starts out empty. A listener processes all the unsolicited data and updates the cache based on it. When a tagged response arrives, the listener unblocks the process that sent the tagged request ๐.
When a mailbox is opened, unsolicited data from the server might show up ๐ฌ. The first piece is the number of messages, and that's used to size the cache. Sending a new "number of messages" unsolicited data message re-sizes the cache, and that's how newly arrived mail is handled ๐. If the client tries to access information from the cache, it'll hit empty spots, which trigger "fetch" requests. The request goes out, some unsolicited data including the answer flows back, and then the "fetch" response unblocks the client ๐ฆ.
If you've studied demand-paged virtual memory operating system design, this will feel super familiar ๐. It's very similar to page-fault handling on a demand-paged system, and honestly that comparison is iconic ๐.
Formal Syntax ๐
The syntax specification below uses augmented Backus-Naur Form (BNF) notation as specified in RFC 822, with one exception: the delimiter used with the "#" construct is a single space (SP) and not a comma ๐.
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
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"
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) 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
Acknowledgements ๐ซถ
Huge shout-out to Bill Yeager and Rich Acuff, who both contributed invaluable suggestions while IMAP2 evolved from the original IMAP ๐. The SUMEX IMAP2 software was written by Mark Crispin (DEC-20 server, Xerox Lisp client, C client), Frank Gilmurray (Common Lisp client), Christopher Lane (Xerox Lisp client), and Bill Yeager (Unix server) ๐. Any mistakes or flaws in this IMAP2 protocol specification are, however, strictly my own ๐.
๐ฆ where this page comes from
- ietf: rfc1064 1988-07
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms