IMAP
Fetch, store, and search
Retrieve selected message data, change flags, and ask the server to search a mailbox.
Once a mailbox is selected, three commands do most of the work. FETCH gets data about messages. STORE changes their flags. SEARCH asks the server to find messages for you.
The important word in that first sentence is data, not messages. IMAP lets you ask for exactly the pieces you need: just the flags, just two headers, just the size. That’s how a mail app shows a 5,000-message inbox in a second without downloading it.
Search on the server
Let’s find the unread messages:
C: A003 UID SEARCH UNSEEN
S: * SEARCH 104 108
S: A003 OK Search completed
The server did the work and returned two UIDs. No message content moved over the network.
You can combine criteria: UID SEARCH FROM "[email protected]" SINCE 1-Jul-2026 UNSEEN. The server searches its index, which is faster than anything the client could do.
Fetch only what you need
Now let’s get the sender and subject of UID 104, plus its flags:
C: A004 UID FETCH 104 (FLAGS BODY.PEEK[HEADER.FIELDS (FROM SUBJECT)])
S: * 7 FETCH (UID 104 FLAGS () BODY[HEADER.FIELDS (FROM SUBJECT)] {52}
S: From: Sara Rossi <[email protected]>
S: Subject: Deployment
S:
S: )
S: A004 OK FETCH completed
Two numbers appear here. 7 is the sequence number, the message’s position right now. 104 is the UID, which stays stable. The {52} announces that 52 bytes of literal data follow.
Notice BODY.PEEK. It reads without setting \Seen. Plain BODY[...] marks the message as read as a side effect, and since flags are shared, every device would see it as read because your code looked at it. Use PEEK unless you mean to mark it.
Change flags without clobbering
STORE changes flags. It has three forms, and the choice matters:
A005 UID STORE 104 +FLAGS (\Seen)
A006 UID STORE 104 -FLAGS (\Flagged)
A007 UID STORE 104 FLAGS (\Seen)
+FLAGS adds. -FLAGS removes. Plain FLAGS replaces the entire list. That last form is dangerous: if another client just set \Flagged, replacing the list erases it. Say what you want to change, not what you think the final state is.
Results are a snapshot
SEARCH results were true when the server answered. A moment later another client can expunge a message, or a new one can arrive. When you fetch UID 108 and get nothing back, that’s not an error. It’s gone. Handle missing results, and read the untagged updates the server sends between your commands.
A habit for fast clients
Fetch headers and flags for the list view. Fetch the body when the user opens a message. Fetch attachments when they click one. Downloading everything up front is how IMAP clients get slow.
Try rewriting the example to mark UID 104 as seen without touching its other flags. Then explain why using sequence number 7 in a later session would be a bug.
Lesson completed