Internet Protocols · Email Protocols

Envelope and Header Addresses in SMTP Delivery

Why a message carries two independent sets of addresses, which one routing and bounces actually consult, and what breaks when a gateway rewrites one but not the other.

A message handed to a mail server arrives with addresses in two places that do not have to agree. The transport protocol reads one set; the human-readable headers contain another. Nearly every surprising behaviour in mail routing, bounce handling, and spam filtering follows from that duplication.

The transaction and the document

SMTP is a transaction protocol that moves an opaque blob. The transaction carries the routing decision: a MAIL FROM command naming the return path, and one or more RCPT TO commands naming recipients. The blob is a document whose headers name an author (From), visible recipients (To, Cc), and a subject. The transaction is the envelope; the blob is the message.

A single session shows the separation plainly:

S: 220 mail.example.net ESMTP
C: EHLO relay.example.org
S: 250-mail.example.net
S: 250 8BITMIME
C: MAIL FROM:<bounces@relay.example.org> SIZE=4211
S: 250 2.1.0 Ok
C: RCPT TO:<alice@example.net>
S: 250 2.1.5 Ok
C: RCPT TO:<bob@example.com>
S: 250 2.1.5 Ok
C: DATA
S: 354 End data with <CR><LF>.<CR><LF>
C: From: Carol <carol@relay.example.org>
C: To: alice@example.net, bob@example.com
C: Subject: Quarterly figures
C: ...
C: .
S: 250 2.0.0 Ok: queued as 4F2A1B

Three addresses appear in the envelope: a return path belonging to nobody in particular, and two recipients. The From header names Carol. Nothing in the protocol requires the MAIL FROM to equal the From header, and in this session it does not. The mismatch is not an error; it is the normal case for any message that wants bounces to land in a central mailbox rather than the author’s inbox.

The envelope exists because SMTP predates the message format it now carries. The 1982 specifications separated the two deliberately: the transport layer needed addresses it could parse without understanding the header grammar, which already permitted comments, quoted strings, and group syntax. Header addresses are a rich grammar, since To: "Smith, Alice" <alice@example.net>, undisclosed-recipients:; is legal, and a relay that had to parse that grammar to route would inherit every ambiguity in it. Envelope addresses are a restricted form: a local-part, an @, a domain. RFC 5321 constrains them further than RFC 5322 constrains header addresses, and the two grammars are not identical.

The immediate consequence is that a RCPT TO is a routing instruction with a per-recipient outcome. One message can be accepted for one recipient and rejected for another in the same transaction, and the sender learns about the two outcomes separately. That is impossible with a single To header, which is a presentation artifact with no per-recipient status attached.

What the envelope carries that headers cannot

The return path is the clearest case. MAIL FROM is where delivery status notifications are sent when delivery fails. A mailing list sets it to the list’s bounce address so that a failed subscription does not generate a notification to the original author, who cannot act on it. A sender that leaves MAIL FROM empty, the null return path <>, is asserting that the message must never generate a bounce, which is what a delivery status notification itself does to avoid notification loops.

Received headers are the other envelope-only artifact. Each hop prepends one, and RFC 5321 requires the trace to record the name the client used in EHLO, the address it connected from, and a timestamp. This is transport metadata that the author cannot supply and cannot remove without breaking the trace. It is also unauthenticated in the base protocol, which is why later authentication schemes had to be layered on top rather than derived from it.

Envelope recipients also differ from header recipients in count. A message addressed to a large distribution list may be delivered in a transaction with hundreds of RCPT TO commands, each producing an independent accept or reject. The To header on that message may name the list only. The gap between the two counts is the entire reason recipient-side filtering operates on the envelope: a filter that saw only To: would classify the message by what the author chose to display.

Rewriting at the boundary

Gateways rewrite envelopes constantly. An outbound relay rewrites MAIL FROM to a local bounce address, then uses a signed or keyed local part to recover the original sender when a bounce comes back. A forwarding service rewrites RCPT TO to its own mailbox and stores the original recipient alongside it. A submission server may rewrite the From header of a message sent on behalf of another domain.

Each rewrite is safe only if the corresponding address space is rewritten too, and the failure modes when they diverge are specific:

  • Rewriting MAIL FROM without touching From breaks authentication checks that compare the two, because the author domain no longer matches the envelope domain.
  • Rewriting From without rewriting MAIL FROM produces a message whose bounce path points at a domain that did not author it, so bounces are either dropped or misattributed.
  • Rewriting RCPT TO without preserving the original in a header (typically Delivered-To or an equivalent local convention) makes later filtering unable to tell which recipient the message was really for, which breaks per-recipient unsubscribe and deduplication.

The rewriting rules interact with submission policy. RFC 6409 defines a submission server that is stricter than a relay: it authenticates the sender, and it is expected to require that the envelope sender is authorized for the domain it claims. The separation between submission and relay is covered in The Split Between Submission and Relay Ports.

Address syntax is not the same grammar

The two grammars diverge in ways that produce real delivery failures. RFC 5321 permits a local-part of up to 64 octets and a domain of up to 255 octets, with the whole path bounded at 256 octets including the angle brackets. RFC 5322 has no such hard bound on header address length, because headers can fold across lines.

Quoted local parts exist in both, but the quoting rules differ. A header address may contain a quoted string with escaped characters; an envelope address may be quoted but the set of characters permitted inside differs, and some characters legal in a header must be encoded in an envelope. Internationalized addresses add a further layer: an envelope may carry UTF-8 local parts only when the server advertises the relevant extension, while header addresses can carry encoded words regardless.

Case sensitivity is the subtlest divergence. The domain part is case-insensitive everywhere. The local part is case-sensitive by specification and case-insensitive in practice at most large providers, which means an implementation cannot normalize case and cannot rely on it being preserved. A relay that folds case in the envelope but not in the header, or the reverse, can produce a message that fails a comparison a downstream filter performs.

Where the split leaks

The clean model of two independent address spaces holds until a component tries to reason about both at once, and several widely deployed mechanisms do.

Sender authentication compares them. The envelope domain is checked against the sending IP; the header From domain is checked against a cryptographic signature. A message that passes the first and fails the second is treated differently from one that fails both, and the difference is meaningful enough that policy engines assign separate verdicts. That architecture is the subject of DMARC Alignment Between Header and Envelope Domains.

Forwarding breaks the equivalence. A forwarder receives at one address and re-sends to another, changing RCPT TO and usually MAIL FROM, while leaving the author’s headers intact. From the receiving side, the message arrives from an IP the author never used, with an envelope sender the author never wrote. Any check that assumes envelope and header describe the same party now fails, even though nothing was forged.

Mailing lists are a controlled version of the same problem. They rewrite the envelope to their own bounce address and add list headers, then re-send. Subscribers who filter on From see the original author; subscribers who filter on the envelope see the list. Both are correct readings of a message that genuinely has two senders, and the ambiguity is resolved only by convention, not by the protocol.

The practical rule an implementer needs is that envelope and header are separate namespaces with separate trust levels, joined by policy rather than by syntax. Code that treats either as authoritative for the other will misroute bounces, misattribute authors, or accept messages it should reject. The rest of the delivery chain, meaning queueing, retry, and notification, is built on the envelope, and it is described in Queue Management and Retry Scheduling in MTAs.

References

  1. RFC 5321: Simple Mail Transfer Protocol — IETF
  2. RFC 5322: Internet Message Format — IETF
  3. RFC 6409: Message Submission for Mail — IETF