RFC 5321 — SMTP: The Transport Protocol
Deliverability-focused digest of SMTP: session model, envelope vs. content, reply-code semantics, null sender, retry rules, size limits, and timeouts.
RFC 5321 defines how mail moves between hosts. Every bounce code, retry policy, and envelope-level identity used in deliverability work traces back to this spec. For the surrounding vocabulary (MTA, MSA, ADMD…), see RFC 5598 — Internet Mail Architecture; for the message inside the envelope, see RFC 5322 — Message Format.
Session model
An SMTP session is a lock-step, one-command-at-a-time dialog (extensions like PIPELINING relax this by mutual agreement):
| Step | Client sends | Server success reply |
|---|---|---|
| Connect | (TCP connection) | 220 greeting |
| Identify | EHLO client-hostname (fallback HELO) |
250 + extension list |
| Envelope sender | MAIL FROM:<reverse-path> |
250 |
| Envelope recipient(s) | RCPT TO:<forward-path> (one per recipient, repeatable) |
250 (or 251 forwarded) |
| Content | DATA |
354 — then message, terminated by <CRLF>.<CRLF>, then 250 |
| End | QUIT |
221 |
Other commands: RSET (abort current transaction), VRFY/EXPN (address verification — widely disabled or answered 252 for anti-harvesting reasons), NOOP, HELP.
- A rejection at
MAIL FROM/RCPT TOcosts the receiver nothing per-message; a rejection afterDATAmeans the receiver already accepted the bytes. Many providers defer final judgment (content filtering) to the post-DATAreply — a5xxafter the final dot is a content/reputation rejection, not an address problem. - The
EHLOhostname is an identity signal: receivers commonly check that it is a resolvable FQDN and consistent with the connecting IP's rDNS. RFC 5321 requires it to be the client's primary host name (or an address literal when none exists).
Envelope vs. content
The envelope is the protocol-level addressing: one reverse-path (MAIL FROM) plus one or more forward-paths (RCPT TO). The content is everything sent inside DATA: header section + body (governed by RFC 5322).
Consequences that matter constantly in deliverability:
- The address people see (
From:header) and the address bounces go to (MAIL FROM, recorded on delivery asReturn-Path:) are independent. SPF authenticates the envelopeMAIL FROM; DMARC then tests its alignment with the headerFrom:— see DMARC. RCPT TOrecipients need not appear inTo:/Cc:(this is how Bcc and list expansion work).- Relays MUST NOT modify the envelope addresses or message semantics; they only prepend trace fields (
Received:; the final delivery agent prependsReturn-Path:).
Reply codes
Three digits; the text after the code is for humans, the number is the contract.
| First digit | Class | Sender behavior |
|---|---|---|
2yz |
Positive completion | Action succeeded; proceed |
3yz |
Positive intermediate | Send more (only 354 in base SMTP) |
4yz |
Transient negative | Failure may clear; retry later, unchanged |
5yz |
Permanent negative | Do not retry the same request; bounce/suppress |
Second digit: x0z syntax, x2z connections, x5z mail system status. Modern servers append RFC 3463 enhanced status codes (5.7.1 etc.) after the three-digit code for finer diagnosis.
Key codes:
| Code | Meaning |
|---|---|
220 |
Service ready (greeting) |
221 |
Closing channel (after QUIT) |
250 |
Requested action OK / completed |
251 |
User not local; will forward to <forward-path> |
252 |
Cannot VRFY user, but will accept and attempt delivery |
354 |
Start mail input; end with <CRLF>.<CRLF> |
421 |
Service not available, closing channel (also used for rate limiting / greylisting-style deferrals) |
450 |
Mailbox unavailable (temporary — e.g., busy, greylisted) |
451 |
Local error in processing; retry later |
452 |
Insufficient system storage / too many recipients — retry |
455 |
Server unable to accommodate MAIL parameters now |
500–504 |
Syntax error / command not implemented / bad parameters |
550 |
Mailbox unavailable (permanent — unknown user, policy rejection) |
551 |
User not local; try <forward-path> |
552 |
Exceeded storage allocation (message too big for mailbox) |
553 |
Mailbox name not allowed (bad address syntax) |
554 |
Transaction failed (no valid recipients / content or policy rejection) |
555 |
MAIL FROM/RCPT TO parameters not recognized |
Deliverability reality check: receivers legally use any code with any text — 4xx deferrals ("try again later", "unusual rate of mail") are the standard soft signal of reputation throttling, and 550 5.7.x texts carry the provider's actual reason. Always log full reply text, not just the code.
Null reverse-path (MAIL FROM:<>)
- Delivery status notifications (bounces) and other MHS-generated notifications MUST be sent with a null reverse-path —
MAIL FROM:<>— so that failed bounces can never generate further bounces (loop prevention). - Servers MUST accept
MAIL FROM:<>; rejecting the null sender breaks bounce handling and is noncompliant (though some spam filters score it). - A message received with a null reverse-path must never itself be answered with a DSN to that path.
- Practical corollary: any address you use in
MAIL FROMmust be able to receive mail (bounce processing); the null sender is only for notifications, never for regular sending.
Retry expectations (Section 4.5.4)
- After a
4xxor connection failure, the sender queues and retries. The retry interval SHOULD be at least 30 minutes per destination (a strategy that shortens this when the first attempt failed mid-connection is permitted). - Give-up time generally needs to be at least 4–5 days, after which a permanent failure notification goes to the reverse-path.
- Retries MUST be per destination host/address, with exponential-style backoff encouraged; hammering a deferring host is itself a reputation signal.
- On
5xx, the sender MUST NOT retry the same message to the same address — generate a non-delivery notification instead. (For list hygiene: hard bounces get suppressed immediately; soft bounces get suppressed after repeated failures across the retry window.) - If multiple MX hosts exist, the client tries them in preference order (lowest MX value first) before deferring.
Size limits (Section 4.5.3.1 — minimums implementations MUST handle)
| Object | Minimum capacity |
|---|---|
| local-part | 64 octets |
| domain | 255 octets |
path (<...> incl. punctuation) |
256 octets |
| command line (incl. CRLF) | 512 octets |
| reply line (incl. code + CRLF) | 512 octets |
| text line (incl. CRLF) | 1000 octets |
| message content | at least 64K octets; no fixed ceiling — advertised via the SIZE extension (RFC 1870) |
Exceeding a receiver's declared limits draws 552 (message) or 500 (line/command). Modern practice: check the SIZE= value in the EHLO response before sending large messages.
Timeouts (Section 4.5.3.2 — minimum client-side waits)
| Waiting for | Minimum timeout |
|---|---|
Initial 220 greeting |
5 minutes |
MAIL reply |
5 minutes |
RCPT reply |
5 minutes |
DATA reply (354) |
2 minutes |
| Each data block accepted | 3 minutes |
Reply to final <CRLF>.<CRLF> |
10 minutes |
| (Server side) inactivity | 5 minutes |
The 10-minute end-of-data wait matters: providers deliberately delay the post-DATA verdict while filtering; clients that hang up early cause duplicate deliveries (server delivers, client retries).
See also
- RFC 5322 — Message Format — what goes inside
DATA. - RFC 5598 — Internet Mail Architecture — who runs each hop.
- DMARC — how envelope and header identities are authenticated and aligned.