Skip to content

IMAP

POP3's closing scenario ended with a message that existed on one device and nowhere else, because POP3 treats the server as a temporary holding area to be emptied on download. IMAP starts from the opposite assumption entirely: the server is the mailbox, permanently, and every device is just a window looking into it.

The server stays the source of truth

IMAP — Internet Message Access Protocol, currently at IMAP4rev1 (RFC 3501) with a newer IMAP4rev2 (RFC 9051) building on it — doesn't download-and-delete. A client connects, and instead of pulling everything down and clearing it out, it synchronizes with whatever state already lives on the server: which folders exist, which messages are in each one, and which flags each message carries.

Those flags are the mechanism that makes multi-device email actually consistent. IMAP defines a small set of them, each a simple marker attached to a message on the server itself:

Flag Meaning
\Seen The message has been read
\Answered A reply has been sent
\Flagged User-marked as important
\Deleted Marked for removal, not yet purged
\Draft An unsent draft

Read a message on your phone, and the client sets \Seen on the server. Open your laptop's mail app a minute later, and it asks the server for the current state of that same message — sees \Seen already set — and shows it as read, with no download-and-delete round trip involved at all. The synchronization, not the download, is the whole point.

Four states, and one that didn't exist in POP3

IMAP's session states extend POP3's three-state model with one IMAP has that POP3 fundamentally can't, because POP3 has no concept of folders:

  1. Not Authenticated — connected, not yet logged in.
  2. Authenticated — logged in, but no specific mailbox is open yet.
  3. Selected — a specific folder (INBOX, Sent, a custom folder) is open, and message-level commands operate on it.
  4. Logout — the session is ending.

The Selected state is the one worth pausing on. Every POP3 session works with a single flat pile of messages; IMAP requires picking a specific mailbox before doing anything message-related, because a real IMAP server hosts an entire folder hierarchy — INBOX, INBOX/Work, Sent, Trash, and whatever else the user or the client created — and the protocol needs an explicit SELECT before any subsequent command knows which folder it's actually addressing.

A real session, command by command

IMAP runs on TCP port 143 in cleartext, or port 993 wrapped in TLS from the first byte. Unlike SMTP and POP3, every IMAP command is prefixed with a client-chosen tag — an arbitrary label the client makes up, most simply an incrementing number — so the client can match each reply back to the request that triggered it, even if the server sends replies out of order or interleaved with unsolicited updates:

* OK IMAP4rev1 Server Ready
a1 LOGIN alice hunter2
a1 OK LOGIN completed
a2 SELECT INBOX
* 4 EXISTS
* 1 RECENT
* OK [UIDVALIDITY 3857529045] UIDs valid
a2 OK [READ-WRITE] SELECT completed
a3 FETCH 1 (FLAGS BODY[HEADER.FIELDS (SUBJECT)])
* 1 FETCH (FLAGS (\Seen) BODY[HEADER.FIELDS (SUBJECT)] {19}
Subject: Hi there

)
a3 OK FETCH completed
a4 STORE 1 +FLAGS (\Deleted)
* 1 FETCH (FLAGS (\Seen \Deleted))
a4 OK STORE completed
a5 LOGOUT
* BYE IMAP4rev1 server logging out
a5 OK LOGOUT completed

Lines starting with * are untagged — server-originated status updates rather than direct replies to a specific command, which is why SELECT returns * 4 EXISTS (four messages in this folder) and * 1 RECENT (one arrived since the folder was last opened) alongside its tagged a2 OK. FETCH requests specific pieces of a message without necessarily downloading the whole thing — here just the flags and the Subject header — which lets a mobile client show an inbox list without pulling every full message body over a slow connection. STORE ... +FLAGS (\Deleted) marks a message for deletion the same way POP3's DELE does, but the message isn't actually purged until a separate EXPUNGE command runs, and other clients connected to the same mailbox can see the \Deleted flag appear in real time via their own unsolicited * FETCH update.

Why this makes IMAP heavier, and why that's the right trade

None of this comes free. A POP3 server only has to remember whether a message has been handed out; an IMAP server has to maintain per-message flags, folder structure, and message sequence numbers that stay consistent across every client connected at once, and answer queries against that state instead of just streaming bytes and forgetting. That's real, ongoing server-side cost — more storage, more state, more complexity in the server implementation itself.

It's also exactly what people expect from email today. Nobody wants a phone and a laptop to disagree about which messages are read, or to lose email entirely because one device happened to check first. IMAP's added weight buys the behavior a modern mailbox is expected to have, and it's why virtually every mail provider defaults new accounts to IMAP and treats POP3 as a legacy option kept around for compatibility.

Practical scenario: a shared mailbox that argues with itself

A small support team shares one mailbox through IMAP, with three people's mail clients connected to it at once. One agent replies to a customer and marks the message \Answered; a minute later, a second agent's inbox view still shows it as needing a reply.

The server's per-connection log shows the second client hasn't issued a fresh SELECT or FETCH against that folder in over ten minutes — it's simply displaying whatever it cached from its last sync and hasn't asked the server for anything new since. IMAP servers can push unsolicited updates to an open connection, but only if the client keeps that connection open and listening for them, typically via the IDLE command; a client that polls infrequently, or that dropped its persistent connection without reconnecting, won't see another agent's flag change until its next scheduled check-in.

The fix isn't a server problem at all — it's a client configuration one: shortening the mail app's sync interval, or confirming IDLE support is actually enabled, so flag changes from teammates propagate in something close to real time rather than on the next periodic poll.

Practice exercises

  1. Using openssl s_client -connect <mail-server>:993 -crlf against a test account, log in and run SELECT INBOX, then identify which lines in the response are tagged replies and which are untagged server status updates.
  2. Explain why STORE ... +FLAGS (\Deleted) doesn't immediately remove a message, and name the command that actually does.
  3. A user asks why their IMAP mailbox "takes up server storage" while an old POP3 account they used years ago didn't. Answer using the state IMAP has to maintain that POP3 never did.

Every protocol so far in this module — FTP, SMTP, POP3, IMAP — has assumed you already know the address of the server you're connecting to. Getting from a name like mail.example.com to an actual IP address is a separate system, one this course has referenced constantly and is about to take apart properly: Introduction to DNS starts with the record types that make that translation possible.

Sources