70.1.14. pepsi-stage-relay-to-lmtp¶
deliver a message to a local MDA (Dovecot) over LMTP
- Manual section:
1
70.1.14.1.1. Name¶
pepsi-stage-relay-to-lmtp - the LMTP local-delivery stage of the Pepsi pipeline.
70.1.14.1.2. Synopsis¶
pepsi-stage-relay-to-lmtp [GLOBAL-OPTIONS] worker
70.1.14.1.3. Description¶
pepsi-stage-relay-to-lmtp is a stage program run by pepsi-dispatch(1).
It loads the pepsi.ingress row (refusing to act unless its status is
running), reads its [stage-<stage>] section, and hands the message to a
Mail Delivery Agent — typically Dovecot — over LMTP (RFC 2033) for
final local delivery. The MDA applies each recipient’s Sieve (RFC 5228)
script as it files the mail, so server-side filtering (fileinto, vacation,
redirect, flag setting, …) is provided by the MDA rather than by Pepsi.
The stage is LMTP-native: every envelope recipient is offered in a single
LMTP transaction and the MDA returns a separate reply per recipient after
end-of-DATA. The stage itself never builds a delivery-status notification —
it delivers, and otherwise routes each recipient onward to a configured stage,
recording why under state.bounce so a downstream pepsi-stage-bounce(1)
(or a relay) can act on it. Each recipient’s fate follows its reply:
2xx — delivered; the recipient leaves the row. When the recipient asked for
NOTIFY=SUCCESSand[pepsi] ORIGINATE_SUCCESS_DSNis set, a positive notification is routed to the optional NOTIFY_STAGE.a permanent reject is routed by reason, classified from the reply’s RFC 3463 enhanced status: a bad destination mailbox (
x.1.x, or a bare550user-unknown) goes to NEXT_STAGE; an over-quota reject (x.2.2) to QUOTA_LIMIT_STAGE (else NEXT_STAGE); a Sieve / local policy reject (x.7.x) to SIEVE_REJECT_STAGE (else NEXT_STAGE); anything else to NEXT_STAGE.4xx (e.g. server busy) — a transient failure: the recipient is retried with exponential backoff until MAX_LIFETIME, then routed by the same reason classification.
A message can therefore be partially handled: delivered, routed and deferred
recipients are reconciled in one fan-out — the delivered recipients leave the
row, each routed recipient becomes a sibling pending row (sliced to that one
recipient, so a relay target never re-delivers to its siblings) at its target
stage, and the original row is reduced to just the still-deferred recipients for
the next retry. A DELAY warning (when due and NOTIFY=DELAY was requested)
is likewise routed to NOTIFY_STAGE.
Because the MDA decides which addresses are local, this stage performs no
locality test of its own (unlike pepsi-stage-relay-to-maildir(1)). Place it
where only intended-local recipients arrive — usually after alias expansion
(pepsi-stage-aliases(1)). It is not terminal: NEXT_STAGE is
mandatory — set it to a pepsi-stage-bounce(1) to bounce undeliverable
recipients, or to a relay stage to forward them off-site. A message that reaches
the stage with no NEXT_STAGE configured is marked failed.
Unlike local Maildir writing, LMTP needs no privileged helper: the MDA
performs the per-user delivery itself, so this stage runs as the unprivileged
pepsi user and carries no setuid/setgid bit. It is folded into the unified
pepsi binary.
70.1.14.1.4. Options¶
Run mode:
- worker
Run as a persistent pepsi-dispatch(1) worker, reading
ingressrow ids on standard input.
Configuration (in the stage’s own [stage-<name>] section):
- PROGRAM
Must be
pepsi-stage-relay-to-lmtp.- NEXT_STAGE
Required. Where a recipient the MDA could not deliver is routed (a bad destination mailbox, and the fallback for the reasons below). Set it to a pepsi-stage-bounce(1) to bounce undeliverable recipients, or to a relay stage (e.g. pepsi-stage-srs(1) → a smarthost) to forward them off-site.
pepsi-setuprejects a configuration without it.- QUOTA_LIMIT_STAGE
Where to route a recipient the MDA refused for being over quota (RFC 3463
x.2.2). Defaults to NEXT_STAGE. Set it to a bounce stage when NEXT_STAGE is a relay, so quota rejects bounce rather than relay off-site.- SIEVE_REJECT_STAGE
Where to route a recipient refused by Sieve / local policy (RFC 3463
x.7.x). Defaults to NEXT_STAGE.- NOTIFY_STAGE
Where positive SUCCESS delivery notifications and DELAY warnings are routed (as a cloned message carrying
state.bounce.kind); set it to a pepsi-stage-bounce(1), which renders the report. When unset, no positive or delay notifications are originated. The stage never builds a notification itself.- SOCKET
Path of the MDA’s LMTP UNIX-domain socket (e.g.
/run/dovecot/lmtp). The common local-delivery layout; no TLS or authentication. Mutually exclusive with HOST.- HOST / PORT
Reach the MDA over TCP instead (
PORTdefaults to 24). Use for an MDA on another host.- TLS
Transport security for a HOST target:
off(default),starttls, ortls(implicit).TLS_VERIFY(default yes) andTLS_CAcontrol PKIX verification;TLS_CLIENT_CERT/TLS_CLIENT_KEYpresent a client certificate for mutual TLS / SASLEXTERNAL.- AUTH
SASL mechanism for a TCP target:
none(default),plain,loginorexternal. Authentication is refused over cleartext, so any non-noneAUTHrequiresTLS = starttlsortls(andexternalrequires a client certificate).USERNAME/PASSWORDsupply the credential.- SERVER_NAME
Name announced in
LHLOand stamped in theReceived:header. Defaults to[pepsi-ingress] HOSTNAME.- MAX_LIFETIME, RETRY_INITIAL, RETRY_MAX_INTERVAL, RETRY_FACTOR
Retry/give-up timing for transiently-deferred recipients.
- DELAY_DSN_AFTER
Emit a one-shot “delayed” DSN once a still-undelivered message has been queued this long and the sender asked for
NOTIFY=DELAY.- CONNECT_TIMEOUT, COMMAND_TIMEOUT, DATA_TIMEOUT
Per-operation LMTP timeouts.
70.1.14.1.5. See Also¶
pepsi-dispatch(1), pepsi-stage-relay-to-maildir(1), pepsi-stage-aliases(1), pepsi-stage-bounce(1), pepsi.conf(5), pepsi.state(7).
RFC 2033 (LMTP), RFC 5228 (Sieve).