.. This file is part of PEPSI. Copyright (C) 2026 Pepsi contributors PEPSI is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. ============================= pepsi-stage-relay-to-internet ============================= *Direct-to-MX delivery with MTA-STS.* 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: :manpage:`pepsi-stage-relay-to-internet(1)`. Features ======== 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. 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); ``testing``/absent policies use opportunistic ``STARTTLS``. Policy lookups fail open only when nothing is cached. The ``mta-sts`` subcommand prints the applicable policy. Delivery, retry and bounce -------------------------- * Sends with the message's own envelope sender (null sender for bounces). * 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. 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``. 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. Configuration ============= ``[stage-]`` 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``) and MTA-STS (``MTA_STS``/``MTA_STS_TIMEOUT``) and ``ADDRESS_FAMILY``. Durations must use ``h``/``m``/``s`` units. Full reference: :manpage:`pepsi-stage-relay-to-internet(1)`. 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. See also ======== :doc:`pepsi-stage-relay-to-smarthost`, :doc:`pepsi-stage-bounce`, :doc:`../features`, :manpage:`pepsi-stage-relay-to-internet(1)`.