RFC 1176
Interactive Mail Access Protocol: Version 2
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 ๐:
- 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 ๐ญ.
- 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 ๐ง.
- PCs and workstations often don't get backed up as carefully as a central mainframe, or get backed up at all ๐พ.
- 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 ๐ข.
- 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\ANSWEREDflag set.BCCstring โ messages that contain the specified string in the envelope's BCC field.BEFOREdate โ messages whose internal date is earlier than the specified date.BODYstring โ messages that contain the specified string in the body of the message.CCstring โ messages that contain the specified string in the envelope's CC field.DELETEDโ messages with the\DELETEDflag set ๐FLAGGEDโ messages with the\FLAGGEDflag set ๐ฉFROMstring โ messages that contain the specified string in the envelope's FROM field.KEYWORDflag โ messages with the specified flag set.NEWโ messages that have the\RECENTflag set but not the\SEENflag. This is functionally equivalent toRECENT UNSEENโจOLDโ messages that do not have the\RECENTflag set.ONdate โ messages whose internal date is the same as the specified date.RECENTโ messages with the\RECENTflag set ๐SEENโ messages with the\SEENflag set.SINCEdate โ messages whose internal date is later than the specified date.SUBJECTstring โ messages that contain the specified string in the envelope's SUBJECT field.TEXTstring โ messages that contain the specified string.TOstring โ messages that contain the specified string in the envelope's TO field.UNANSWEREDโ messages that do not have the\ANSWEREDflag set.UNDELETEDโ messages that do not have the\DELETEDflag set.UNFLAGGEDโ messages that do not have the\FLAGGEDflag set.UNKEYWORDflag โ messages that do not have the specified flag set.UNSEENโ messages that do not have the\SEENflag 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 toFETCH๐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
- ietf: rfc1176 1990-08
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms