85.1.25. pepsi-stage-auto-whitelist¶
whitelist recipients of outgoing mail
- Manual section:
1
85.1.25.1.1. Name¶
pepsi-stage-auto-whitelist - the recipient-recording stage of the Pepsi pipeline.
85.1.25.1.2. Synopsis¶
pepsi-stage-auto-whitelist [GLOBAL-OPTIONS] worker
85.1.25.1.3. Description¶
This stage defaults to FUSION = yes: when stage fusion is enabled ([pepsi]
ALLOW_FUSION, the default) and this stage is folded into the unified pepsi
binary, a predecessor may run it in its own worker process instead of
dispatching it separately. See pepsi-dispatch(1) and pepsi.conf(5).
pepsi-stage-auto-whitelist is a stage program run by pepsi-dispatch(1)
as a persistent worker reading message ids on standard input. It loads that pepsi.workqueue row
(refusing to act unless its status is running) and reads its
[stage-<stage>] section. It is the write-side counterpart of
pepsi-stage-check-whitelist(1): as an outgoing message passes through,
it records every envelope recipient (rcpt_to) in a named whitelist, so that
when that person later replies, pepsi-stage-check-whitelist(1)
recognises their From: header and lets the reply skip the anti-spam payment
gate. Place it on the outbound path (for example, ahead of a relay stage).
The whitelist lives in the pepsi.whitelist table, shared with
pepsi-stage-check-whitelist(1) — this stage only INSERTs into it, so it
needs no schema of its own. Each recipient address is stored as a
whitelist_regex: the address is lower-cased, every non-alphanumeric character
is backslash-escaped so it matches literally, and the result is anchored on
^/$ so it matches that address and nothing else. The check stage matches
that regex case-insensitively
(PostgreSQL’s ~* operator) against the addr-spec parsed out of a reply’s
From: header — not the raw header value, so a whitelisted address written
into the display-name position (From: "bob@example.com" <evil@attacker.example>)
cannot spoof a match. The boundary anchoring is what additionally stops
bob@example.com.evil from matching.
Each inserted row carries two condition flags that govern when a future reply counts as whitelisted:
dkim_requiredis set from the stage’s DKIM_REQUIRED option (default yes): when true, the reply is only trusted if its DKIM or ARC signature verified.signature_requiredis set to true when the outgoing message’s state hasencrypted: true(the message was end-to-end encrypted), otherwise false. That key is written by pepsi-stage-encrypt(1), so this stage must run after the encrypt stage (and, since it changes no content, may run between it and pepsi-stage-dkim-sign(1), which is where pepsi-setup(1)--wizardputs it). Placed earlier, no row ever carries the flag. The rows for encrypted correspondents then require their replies to arrive with a verified signature (state.signature_verified, which pepsi-stage-decrypt(1) sets) to match at all.
Every row is written with match_field = 'from': what this stage records is an
address a reply will arrive from. It never writes the list-id rows
pepsi-stage-check-whitelist(1) also understands — recognising that a user
has joined a mailing list is a different inference over different headers, made
by hand with pepsi-whitelist add-list.
Existing rows are left untouched (the insert is ON CONFLICT DO NOTHING on the
UNIQUE(whitelist_name, match_field, whitelist_regex) constraint), so
reprocessing a message is harmless. The stage then advances the message to
NEXT_STAGE. It never modifies the message’s own state and never drops,
bounces or pauses a message; a message with no recipients simply advances.
85.1.25.1.4. Configuration¶
Options live in the stage’s own [stage-<name>] section
(PROGRAM = pepsi-stage-auto-whitelist): the required WHITELIST_NAME group
to populate (one literal whitelist name; the stage expands no {login} or
{localpart} placeholder and refuses a value containing one),
DKIM_REQUIRED (default yes) and a NEXT_STAGE — also
required, since the stage records the recipients and then always hands the
message on, so pepsi-setup rejects a section without one. They are
documented in pepsi.conf(5).
85.1.25.1.4.1. Whose whitelist¶
The stage runs on the outbound path, so the per-address layers of the
configuration are looked up for the envelope sender: that address’s
pepsi.config_override rows at domain:/address: scope and its
pepsi.settings row decide which list its recipients are written to.
The operator may name any whitelist, a shared one included, in each of its
own layers: the INI file, pepsi.config_override at any scope, and a
pepsi.settings row written with pepsi-settings(1). The stage writes to
the effective value as it finds it.
An account owner who may edit this stage by mail (it is in
pepsi-stage-edit-settings(1)’s EDITABLE_STAGES) may only choose a
whitelist of their own: a name in the <login>/... namespace of the account
their address resolves to (alice/sent, say), or the whitelist the operator’s
configuration already names for them. Anything else – a shared list, another
user’s, or any value for an address that is no local account – would let them
fill that list with addresses of their choosing, and
pepsi-stage-edit-settings(1) refuses it. The login is resolved as
pepsi-stage-check-whitelist(1) resolves {login}: the address’s domain
must be one of LOCAL_DOMAINS (default [pepsi-ingress] ACCEPTED_DOMAINS),
its local part, with the sub-address after RECIPIENT_DELIMITER removed, must
be a passwd login, and that account must be permitted by TARGETS. These
three options are read from the operator’s stage section, never from the
owner’s own override.
A business that wants every correspondent recognised whoever they reply to – a customer told to write to a colleague rather than to the employee who first mailed them – shares one whitelist among all local users, written by this stage and read by the check stage:
[stage-auto-whitelist]
PROGRAM = pepsi-stage-auto-whitelist
NEXT_STAGE = dkim-sign
WHITELIST_NAME = correspondents
[stage-check-whitelist]
PROGRAM = pepsi-stage-check-whitelist
NEXT_STAGE = anti-spam
WHITELIST_NAME = correspondents
85.1.25.1.5. State¶
Inputs: the envelope recipients come from the rcpt_to column;
state.encrypted sets the stored signature_required flag. That key is
written by pepsi-stage-encrypt(1), earlier on the same outbound path, when
the outgoing message really was encrypted to a recipient key — so a
correspondent reached under encryption is later held to the same standard.
Outputs: none on the message itself — the message state is left
untouched. The side effect is one pepsi.whitelist row per recipient. The
state layout is described in pepsi.state(7).
Transitions: always advances to NEXT_STAGE — after inserting one whitelist row per envelope recipient, or unchanged when there are none. There is no branch; the stage never pauses, fails, reroutes or finishes.
85.1.25.1.6. Commands¶
- worker
Run as a persistent pepsi-dispatch(1) worker, reading message ids on standard input.
85.1.25.1.7. Failures¶
Recording is fail-open. When the INSERT fails (a database error, a
missing grant) the stage logs a warning and advances the message anyway: the
whitelist is a convenience for the recipient’s reply, and holding the user’s
outbound mail until it can be recorded would be the wrong way round. A pattern
that PostgreSQL could not compile is never written (the patterns are escaped
addresses, so this is a safeguard, not an expected case).
85.1.25.1.8. Global Options¶
- -c FILE, –config FILE
Read the configuration from FILE instead of searching the default locations.
- -L LOGLEVEL, –log LOGLEVEL
Set the logging verbosity (default
info).- -v, –verbose
Show log messages from all sources.
- -h, –help; -V, –version
Print a usage summary / the version and exit.
85.1.25.1.9. Exit Status¶
- 0
The message was processed (recipients recorded and the message advanced).
- 1
An error occurred (message not found or not
running, misconfigured stage — e.g. a missing WHITELIST_NAME — or a database error). The reason is written to the log.
85.1.25.1.10. Examples¶
Record the recipients of message 42 (it must be running):
echo 42 | pepsi-stage-auto-whitelist -c /etc/pepsi/pepsi.conf worker
An outbound pipeline section that whitelists everyone we mail, requiring their replies to be DKIM/ARC-signed:
[stage-auto-whitelist]
PROGRAM = pepsi-stage-auto-whitelist
NEXT_STAGE = srs
WHITELIST_NAME = trusted-senders
DKIM_REQUIRED = yes
85.1.25.1.11. See Also¶
pepsi-config(1), pepsi-stage-check-whitelist(1), pepsi-stage-anti-spam(1), pepsi-stage-arc(1), pepsi-dispatch(1), pepsi.conf(5), pepsi.state(7), pepsi-setup(1)
85.1.25.1.12. Bugs¶
Report bugs to the Pepsi issue tracker.