38. pepsi-stage-relay-to-internet

Direct-to-MX delivery with MTA-STS.

38.1. Role

pepsi-stage-relay-to-internet delivers a message directly to the recipient domain’s mail exchangers, doing its own MX discovery and TLS policy enforcement. It is one of the two interchangeable delivery stages. Reference: pepsi-stage-relay-to-internet(1).

38.2. Features

38.2.1. MX discovery (RFC 5321 / RFC 7505)

  • Own MX lookup, hosts tried in ascending preference (equal preference in random order); a domain with no MX falls back to its address records (implicit MX, RFC 5321 §5.1).

  • Null MX (RFC 7505, 0 .) and a non-existent domain are permanent failures, never retries.

  • Happy-Eyeballs address selection across A/AAAA, intersected with ADDRESS_FAMILY; resolved addresses are cached per address (with connect health) in the pepsi.dns_address table, so a working address is preferred until its DNS TTL elapses.

38.2.2. Transport security (RFC 8461 / RFC 6125)

  • MTA-STS (RFC 8461) discovery and enforcement (unless MTA_STS = no): an enforce policy restricts delivery to listed MX hosts over STARTTLS with a certificate that validates for the host (RFC 6125). A testing policy is validated the same way and the outcome recorded for TLS Reporting, but a failure falls back to opportunistic STARTTLS over all MX hosts; with no policy, delivery uses opportunistic STARTTLS. Policy lookups fail open only when nothing is cached. The mta-sts subcommand prints the applicable policy.

  • DANE/TLSA (RFC 7672), per MX host: DANE = off | warn | strict, default warn. When usable TLSA records exist and the MX RRset is DNSSEC-secure (Pepsi reads the resolver’s AD bit; it does not validate DNSSEC itself) they take precedence over MTA-STS for that connection — except that warn mode never replaces an enforce MTA-STS policy’s PKIX validation. A usable-record mismatch defers delivery under strict and only warns under warn. A host whose TLSA records are all unusable must still offer STARTTLS (RFC 7672 §2.2).

38.2.3. Delivery, retry and bounce

  • Sends with the message’s own envelope sender (null sender for bounces), one recipient per attempt: a multi-recipient row is first split into one row per recipient.

  • On success, finishes the row (or advances to NEXT_STAGE).

  • Exponential backoff on transient failure (RETRY_INITIAL/RETRY_MAX_INTERVAL/RETRY_FACTOR); past MAX_LIFETIME a transient failure becomes permanent.

  • Loop detection via MAX_HOP_COUNT Received: headers.

  • A permanent failure of an ordinary message routes to BOUNCE_STAGE (or marks the row failed); a permanent failure of a bounce is never re-bounced — a copy goes to POSTMASTER if set, else it is discarded.

38.2.4. DSN propagation and origination (RFC 3461)

  • Propagates RET/ENVID/NOTIFY/ORCPT to the MX only when it advertises DSN.

  • On permanent failure, hands the recipient’s NOTIFY/ORCPT/ENVID to the bounce stage so a failure DSN is generated only when requested.

  • Success DSN (Action: delivered) when ORIGINATE_SUCCESS_DSN + NOTIFY=SUCCESS; delay DSN (Action: delayed, once) when DELAY_DSN_AFTER elapses and NOTIFY=DELAY.

38.2.5. Content adaptation (RFC 6152 / RFC 6531)

  • Matches the message to the extensions the MX advertises: re-advertises BODY=8BITMIME / SMTPUTF8 when supported, otherwise downgrades the body (RFC 2045) and UTF-8 headers (RFC 2047). A non-ASCII address that cannot be represented to a non-SMTPUTF8 hop is bounced, and so is a body that is still 8-bit after the downgrade — RFC 6152 §3 permits no attempt to send it.

38.3. Configuration

[stage-<name>] with PROGRAM = pepsi-stage-relay-to-internet: SERVER_NAME (required), NEXT_STAGE/BOUNCE_STAGE, POSTMASTER, the timeouts (CONNECT_TIMEOUT/COMMAND_TIMEOUT/DATA_TIMEOUT), the retry policy (RETRY_INITIAL/RETRY_MAX_INTERVAL/RETRY_FACTOR/MAX_LIFETIME/ DELAY_DSN_AFTER), MAX_HOP_COUNT, DNS (DNS_SERVERS/DNS_TIMEOUT), MTA-STS (MTA_STS/MTA_STS_TIMEOUT), DANE and ADDRESS_FAMILY. Durations must use h/m/s units. Full reference: pepsi-stage-relay-to-internet(1).

38.4. State

  • Inputs: state.dsn (propagation + report gating) and state.origin (8BITMIME/SMTPUTF8 hints).

  • Outputs: attempts/last_error/delay_sent on pause; a state.bounce object (permanent/success/delay) when routing to or enqueuing for the bounce stage; last_error on terminal fail. state.dsn and state.origin are preserved.

38.5. See also

pepsi-stage-relay-to-smarthost, pepsi-stage-bounce, Supported Features, pepsi-stage-relay-to-internet(1).