Loading content...
Every interaction between an email client and an IMAP server is conducted through a precisely defined command language. Unlike simple protocols where commands are brief and responses predictable, IMAP commands form a sophisticated vocabulary capable of expressing complex operations—from basic message retrieval to conditional searches, partial downloads, and state modifications.
Understanding IMAP commands is essential for anyone who debugs email issues, develops email clients, or simply wants to comprehend what happens when they click 'Check Mail.' Each command follows a consistent structure: a client-generated tag for tracking, a command name, optional arguments, and a server response indicating success, failure, or data.
This page provides a comprehensive exploration of IMAP commands organized by function: connection lifecycle, mailbox management, message retrieval, state modification, and synchronization. By the end, you'll be able to read IMAP session logs fluently and understand the protocol-level actions behind every email client operation.
This page covers the complete IMAP command vocabulary: authentication commands, mailbox selection and management, message fetching with various granularities, flag manipulation, searching, and synchronization commands. You'll understand command structure, response parsing, and the stateful nature of IMAP sessions.
IMAP commands follow a strict format that enables reliable, pipelined communication. Each element of this format serves a specific purpose.
Command Format:
tag COMMAND [arguments...]
Response Format:
The server responds with three types of lines:
* ...): Data or status informationtag OK/NO/BAD ...): Command completion status+ ...): Server requests more data123456789101112131415161718192021222324252627282930313233
# Client opens connection[TCP Connection Established] # Server greeting (untagged)* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE] Dovecot ready. # Client sends LOGIN command with tag "a001"a001 LOGIN "alice@example.com" "secretpassword" # Server responds to tagged commanda001 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPECIAL-USE BINARY MOVE QUOTA] Logged in # Client requests mailbox lista002 LIST "" "*" # Server sends untagged data lines for each mailbox* LIST (\HasNoChildren) "." "INBOX"* LIST (\HasNoChildren \Drafts) "." "Drafts"* LIST (\HasNoChildren \Sent) "." "Sent"* LIST (\HasNoChildren \Trash) "." "Trash"* LIST (\HasNoChildren \Junk) "." "Junk"* LIST (\HasChildren) "." "Archive"* LIST (\HasNoChildren) "." "Archive.2023"* LIST (\HasNoChildren) "." "Archive.2024" # Completion responsea002 OK List completed (0.001 + 0.000 secs).Command Pipelining
IMAP allows clients to send multiple commands without waiting for each response. The server processes commands in order and returns responses in order, tagged for identification:
a001 SELECT INBOX
a002 FETCH 1:10 (FLAGS ENVELOPE)
a003 SEARCH UNSEEN
Responses will arrive with their corresponding tags, allowing the client to match them even if received out-of-order due to processing time differences.
Literals for Large Data
When command arguments contain special characters, newlines, or are simply large, IMAP uses literals—a mechanism to send arbitrary octets:
a001 APPEND INBOX {305}
+ OK
[305 bytes of message data follows]
The {305} indicates 305 bytes will follow. The server responds with + OK to signal readiness, and the client sends the data.
When debugging IMAP issues, tags are invaluable. Each command-response pair is matched by tag, so you can trace exactly which command produced which response. Many clients use incrementing tags (a001, a002, a003...) making session logs easy to follow.
Before accessing any mailbox, clients must establish a connection and authenticate. IMAP provides several commands for this initial handshake.
CAPABILITY
Requests the server to list its supported capabilities. The server usually includes capabilities in the greeting, but clients can explicitly request them:
a001 CAPABILITY
* CAPABILITY IMAP4rev1 LITERAL+ SASL-IR AUTH=PLAIN AUTH=XOAUTH2 ID IDLE
a001 OK CAPABILITY completed
Capabilities inform the client which extensions are available: IDLE for push notifications, CONDSTORE for synchronization, MOVE for atomic move operations, etc.
12345678910111213141516171819202122232425262728
# LOGIN - Simple username/password authenticationa001 LOGIN "alice@example.com" "mypassword"a001 OK LOGIN completed # AUTHENTICATE - SASL-based authentication (more secure methods)# Plain authentication (base64 encoded)a001 AUTHENTICATE PLAIN+ AGFsaWNlQGV4YW1wbGUuY29tAG15cGFzc3dvcmQ=a001 OK AUTHENTICATE completed # OAuth2 authentication (used by Gmail, Outlook.com, etc.)a001 AUTHENTICATE XOAUTH2+ dXNlcj1hbGljZUBleGFtcGxlLmNvbQFhdXRoPUJlYXJlciB5YTI5LmEwQWY...AQE=a001 OK AUTHENTICATE completed # STARTTLS - Upgrade connection to encrypted TLSa001 STARTTLSa001 OK Begin TLS negotiation now[TLS Handshake occurs]# Connection now encrypted; re-issue CAPABILITY to see updated list # LOGOUT - End session gracefullya001 LOGOUT* BYE IMAP4rev1 Server logging outa001 OK LOGOUT completed[Connection closed]NOOP (No Operation)
The NOOP command does nothing but prompts the server to send any pending updates:
a001 NOOP
* 15 EXISTS
* 2 RECENT
a001 OK NOOP completed
NOOP is commonly used to:
ID
The ID command (RFC 2971) allows client and server to identify themselves:
a001 ID ("name" "Thunderbird" "version" "115.0")
* ID ("name" "Dovecot" "version" "2.3.20")
a001 OK ID completed
This is useful for debugging, statistics, and server-side behavior tuning based on client type.
| Method | Security | Usage | Notes |
|---|---|---|---|
| LOGIN | Weak (plaintext) | Legacy clients | Only use over TLS |
| AUTHENTICATE PLAIN | Base64 (not encrypted) | SASL-compliant | Only use over TLS |
| AUTHENTICATE XOAUTH2 | Strong (OAuth token) | Gmail, Outlook | Token-based, no password transmission |
| STARTTLS + LOGIN | Encrypted channel | Modern standard | Upgrades plain to encrypted |
LOGIN and AUTHENTICATE PLAIN send credentials that can be trivially decoded. Always use port 993 (IMAPS) for implicit TLS, or port 143 with STARTTLS before authenticating. Modern servers often disable LOGIN command until encryption is established.
Once authenticated, clients manage mailboxes—creating, deleting, renaming, subscribing, and selecting them for operations.
LIST and LSUB
LIST returns mailboxes matching a pattern. LSUB returns only subscribed mailboxes (mailboxes the user wants to see in their client):
# List all mailboxes
a001 LIST "" "*"
# List mailboxes under Archive
a001 LIST "" "Archive.*"
# List subscribed mailboxes only
a001 LSUB "" "*"
The response includes mailbox attributes (\HasChildren, \Noselect, \Drafts, etc.) and the hierarchy separator.
12345678910111213141516171819202122232425262728293031
# SELECT - Open a mailbox for read/write accessa001 SELECT INBOX* FLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded)* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded \*)]* 156 EXISTS # Total messages in mailbox* 3 RECENT # Messages new since last session* OK [UNSEEN 42] # First unseen message sequence number* OK [UIDVALIDITY 1609459200] # UID epoch (cache validator)* OK [UIDNEXT 892] # Next UID to be assigned* OK [HIGHESTMODSEQ 12345] # For CONDSTORE synca001 OK [READ-WRITE] SELECT completed # EXAMINE - Open mailbox read-only (no flag changes allowed)a001 EXAMINE "Sent"* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)* 1047 EXISTS* 0 RECENTa001 OK [READ-ONLY] EXAMINE completed # STATUS - Get mailbox info without selecting ita001 STATUS "Drafts" (MESSAGES UNSEEN UIDNEXT)* STATUS "Drafts" (MESSAGES 8 UNSEEN 2 UIDNEXT 45)a001 OK STATUS completed # CLOSE - Close selected mailbox, expunge deleted messagesa001 CLOSEa001 OK CLOSE completed # UNSELECT - Close without expunging (preserves \Deleted messages)a001 UNSELECTa001 OK UNSELECT completedCREATE, DELETE, RENAME
Clients can manage the mailbox hierarchy:
# Create a new mailbox
a001 CREATE "Projects/NewProject"
a001 OK CREATE completed
# Delete a mailbox (usually must be empty)
a001 DELETE "Projects/OldProject"
a001 OK DELETE completed
# Rename a mailbox (atomic)
a001 RENAME "Projects/NewProject" "Archive/2024/NewProject"
a001 OK RENAME completed
SUBSCRIBE and UNSUBSCRIBE
Subscription controls which mailboxes appear in the client's folder list:
a001 SUBSCRIBE "Archive/2024"
a001 OK SUBSCRIBE completed
a001 UNSUBSCRIBE "Archive/2020"
a001 OK UNSUBSCRIBE completed
Subscription is purely a user preference—it doesn't affect mail delivery or storage.
SELECT opens a mailbox for read/write operations (flag changes, deletions). EXAMINE opens it read-only—useful when you only need to view messages without affecting their state. Some servers automatically use EXAMINE for shared mailboxes where the user lacks write permission.
The FETCH command is IMAP's workhorse, providing flexible retrieval of message data. Its power lies in the ability to request exactly what you need—from a single header to the entire message, from message flags to MIME structure.
Basic FETCH Syntax:
a001 FETCH <sequence-set> <data-items>
The sequence set specifies which messages (by sequence number or UID). The data items specify what to retrieve.
12345678910111213141516171819202122232425262728293031323334353637383940
# Common FETCH data items and their meanings: # FLAGS - Message flagsa001 FETCH 1 (FLAGS)* 1 FETCH (FLAGS (\Seen \Answered)) # ENVELOPE - Parsed header summary (From, To, Subject, Date, etc.)a001 FETCH 1 (ENVELOPE)* 1 FETCH (ENVELOPE ("Wed, 15 Jan 2025 10:30:00 +0000" "Meeting Tomorrow" (("Alice Smith" NIL "alice" "example.com")) # From (("Alice Smith" NIL "alice" "example.com")) # Sender (("Alice Smith" NIL "alice" "example.com")) # Reply-To (("Bob Jones" NIL "bob" "example.com")) # To NIL NIL # CC, BCC "<msg123@example.com>" # In-Reply-To "<msg456@example.com>")) # Message-ID # BODY[HEADER] - Raw headersa001 FETCH 1 (BODY[HEADER])* 1 FETCH (BODY[HEADER] {456}From: alice@example.comTo: bob@example.comSubject: Meeting TomorrowDate: Wed, 15 Jan 2025 10:30:00 +0000... ) # BODY[TEXT] - Message body (without headers)a001 FETCH 1 (BODY[TEXT]) # BODY[] - Entire message (headers + body)a001 FETCH 1 (BODY[]) # BODYSTRUCTURE - MIME structure without contenta001 FETCH 1 (BODYSTRUCTURE)* 1 FETCH (BODYSTRUCTURE (("text" "plain" ("charset" "utf-8") NIL NIL "7bit" 1256 42 NIL NIL NIL NIL) ("image" "jpeg" ("name" "photo.jpg") NIL NIL "base64" 524288 NIL ("attachment" ("filename" "photo.jpg")) NIL NIL) "mixed" ("boundary" "----=_Part_123") NIL NIL NIL))Partial Fetching
IMAP allows fetching portions of data, crucial for bandwidth efficiency:
# Fetch first 500 bytes of body (preview)
a001 FETCH 1 (BODY[TEXT]<0.500>)
# Fetch bytes 1000-2000 of body (resuming download)
a001 FETCH 1 (BODY[TEXT]<1000.1000>)
# Fetch specific MIME part (e.g., second attachment)
a001 FETCH 1 (BODY[2])
# Fetch specific part's headers
a001 FETCH 1 (BODY[2.HEADER])
UID FETCH
Using UIDs for fetches ensures consistency across sessions:
# Fetch message by UID instead of sequence number
a001 UID FETCH 12345 (FLAGS ENVELOPE)
# Fetch range of UIDs
a001 UID FETCH 12345:12400 (FLAGS)
# Fetch specific UIDs
a001 UID FETCH 12345,12356,12378 (ENVELOPE)
| Macro | Equivalent | Use Case |
|---|---|---|
| ALL | FLAGS INTERNALDATE RFC822.SIZE ENVELOPE | Message list display |
| FAST | FLAGS INTERNALDATE RFC822.SIZE | Quick status check |
| FULL | FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY | Detailed message info |
Using BODY[section] implicitly sets the \Seen flag on the message. To fetch without marking as read, use BODY.PEEK[section]. This is essential for preview panes that shouldn't mark messages as read until explicitly opened.
Beyond retrieval, IMAP provides commands to modify message states, copy messages between mailboxes, and upload new messages.
STORE: Modifying Flags
The STORE command changes message flags. It has three modes: set, add, and remove:
# Set flags (replaces all existing flags)
a001 STORE 1 FLAGS (\Seen \Flagged)
# Add flags (keeps existing, adds new)
a001 STORE 1 +FLAGS (\Flagged)
# Remove flags
a001 STORE 1 -FLAGS (\Seen)
By default, STORE returns the updated flags. Use .SILENT to suppress the response when you don't need confirmation:
a001 STORE 1:100 +FLAGS.SILENT (\Seen)
a001 OK STORE completed
12345678910111213141516171819202122232425262728293031
# COPY - Copy messages to another mailbox (original remains)a001 COPY 1:10 "Archive/2024"a001 OK [COPYUID 1704067200 1:10 892:901] COPY completed# COPYUID response shows: UIDVALIDITY source-UIDs dest-UIDs # MOVE - Atomically move messages (MOVE extension, RFC 6851)a001 MOVE 15:20 "Receipts"* OK [COPYUID 1704067200 15:20 156:161]* 15 EXPUNGE* 15 EXPUNGE* 15 EXPUNGE* 15 EXPUNGE* 15 EXPUNGE* 15 EXPUNGEa001 OK [COPYUID 1704067200 15:20 156:161] MOVE completed # Without MOVE extension, you must COPY then STORE \Deleted then EXPUNGEa001 COPY 15:20 "Receipts"a002 STORE 15:20 +FLAGS (\Deleted)a003 EXPUNGE # EXPUNGE - Permanently delete messages with \Deleted flaga001 EXPUNGE* 42 EXPUNGE* 43 EXPUNGEa001 OK EXPUNGE completed # UID EXPUNGE - Expunge only specific messages (UIDPLUS extension)a001 UID EXPUNGE 12345:12350* 42 EXPUNGEa001 OK UID EXPUNGE completedAPPEND: Uploading Messages
APPEND uploads a message to a mailbox. This is used for:
12345678910111213141516171819202122
# Basic APPEND syntaxa001 APPEND "Sent" {256}+ OKFrom: alice@example.comTo: bob@example.comSubject: Test MessageDate: Wed, 15 Jan 2025 10:30:00 +0000MIME-Version: 1.0Content-Type: text/plain; charset="utf-8" This is the message body.a001 OK [APPENDUID 1704067200 902] APPEND completed # APPEND with flags and datea001 APPEND "Drafts" (\Draft \Seen) "15-Jan-2025 10:30:00 +0000" {512}+ OK[Message content...]a001 OK [APPENDUID 1704067200 903] APPEND completed # The APPENDUID response provides:# - UIDVALIDITY of the target mailbox# - UID assigned to the new messageEXPUNGE permanently removes all \Deleted messages from the selected mailbox—there is no undo. Clients should be careful when running EXPUNGE, especially in mailboxes shared with other clients that might have marked messages for deletion. Use CLOSE to auto-expunge when leaving a mailbox, or UID EXPUNGE to target specific messages.
IMAP's SEARCH command enables server-side message filtering, returning only messages matching specified criteria. This is far more efficient than downloading all messages to search locally.
Basic SEARCH Syntax:
a001 SEARCH <criteria>
a001 UID SEARCH <criteria>
SEARCH returns sequence numbers; UID SEARCH returns UIDs (preferred for synchronization).
1234567891011121314151617181920212223242526272829303132333435363738394041
# Flag-based searchesa001 SEARCH UNSEEN # Unread messagesa001 SEARCH SEEN # Read messagesa001 SEARCH FLAGGED # Starred messagesa001 SEARCH UNFLAGGED # Not starreda001 SEARCH DELETED # Marked for deletiona001 SEARCH ANSWERED # Replied to # Header searchesa001 SEARCH FROM "alice@example.com" # From specific sendera001 SEARCH TO "team@example.com" # Sent to addressa001 SEARCH SUBJECT "quarterly report" # Subject contains texta001 SEARCH HEADER "X-Priority" "1" # Custom header value # Date searchesa001 SEARCH SINCE 01-Jan-2024 # After datea001 SEARCH BEFORE 31-Dec-2024 # Before datea001 SEARCH ON 15-Jan-2024 # Exactly on datea001 SEARCH SENTSINCE 01-Jan-2024 # Date header (not received) # Size searchesa001 SEARCH LARGER 1000000 # Larger than 1MBa001 SEARCH SMALLER 10000 # Smaller than 10KB # Body searchesa001 SEARCH BODY "project deadline" # Text in bodya001 SEARCH TEXT "urgent" # Text in headers + body # Combined searches (AND is implicit)a001 SEARCH FROM "boss@example.com" UNSEEN SINCE 01-Jan-2024# Returns: * SEARCH 42 47 89 102 # OR searchesa001 SEARCH OR FROM "alice@example.com" FROM "bob@example.com" # NOT searchesa001 SEARCH NOT SEEN # Same as UNSEENa001 SEARCH NOT FROM "spam@example.com" # Complex query with groupinga001 SEARCH (OR FROM "alice" FROM "bob") UNSEEN LARGER 5000ESEARCH Extension
The ESEARCH extension (RFC 4731) provides more control over search results:
# Return count instead of message list
a001 SEARCH RETURN (COUNT) UNSEEN
* ESEARCH (TAG "a001") COUNT 47
# Return min and max sequence numbers
a001 SEARCH RETURN (MIN MAX) FROM "alice"
* ESEARCH (TAG "a001") MIN 12 MAX 256
# Return both count and list
a001 SEARCH RETURN (COUNT ALL) FLAGGED
* ESEARCH (TAG "a001") COUNT 5 ALL 12,47,89,123,256
ESEARCH is particularly useful when you only need aggregate information rather than a full message list.
BODY and TEXT searches require the server to examine message content. Servers without full-text search indexes may perform these searches slowly on large mailboxes. Consider if the server supports extensions like FUZZY for approximate matching or uses external search engines for performance.
Efficient synchronization is crucial for email clients, especially on mobile devices. IMAP provides several mechanisms for detecting changes since the last sync.
IDLE: Real-Time Notifications
The IDLE command (RFC 2177) allows the server to push notifications to the client:
a001 IDLE
+ idling
[Client waits...]
* 157 EXISTS # New message arrived
* 2 RECENT
[Client processes update]
DONE # Client sends DONE to exit IDLE
a001 OK IDLE terminated
During IDLE, the connection remains open but quiet. The server sends untagged responses when:
The client must periodically end IDLE (send DONE) and restart it, as some servers timeout long IDLEs.
1234567891011121314151617181920212223242526272829303132333435363738394041
# Enable CONDSTORE for modification trackinga001 ENABLE CONDSTORE* ENABLED CONDSTOREa001 OK ENABLE completed # SELECT with CONDSTORE shows HIGHESTMODSEQa001 SELECT INBOX* OK [HIGHESTMODSEQ 54321]...a001 OK SELECT completed # FETCH changed messages since a MODSEQ valuea001 FETCH 1:* (FLAGS) (CHANGEDSINCE 50000)* 47 FETCH (FLAGS (\Seen \Flagged) MODSEQ (54100))* 89 FETCH (FLAGS (\Seen) MODSEQ (54321))a001 OK FETCH completed # Only messages changed since MODSEQ 50000 are returned # QRESYNC - Quick Resynchronization (RFC 7162)# Enable QRESYNC (implies CONDSTORE)a001 ENABLE QRESYNC* ENABLED QRESYNC CONDSTOREa001 OK ENABLE completed # SELECT with QRESYNC for efficient reconnection synca001 SELECT INBOX (QRESYNC (1704067200 54000 1:500))# UIDVALIDITY MODSEQ known-UIDs * OK [UIDVALIDITY 1704067200]* 157 EXISTS* OK [HIGHESTMODSEQ 54321]* VANISHED (EARLIER) 45,89,120 # These UIDs were expunged* 47 FETCH (UID 47 FLAGS (\Seen) MODSEQ (54100))* 156 FETCH (UID 156 FLAGS () MODSEQ (54300))a001 OK SELECT completed # In one command, client learns:# - Current mailbox state# - Which known messages were deleted# - Flag changes for remaining messagesWhy QRESYNC Matters
Without QRESYNC, reconnecting to a large mailbox requires:
With QRESYNC, a single SELECT command provides:
For a mailbox with 10,000 messages where only 50 changed, QRESYNC synchronizes in one command instead of potentially thousands of FLAG checks.
Mobile email clients heavily depend on CONDSTORE/QRESYNC for efficiency. Without these extensions, syncing after periods offline would drain battery and data. Check if your email provider supports these extensions—most modern servers do, but some legacy systems don't.
We've covered the comprehensive IMAP command vocabulary—the protocol language that makes email access possible. Let's consolidate the key insights:
What's Next:
With IMAP commands understood, the next page explores folders and flags in-depth—the organizational structures and state markers that enable sophisticated email workflows. You'll learn about folder hierarchies, special-use folders, flag semantics, and best practices for email organization.
You now understand the IMAP command language: from connection establishment through authentication, mailbox management, message retrieval and manipulation, searching, and synchronization. This knowledge enables you to read IMAP logs, debug email issues, and appreciate the protocol-level actions behind your email client's operations.