39. pepsi-stage-relay-to-smarthost

Relay through a configured upstream smarthost.

39.1. Role

pepsi-stage-relay-to-smarthost relays mail to a configured upstream MTA (smarthost) chosen by recipient domain, instead of contacting MX hosts directly. It is the other interchangeable delivery stage. Reference: pepsi-stage-relay-to-smarthost(1).

39.2. Features

39.2.1. Smarthost routing

  • Routes each recipient domain to the […-mta-<name>] whose DOMAINS lists it, or to the single CATCH_ALL MTA; a domain with no matching MTA is a permanent failure. A domain may be listed by only one MTA. The MTA sections are shared across all smarthost-relay stages.

  • No MX discovery and no DNS-learned MTA-STS — it speaks only to the configured smarthosts.

39.2.2. Transport and authentication

  • Per-MTA transport plain / tls (implicit) / starttls (RFC 3207, the default).

  • Certificate verification against the system store (plus an optional extra TLS_CA), or disabled for testing; an optional client certificate (TLS_CLIENT_CERT/TLS_CLIENT_KEY).

  • SMTP AUTH (RFC 4954), per MTA: none, plain, login, external, cram-md5, digest-md5, scram-sha-1 / scram-sha-256 and their -plus channel-binding forms, ntlm, gssapi, oauth, or auto to pick the strongest password mechanism the server offers. Most take USERNAME/PASSWORD; gssapi takes SERVICE_NAME/KRB5CCNAME, ntlm takes NT_DOMAIN/NT_WORKSTATION, and oauth takes USERNAME/TOKEN_FILE.

  • DANE/TLSA (RFC 7672) per MTA section: DANE = off | warn | strict, default warn.

  • HELO_NAME per MTA (defaults to SERVER_NAME).

39.2.3. Delivery, retry and bounce

  • Sends with the message’s own envelope sender, 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 up to MAX_LIFETIME; loop detection via MAX_HOP_COUNT.

  • A permanent failure (including no matching MTA) routes to BOUNCE_STAGE (or marks failed); a permanent failure of a bounce is discarded, never re-bounced. A rejected credential is a transient failure, never a bounce.

39.2.4. DSN and content adaptation

  • Propagates RET/ENVID/NOTIFY/ORCPT to the smarthost only when it advertises DSN (RFC 3461); originates failure/success/delay reports under the same rules as the direct stage.

  • Per-hop 8BITMIME/SMTPUTF8 re-advertising or downgrade (RFC 6152 / RFC 6531 / RFC 2045 / RFC 2047).

39.3. Configuration

[stage-<name>] with PROGRAM = pepsi-stage-relay-to-smarthost: SERVER_NAME (required), NEXT_STAGE/BOUNCE_STAGE, 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, ADDRESS_FAMILY (the default every MTA entry inherits) and the DANE resolver settings DNS_SERVERS/DNS_TIMEOUT. The upstream MTAs are defined in shared [pepsi-stage-relay-to-smarthost-mta-<name>] sections: HOST/PORT (both required), MODE, TLS_VERIFY/TLS_CA/TLS_CLIENT_CERT/ TLS_CLIENT_KEY, AUTH with its credentials, DANE, ADDRESS_FAMILY, HELO_NAME, and routing via DOMAINS / CATCH_ALL. Full reference: pepsi-stage-relay-to-smarthost(1).

39.4. Privilege

Installed setgid pepsi-token (mode 2550, owner pepsi:pepsi-token), and therefore a standalone binary rather than one of the programs folded into the unified pepsi binary. The dispatcher runs the stage as the unprivileged pepsi user; the setgid bit gives the worker egid=pepsi-token, which is what lets it read the group-restricted files it needs — the OAuth access tokens pepsi-helper-token-refresh writes (AUTH = oauth), a mutual-TLS TLS_CLIENT_KEY and a Kerberos credential cache (AUTH = gssapi) — without making pepsi a permanent member of that group. The file is not world-executable: the stage accepts -c, so any local user able to run it could point it at a server of their own and send that server the credentials.

39.5. State

Identical to pepsi-stage-relay-to-internet:

  • Inputs: state.dsn and state.origin.

  • Outputs: attempts/last_error/delay_sent on pause; a state.bounce object when routing to/enqueuing for the bounce stage; last_error on terminal fail. state.dsn/state.origin preserved.

39.6. See also

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