Deliverability

IMAP: what RFC 3501 and RFC 9051 actually define

A standards-first look at IMAP: the folder-based, server-side protocol that keeps every connected client in sync, and what IMAP4rev2 consolidates.

Olivier Bazoud
August 11, 2026
6 min read

Open your inbox on a laptop, then check the same account from a phone. Both show the same messages, the same read and unread state, and the same folders. IMAP makes that possible by design. POP3 was built around a single client downloading messages and deleting them from the server, so once one device pulled the mail, any other device checking the same account found nothing. IMAP keeps mail state on the server instead of the device, so every connected client works from the same copy.

What RFC 3501 and RFC 9051 define

RFC 3501, published in 2003, defines IMAP4rev1 and obsoletes the earlier RFC 2060. It specifies folder-based mailbox management: an account can hold multiple mailboxes instead of one flat store, each message carries flags such as \Seen, \Answered, \Deleted, and \Flagged, and a client can fetch part of a message, a header, one body section, without downloading the whole thing.

RFC 9051, published in 2021, defines IMAP4rev2. It doesn't start over. It folds IMAP4rev1 together with several extensions that were already widely deployed on their own, UTF-8 support and condition-based synchronization among them, into a single current specification.

How it works

A client opens a connection, authenticates, and issues SELECT to open a specific mailbox. From there it can FETCH message data: headers, one body part, or the full content, addressed either by sequence number or by a UID that stays stable across sessions. STORE changes a message's flags, marking it read, for instance.

None of this happens locally. Every fetch reads the server's copy, and every STORE writes to it, so the next client that connects and selects the same mailbox sees the change immediately.

Anatomy

Core commands:

CommandPurpose
LOGINAuthenticates the client against the server
SELECTOpens a mailbox for reading and modification
FETCHRetrieves message data: flags, headers, specific body parts, or full content
STOREChanges flags on a message
SEARCHFinds messages in the selected mailbox matching given criteria
EXPUNGEPermanently removes messages marked \Deleted
LOGOUTCloses the session

Standard flags:

FlagMeaning
\SeenMessage has been read
\AnsweredMessage has been replied to
\FlaggedMessage marked for follow-up
\DeletedMessage marked for removal, pending EXPUNGE
\DraftMessage is a draft, not yet sent

Sequence numbers and UIDs both identify a message, but they don't behave the same way. A sequence number is the message's position in the current mailbox view, and it shifts as messages are added or removed. A UID is assigned once and stays fixed for that message in that mailbox, so a client tracks state across sessions by UID, not by sequence number.

A session, traced

A client opens a mailbox, reads the first message's flags and headers, then marks it read:

a1 SELECT INBOX
* 172 EXISTS
* 1 RECENT
* OK [UNSEEN 1]
a1 OK [READ-WRITE] SELECT completed
a2 FETCH 1 (FLAGS BODY[HEADER])
* 1 FETCH (FLAGS () BODY[HEADER] {342}
Date: Mon, 10 Aug 2026 09:14:02 +0000
From: sender@example.com
To: user@example.com
Subject: Weekly report
)
a2 OK FETCH completed
a3 STORE 1 +FLAGS (\Seen)
* 1 FETCH (FLAGS (\Seen))
a3 OK STORE completed

SELECT INBOX opens the mailbox and reports how many messages it holds. FETCH 1 (FLAGS BODY[HEADER]) returns message 1's current flags, empty here, and its header block. STORE 1 +FLAGS (\Seen) adds the \Seen flag without disturbing any other flag, and the server echoes back the message's updated flag list to confirm the change.

Where this gets heavy

IMAP is verbose and stateful. A session carries mailbox selection, sequence-number bookkeeping, and pending server responses across many round trips, and that state has to stay consistent for as long as the connection is open. It's widely cited as harder to implement correctly than SMTP, whose command sequence is smaller and largely stateless per transaction.

Its synchronization model is poll-based by default: a client checks for changes rather than being told about them. The IDLE extension narrows that gap by letting a server push new-message notifications over an already-open connection, but that's an addition, not the protocol's original design point the way push is for JMAP. As a text-based wire protocol, IMAP also carries more per-request overhead than a JSON-over-HTTP alternative, a gap JMAP closes by design.

Check it yourself

Connect to a mail server directly over TLS and issue commands by hand:

Shell
openssl s_client -connect yourdomain.com:993

Once connected, type:

a1 LOGIN user pass
a2 SELECT INBOX
a3 FETCH 1 BODY[HEADER]

Read the raw response after each line. You'll see the same tagged OK, NO, and BAD completions, and the same untagged * data responses, that any IMAP client library relies on internally.

Where it fits

IMAP sits alongside two protocols that solve related but different problems. POP3 is the older download-and-delete alternative; IMAP replaces it for multi-device use. JMAP is the more recent, JSON-based alternative that addresses IMAP's verbosity and poll-based defaults directly.

IMAP also sits downstream of SMTP in the same mail flow, just facing the opposite direction. SMTP delivers a message into a mailbox. IMAP is what manages that mailbox afterward, for as long as the message stays there.

For the wider set of email standards this page sits inside, see the reference hub.

Nuntly's receiving pipeline takes a different approach entirely, webhook delivery instead of a protocol a client polls or holds open; see the receiving overview and AI agent inboxes.

FAQ

Should a new implementation target IMAP4rev1 or IMAP4rev2?

RFC 9051 (IMAP4rev2) is the current specification and already consolidates IMAP4rev1 plus the extensions that saw the widest deployment, so new work should target it. At the same time, account for the very large existing base of IMAP4rev1-only servers and clients still running in production.

What's the difference between a sequence number and a UID?

A sequence number is the message's position in the current mailbox view, and it shifts as messages are added or removed. A UID is a stable identifier for that message within that mailbox, meant to stay constant across sessions.

Does IMAP delete messages from the server?

Not by default. IMAP is designed to keep messages on the server and sync state, read or unread, across every connected client, unlike POP3's typical download-and-delete behavior.

Is IMAP push or pull?

Base IMAP is pull. The IDLE extension lets a server push new-message notifications over an already-open connection, but that's still different from JMAP's more explicitly push-oriented design.

RFC reference

RFCs covered: RFC 3501, RFC 9051. Superseded / updated by: RFC 9051 (IMAP4rev2) obsoletes RFC 3501 (IMAP4rev1), which itself obsoleted RFC 2060.