70.1.18. pepsi-stage-aliases

expand message recipients through an alias mapping file

Manual section:

1

70.1.18.1.1. Name

pepsi-stage-aliases - the alias / mailing-list expansion stage of the Pepsi pipeline.

70.1.18.1.2. Synopsis

pepsi-stage-aliases [GLOBAL-OPTIONS] worker

70.1.18.1.3. Description

pepsi-stage-aliases is a stage program run by pepsi-dispatch(1). It loads a pepsi.ingress row (refusing to act unless its status is running), reads its [stage-<stage>] section, and rewrites the message’s envelope recipients through the alias map named by ALIASES. Every recipient that matches an entry in the map is replaced by that entry’s target addresses; recipients that match nothing are left unchanged. The resulting recipient list is de-duplicated so each address is delivered to at most once, and the message is advanced to NEXT_STAGE.

The stage only loads the envelope and state — never the headers or body. When no recipient matches the map (and no duplicate is removed) the message is advanced unchanged.

70.1.18.1.4. Alias file

ALIASES names a human-readable mapping file parsed like a Postfix virtual(5) table. Each non-blank line maps one key to one or more target addresses:

# comments begin with '#'; blank lines are ignored
postmaster@example.com   alice@example.com
staff@example.com        bob@example.com, carol@partner.org
@example.net             ops@example.com
sales-*@example.org      sales@example.com

The key (left-hand side) is the first whitespace-delimited field: a full address, an @domain catch-all, or a * wildcard pattern (a *-glob such as *@example.org or sales-*@example.org). The targets (right-hand side) are separated by commas and/or whitespace and are kept verbatim — they may be local or remote, but may not contain a wildcard. A line with a key but no targets is ignored (a recipient is never silently deleted). If the same key appears twice, the later line wins.

Warning

Wildcards are globs, not regular expressions. * matches any run of characters and every other character — a . included — is a literal. To alias a whole domain write *@example.net (or the @example.net catch-all); .*@example.net is a regular expression and, read as a glob, demands a leading dot, so it matches no real address and every message to that domain falls through unaliased. (The pepsi.whitelist patterns of pepsi-whitelist(1) are POSIX EREs; this map is not.) Both pepsi-setup’s syntax check and the stage’s own map parser reject/flag a regex-looking key and name the glob you probably meant.

The file is read into memory and re-read only when its modification time changes, so a busy worker does not re-parse it for every message. A missing or unreadable file is treated as an empty map (and logged), so a momentary misconfiguration does not fail messages. pepsi-setup syntax-checks the ALIASES file at install time when it exists (see pepsi-setup(1)), so a malformed line is caught before deployment rather than only warned about at run time.

70.1.18.1.5. Matching and expansion

A recipient is lower-cased and looked up verbatim; on a miss the @domain catch-all key for its domain is tried, and finally any * wildcard key — the most specific matching wildcard wins (a narrow sales-*@example.org beats a broad *@example.org beats a bare *; ties are broken deterministically). Sub-address (+tag) detail is not stripped, so a specific list address such as list+announce@example.com can be aliased on its own.

Expansion is transitive: when an alias target is itself a key it is expanded in turn, so nested distribution lists resolve to their leaf addresses. A loop — an alias that refers back to itself directly or through a chain — is broken by resolving the repeated key to its literal address rather than recursing forever.

70.1.18.1.6. Delivery Status Notifications

state.dsn.rcpt is parallel to the recipient list, so it is rebuilt in lockstep with the rewritten recipients. An expanded target inherits the NOTIFY of the original recipient it came from and, following RFC 3461 §5.2.7, carries an ORCPT pointing at the original recipient (its existing ORCPT if it had one, otherwise rfc822;<original-recipient>). A recipient that was not expanded keeps its DSN entry unchanged. Message-level RET/ENVID and all other state keys are preserved.

70.1.18.1.7. Configuration

Options live in the stage’s own [stage-<name>] section (PROGRAM = pepsi-stage-aliases): the ALIASES map-file path and the NEXT_STAGE the expanded message advances to. They are documented in pepsi.conf(5).

70.1.18.1.8. State

Inputs: the envelope rcpt_to and the per-recipient state.dsn.rcpt.

Outputs: a rewritten rcpt_to and a matching state.dsn.rcpt (only when an alias applied); no other state is touched. The state layout is described in pepsi.state(7).

Transitions: advances to NEXT_STAGE (the only transition); the stage never pauses, fails, reroutes or finishes.

70.1.18.1.9. Commands

worker

Run as a persistent pepsi-dispatch(1) worker, reading message ids on standard input. This is how the dispatcher runs the stage in production.

70.1.18.1.10. 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.

70.1.18.1.11. Exit Status

0

The message was processed (advanced to NEXT_STAGE).

1

An error occurred (message not found or not running, a misconfigured stage — e.g. a missing ALIASES or NEXT_STAGE — or a database error). The reason is written to the log. A missing alias file is not an error: it is treated as an empty map.

70.1.18.1.12. Examples

Expand and advance message 42 (it must be running):

pepsi-stage-aliases -c /etc/pepsi/pepsi.conf 42

A pipeline section placed just before local delivery, expanding recipients and forwarding to the local-delivery stage:

[stage-aliases]
PROGRAM = pepsi-stage-aliases
NEXT_STAGE = local
ALIASES = /etc/pepsi/aliases

70.1.18.1.13. See Also

pepsi-config(1), pepsi-stage-relay-to-maildir(1), pepsi-stage-if(1), pepsi-dispatch(1), pepsi.conf(5), pepsi.state(7), pepsi-setup(1)

70.1.18.1.14. Bugs

Report bugs to the Pepsi issue tracker.