Loading content...
POP3's elegance lies in its simplicity. The entire protocol consists of a small set of text-based commands—human-readable keywords followed by optional arguments. This minimalist design means you can interact with a POP3 server using nothing more than a Telnet client, making debugging and learning straightforward.
Unlike modern protocols with complex binary encodings or extensive negotiation, POP3 commands read like simple instructions: USER to identify yourself, PASS to authenticate, LIST to see your mail, RETR to retrieve a message. This design philosophy prioritized transparency and implementation simplicity.
By the end of this page, you will master every standard POP3 command defined in RFC 1939, understand command syntax and response formats, know which commands are valid in which states, and be able to conduct manual POP3 sessions for troubleshooting.
All POP3 commands follow a consistent syntax pattern, making the protocol predictable and easy to parse.
Basic Syntax:
COMMAND [argument1] [argument2] CRLF
USER, user, and User are equivalent\r\n)| Indicator | Meaning | Format |
|---|---|---|
+OK | Success | +OK [informational text] |
-ERR | Failure | -ERR [error description] |
. (alone) | End of multi-line response | Single period on its own line |
Response Types:
Single-line responses: Status indicator plus optional text
+OK Mailbox locked and ready
-ERR Authentication failed
Multi-line responses: Status indicator, followed by data lines, terminated by .
+OK 3 messages (5000 octets)
1 1500
2 2000
3 1500
.
Byte-Stuffing for Multi-line Responses:
If a data line in a multi-line response begins with a period, the server prepends an additional period. The client removes this extra period when processing:
..This line begins with a period.This line begins with a periodThis prevents data lines from being mistaken for the termination indicator.
When manually testing POP3, remember that your terminal might not show the CRLF. Ensure you're pressing Enter (which typically sends CRLF on most systems) after each command. If commands seem to hang, you might be missing the proper line ending.
POP3 commands are only valid in specific session states. Attempting a command in the wrong state returns an error.
State-Command Matrix:
| Command | AUTHORIZATION | TRANSACTION | Notes |
|---|---|---|---|
| USER | ✓ | ✗ | Only before authentication |
| PASS | ✓ | ✗ | Must follow USER |
| APOP | ✓ | ✗ | Alternative to USER/PASS |
| STAT | ✗ | ✓ | Mailbox statistics |
| LIST | ✗ | ✓ | Message listing |
| RETR | ✗ | ✓ | Message retrieval |
| DELE | ✗ | ✓ | Mark for deletion |
| NOOP | ✗ | ✓ | Keep-alive |
| RSET | ✗ | ✓ | Unmark deletions |
| TOP | ✗ | ✓ | Partial message (optional) |
| UIDL | ✗ | ✓ | Unique IDs (optional) |
| QUIT | ✓ | ✓ | Always valid |
State Transition Rules:
Error Handling:
Issuing a command in the wrong state returns an error but doesn't change state:
# Before authentication, trying to read messages
C: STAT
S: -ERR Not authenticated
# Session remains in AUTHORIZATION state
QUIT is valid in any state. In AUTHORIZATION state, it simply closes the connection. In TRANSACTION state, it triggers UPDATE (commit deletions) before closing. This ensures clean session termination regardless of state.
Commands in AUTHORIZATION state handle user identification and authentication.
USER Command:
Identifies the user attempting to access the mailbox.
123456789101112131415161718
# SyntaxUSER username # ExampleC: USER alice@example.comS: +OK User accepted, password required # The +OK response does NOT mean authentication succeeded# It only means the username is syntactically valid# Actual authentication happens with PASS # Some servers reveal whether user exists:C: USER unknownuserS: -ERR No such user # Other servers (more secure) don't reveal: C: USER unknownuserS: +OK User accepted, password requiredPASS Command:
Provides the password to complete authentication. Must immediately follow USER.
12345678910111213141516171819202122232425
# SyntaxPASS password # Example - SuccessC: USER aliceS: +OK User acceptedC: PASS correctpasswordS: +OK Mailbox locked and ready # The mailbox is now EXCLUSIVELY LOCKED to this session# No other POP3 client can access it until QUIT # Example - FailureC: USER alice S: +OK User acceptedC: PASS wrongpasswordS: -ERR Authentication failed # After failure, some servers allow retry:C: USER aliceS: +OK User accepted # Others lock out after N failures:C: PASS wrongagainS: -ERR Account locked, too many failuresUSER/PASS sends the password in plaintext. Without TLS encryption, passwords are visible to any network observer. Always use POP3S (port 995) or STARTTLS to encrypt the connection before authentication.
APOP Command:
Alternative authentication that never sends the password in plaintext.
123456789101112131415161718
# Server greeting includes unique timestampS: +OK POP3 server ready <1896.697170952@mail.example.com> # Syntax: APOP username digest# digest = MD5(timestamp + password) # Example# Timestamp: <1896.697170952@mail.example.com># Password: secret123# Concatenated: <1896.697170952@mail.example.com>secret123# MD5 hash: c4c9334bac560ecc979e58001b3e22fb C: APOP alice c4c9334bac560ecc979e58001b3e22fbS: +OK Mailbox locked and ready # The password never appears on the wire!# Only the MD5 hash of (timestamp + password) is sent# Timestamp changes each session, preventing replay attacks| Aspect | USER/PASS | APOP |
|---|---|---|
| Password on wire | Plaintext (vulnerable) | Never (hashed) |
| Replay protection | None | Timestamp prevents replay |
| Server requirement | Universal support | Must provide timestamp |
| Client complexity | Trivial | Requires MD5 implementation |
| Modern recommendation | Only with TLS | Acceptable without TLS |
Use TLS encryption (POP3S or STARTTLS) regardless of authentication method. APOP prevents password exposure but doesn't encrypt message content. TLS protects everything.
These commands query mailbox status without retrieving message content.
STAT Command:
Returns the number of messages and total size in octets (bytes).
12345678910111213141516
# Syntax (no arguments)STAT # Response: +OK message-count mailbox-size # ExampleC: STATS: +OK 3 25600 # Interpretation:# - 3 messages in mailbox# - 25,600 bytes total size # Empty mailboxC: STATS: +OK 0 0LIST Command:
Lists messages with their individual sizes. Can list all messages or a specific one.
1234567891011121314151617181920212223242526272829
# Syntax for all messagesLIST # Multi-line response with all messagesC: LISTS: +OK 3 messages (25600 octets)S: 1 8000S: 2 10000S: 3 7600S: . # Format: message-number size-in-octets # Syntax for specific messageLIST message-number # Single-line responseC: LIST 2S: +OK 2 10000 # Non-existent messageC: LIST 99S: -ERR No such message # Deleted message (marked but not yet committed)C: DELE 2S: +OK Message 2 deletedC: LIST 2S: -ERR Message 2 has been deletedUIDL Command:
Returns unique identifiers for messages. These IDs persist across sessions.
1234567891011121314151617181920212223242526272829
# Syntax for all messagesUIDL # Multi-line responseC: UIDLS: +OKS: 1 XYZ123abc456S: 2 ABC789def012 S: 3 MNO345ghi678S: . # Format: message-number unique-id # Syntax for specific messageUIDL message-number C: UIDL 2S: +OK 2 ABC789def012 # UID characteristics:# - 1-70 printable ASCII characters# - Unique within mailbox# - Persistent until message deleted# - Server-generated (format varies) # Common UID formats across servers:# - Gmail: Numeric string# - Exchange: GUID format# - Dovecot: Hash-basedThe UIDL command is technically optional per RFC 1939. If unsupported, the server returns -ERR UIDL not implemented. However, virtually all modern servers support it—it's essential for leave-on-server functionality.
These commands retrieve message content from the mailbox.
RETR Command:
Retrieves the complete message (headers + body).
123456789101112131415161718192021222324252627282930313233
# SyntaxRETR message-number # Response: +OK octets, then message content, then . C: RETR 1S: +OK 1500 octetsS: Received: from mail.example.com (mail.example.com [192.0.2.1])S: by recipient.example.org with SMTPS: for <user@example.org>; Sat, 15 Jan 2026 10:30:00 -0500S: From: Alice <alice@example.com>S: To: Bob <bob@example.org>S: Subject: Meeting TomorrowS: Date: Sat, 15 Jan 2026 10:25:00 -0500S: Message-ID: <unique-id-12345@example.com>S: MIME-Version: 1.0S: Content-Type: text/plain; charset="UTF-8"S: S: Hi Bob,S: S: Just confirming our meeting tomorrow at 2pm.S: S: Best regards,S: AliceS: . # Non-existent messageC: RETR 99S: -ERR No such message # Deleted messageC: RETR 2S: -ERR Message 2 has been deletedTOP Command:
Retrieves headers plus the first N lines of the message body. Optional but widely supported.
1234567891011121314151617181920212223242526272829303132
# SyntaxTOP message-number lines # Example: Get headers plus 5 body linesC: TOP 1 5S: +OKS: From: alice@example.comS: To: bob@example.orgS: Subject: Long Document AttachedS: Date: Sat, 15 Jan 2026 10:30:00 -0500S: Content-Type: multipart/mixed; boundary="----=_Part_1234"S: S: ------=_Part_1234S: Content-Type: text/plainS: S: Hi Bob,S: S: Please find the document attached.S: . # Headers only (0 body lines)C: TOP 1 0S: +OKS: From: alice@example.comS: To: bob@example.orgS: Subject: Long Document AttachedS: Date: Sat, 15 Jan 2026 10:30:00 -0500S: Content-Type: multipart/mixed; boundary="----=_Part_1234"S: S: . # Note: The blank line separating headers from body is included| Aspect | RETR | TOP |
|---|---|---|
| Content retrieved | Complete message | Headers + N body lines |
| Bandwidth usage | Full message size | Minimal |
| Use case | Downloading mail | Previewing/filtering |
| Attachments | Complete retrieval | Usually truncated |
| RFC status | Required | Optional |
Use TOP n 0 to efficiently retrieve only headers for spam filtering or preview display. This is especially valuable on slow connections or when dealing with large attachments you may not want to download.
These commands manage message state in the mailbox.
DELE Command:
Marks a message for deletion. The deletion is committed only when the session ends via QUIT.
123456789101112131415161718192021
# SyntaxDELE message-number # Mark message for deletionC: DELE 1S: +OK Message 1 deleted # Message is now excluded from LIST, RETR, etc.C: LIST 1S: -ERR Message 1 has been deleted # But deletion isn't permanent yet!# Only committed on QUIT # Attempting to delete already-deleted messageC: DELE 1S: -ERR Message 1 has been deleted # Non-existent messageC: DELE 99S: -ERR No such messageRSET Command:
Resets the session, unmarking all messages marked for deletion.
12345678910111213141516171819202122232425
# Syntax (no arguments)RSET # Scenario: Multiple deletions, then resetC: STATS: +OK 5 10000 C: DELE 1S: +OK Message 1 deletedC: DELE 2S: +OK Message 2 deletedC: DELE 3S: +OK Message 3 deleted # Changed mind, want to undoC: RSETS: +OK 5 messages (10000 octets) # All messages are unmarkedC: STATS: +OK 5 10000 # Messages are accessible againC: LIST 1S: +OK 1 2000NOOP Command:
No operation. Used as a keep-alive to prevent server timeout.
12345678910111213141516
# Syntax (no arguments)NOOP C: NOOPS: +OK # Use case: Prevent timeout during long processing # Typical scenario:# - Server auto-timeout: 10 minutes# - Client is processing a large message locally# - Client sends NOOP every 5 minutes to keep session alive # NOOP has no side effects# Does not reset any timers related to message marking# Does not modify mailbox state in any wayEmail clients typically send NOOP periodically during long sessions. The interval should be less than the server's idle timeout. Most servers have a 10-15 minute timeout, so NOOP every 5-8 minutes is a reasonable strategy.
QUIT Command:
Ends the POP3 session. Behavior depends on current state.
1234567891011121314151617181920212223242526
# Syntax (no arguments)QUIT # QUIT from AUTHORIZATION state (before authentication)C: USER aliceS: +OK User acceptedC: QUITS: +OK POP3 server signing off# Connection closed, no mailbox modifications # QUIT from TRANSACTION state (after authentication)C: DELE 1S: +OK Message 1 deletedC: DELE 2S: +OK Message 2 deletedC: QUITS: +OK POP3 server signing off (2 messages deleted) # QUIT triggers UPDATE state:# 1. Deletions are committed (permanent)# 2. Mailbox statistics updated# 3. Exclusive lock released# 4. Connection closed # Response indicates what happenedS: +OK POP3 server signing off (2 messages deleted, 3 remaining)UPDATE State Processing:
When QUIT is issued in TRANSACTION state, the server enters UPDATE state and:
If any step fails, the server may:
| Starting State | Action | Mailbox Effect |
|---|---|---|
| AUTHORIZATION | Close connection | None (no access) |
| TRANSACTION (no DELE) | Close connection | None (no deletions) |
| TRANSACTION (with DELE) | UPDATE then close | Marked messages deleted |
Dropping the connection without QUIT leaves the mailbox locked until server timeout. Other clients will receive 'mailbox locked' errors. Always issue QUIT to cleanly release the lock, even if no deletions were made.
Beyond RFC 1939's core commands, several extensions add functionality.
CAPA Command (RFC 2449):
Returns a list of capabilities the server supports.
1234567891011121314151617181920212223
# Syntax (no arguments)CAPA # Example responseC: CAPAS: +OK Capability list followsS: TOPS: UIDLS: USERS: SASL PLAIN LOGIN CRAM-MD5S: STLSS: PIPELININGS: EXPIRE 30S: RESP-CODESS: . # Important capabilities:# TOP - Server supports TOP command# UIDL - Server supports UIDL command# STLS - Server supports STARTTLS# SASL - Supported SASL mechanisms# PIPELINING - Can send multiple commands without waiting# EXPIRE n - Messages auto-expire after n daysSTLS Command (RFC 2595):
Upgrades the connection to TLS encryption.
123456789101112131415161718192021222324
# Connect to port 110 (unencrypted)# Check capabilities firstC: CAPAS: +OK Capability list followsS: STLSS: ...S: . # Initiate TLS upgradeC: STLSS: +OK Begin TLS negotiation # TLS handshake happens here (at transport layer)# All subsequent communication is encrypted # After TLS established, re-check capabilitiesC: CAPAS: +OK Capability list followsS: TOPS: UIDLS: USERS: SASL PLAINS: .# Note: STLS disappears (already upgraded)AUTH Command (RFC 1734, 5034):
Supports SASL authentication mechanisms beyond USER/PASS.
123456789101112131415161718192021
# SyntaxAUTH mechanism [initial-response] # Example: PLAIN authentication# PLAIN format: base64(\0username\0password)C: AUTH PLAIN dXNlcm5hbWUAcGFzc3dvcmQ=S: +OK Logged in # Example: LOGIN authentication (multi-step)C: AUTH LOGINS: + VXNlcm5hbWU6C: dXNlcm5hbWU=S: + UGFzc3dvcmQ6C: cGFzc3dvcmQ=S: +OK Logged in # Example: CRAM-MD5 (challenge-response)C: AUTH CRAM-MD5S: + PDE4OTYuNjk3MTcwOTUyQHBvc3RvZmZpY2UucmVzdG9uLm1jaS5uZXQ+C: <base64-encoded-response>S: +OK Logged in| Mechanism | Security | Notes |
|---|---|---|
| PLAIN | Requires TLS | Base64 encoded, plaintext password |
| LOGIN | Requires TLS | Similar to PLAIN, two-step |
| CRAM-MD5 | Medium | Challenge-response, no plaintext password |
| SCRAM-SHA-256 | High | Modern, strong, recommended |
| XOAUTH2 | High | OAuth 2.0 tokens (Gmail, etc.) |
Major providers (Google, Microsoft) support OAuth via SASL XOAUTH2. This allows authentication using OAuth tokens instead of passwords, enabling POP3 access for accounts with multi-factor authentication.
Let's trace a complete, realistic POP3 session from connection to disconnection.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
# === CONNECTION ===# Establish TCP connection to port 110# Server sends greeting, enters AUTHORIZATION stateS: +OK POP3 server ready <9812.1234567890@mail.example.com> # Check what the server supportsC: CAPAS: +OK Capability list followsS: TOPS: UIDLS: USERS: STLSS: SASL PLAIN LOGINS: . # === UPGRADE TO TLS ===C: STLSS: +OK Begin TLS negotiation# [TLS handshake completes - connection now encrypted] # === AUTHENTICATION ===C: USER alice@example.comS: +OK User accepted C: PASS supersecretpasswordS: +OK Mailbox locked and ready# Now in TRANSACTION state # === MAILBOX INQUIRY ===C: STATS: +OK 4 32768 C: LISTS: +OK 4 messages (32768 octets)S: 1 8192S: 2 4096S: 3 16384S: 4 4096S: . # Check for new messages (using saved UIDs from last session)C: UIDLS: +OKS: 1 AAA111S: 2 BBB222S: 3 CCC333 S: 4 DDD444S: .# Client notes: AAA111 and BBB222 were downloaded before# CCC333 and DDD444 are new # === PREVIEW NEW MESSAGES ===C: TOP 3 0S: +OKS: From: newsletter@company.comS: Subject: Weekly Newsletter - January 15S: Date: Sat, 15 Jan 2026 08:00:00 -0500S: Content-Type: multipart/alternativeS: S: . C: TOP 4 0S: +OKS: From: friend@example.orgS: Subject: Dinner plans?S: Date: Sat, 15 Jan 2026 09:30:00 -0500S: Content-Type: text/plainS: S: . # === DOWNLOAD NEW MESSAGES ===C: RETR 3S: +OK 16384 octetsS: [complete message content...]S: . C: RETR 4S: +OK 4096 octetsS: [complete message content...]S: . # === CLEANUP (using download-and-delete model) ===# Mark all messages for deletionC: DELE 1S: +OK Message 1 deletedC: DELE 2S: +OK Message 2 deletedC: DELE 3S: +OK Message 3 deletedC: DELE 4S: +OK Message 4 deleted # === END SESSION ===C: QUITS: +OK POP3 server signing off (4 messages deleted)# Connection closed# All deletions committed in UPDATE stateYou can replicate this session manually using openssl s_client -connect mail.server.com:995 for POP3S. This is invaluable for debugging client configuration issues or understanding server behavior.
POP3's command set is intentionally minimal, making the protocol easy to implement and debug. Let's consolidate the key points:
What's Next:
With the complete command set understood, we'll examine POP3 authentication mechanisms in depth—covering USER/PASS, APOP, SASL mechanisms, and modern OAuth integration.
You now have a complete reference for POP3 commands. You understand the syntax, responses, state requirements, and practical usage of every standard command. Next, we'll dive deep into authentication mechanisms.