46. pepsi-stage-vacation¶
Answer mail that arrives while the recipient is away.
46.1. Role¶
pepsi-stage-vacation is the out-of-office responder. When the envelope
recipient is away on the day the stage runs, it sends that recipient’s vacation
notice to the sender and tags the forwarded copy’s Subject:. The message itself
always continues to NEXT_STAGE: the stage adds a reply, it never holds,
drops or bounces mail. Reference: pepsi-stage-vacation(1).
46.2. Whose vacation¶
The stage reads its options through the per-address override layer, so they are the envelope recipient’s. That is what makes one stage serve both cases the feature has to cover:
[stage-<name>] in pepsi.conf the operator's default: normally nobody away
< config_override 'global' a national holiday, for everybody
< config_override 'domain:<d>' a holiday for one served domain
< config_override 'address:<a>' a leave the operator enters for someone
< pepsi.settings[<a>] the account owner's own leave dates
The chain is not this stage’s invention — Configuration describes it, and
every stage gets it — but this is the stage that uses all of it. Operators enter a
holiday with pepsi-config, a user’s leave with pepsi-settings; listing
vacation in pepsi-stage-edit-settings’s EDITABLE_STAGES lets account
owners set their own dates by e-mail.
A row that still carries several recipients sharing one configuration (two aliases of a person, or everybody during a holiday) is split one recipient per row before any notice is built: each notice is from one address, and each rate limit is for one address.
46.3. When a notice is sent¶
Today — in the server’s time zone, resolved when the stage runs — falls in one of
the VACATION_RANGES (inclusive whole days; 2026-08-01: is an open-ended
leave), and the message is one it is proper to answer. The full RFC 3834 rule
set is in the man page; the short version is that Pepsi does not answer bounces,
mailing-list mail, anything marked Auto-Submitted: or Precedence: bulk,
service senders such as MAILER-DAEMON or <list>-request, delivery reports,
mail an upstream stage marked as spam, mail the recipient sent themselves, or mail
that does not name the recipient in To:/Cc:. On top of that, one
correspondent is answered at most once per SUPPRESS_DAYS (default 7).
An out-of-office responder is the one component that emits a message per received
message, so four things bound it at once: the notice’s null envelope sender
(nothing can reply to it), the Auto-Submitted: auto-replied it carries, the
per-correspondent rate limit (a responder that ignores both still costs one message
a week), and the UNIQUE queue token that makes a retried stage unable to send a
second copy.
46.4. The message¶
The notice text is a Mustache template held in an INI option rather than in a
TEMPLATE_DIR file, because this is the message users write themselves and the
settings layer carries options, not files. Per candidate language the stage prefers
MESSAGE_<LANG> in the stage’s own section (the user’s own text) and falls back
to <LANG> in DEFAULT_MESSAGE_SECTION — by default
[pepsi-vacation-default-message], which ships in ${DATADIR}/config.d with
ten languages, so a working default exists before anyone configures anything.
The language is chosen from state.language (written by
pepsi-stage-detect-language) and falls back to DEFAULT_LANGUAGE. The
fields are {{SENDER_NAME}}, {{VACATION_START}}, {{VACATION_END}} and
{{EMERGENCY_CONTACT}}; the last two are absent rather than empty when they do
not apply, so a template can branch. Since an INI option is one line, two spaces
become a newline (four, a paragraph break).
46.5. Placement¶
After pepsi-stage-detect-language (for the language), after pepsi-stage-check-whitelist and pepsi-stage-anti-spam (so spam and unpaid mail draw no reply), and after pepsi-stage-aliases if aliases are in use (the configuration is keyed on the envelope recipient, which must be the user’s own address by then).
Rewriting the Subject: invalidates the originator’s DKIM signature and Pepsi’s
own ARC message signature, both of which cover it — harmless on a branch ending in
local delivery, which is the placement above and the one pepsi-stage-decrypt
already relies on. On a branch that relays the message onward, set
VACATION_TAG = none.
46.6. Configuration¶
[stage-<name>]: PROGRAM = pepsi-stage-vacation, NEXT_STAGE (mandatory),
RESPONSE_STAGE (mandatory — where the notice is injected to be signed and
relayed), VACATION_RANGES, DEFAULT_LANGUAGE, DEFAULT_MESSAGE_SECTION,
EMERGENCY_CONTACT, VACATION_TAG, SUPPRESS_DAYS,
REQUIRE_ADDRESSED_TO and SUBJECT_PREFIX. pepsi-setup rejects a bad date
range, an unresolvable NEXT_STAGE/RESPONSE_STAGE, and a configuration with
no message for DEFAULT_LANGUAGE. See pepsi-stage-vacation(1) and
Configuration.
46.7. State¶
Inputs:
state.language(for the notice’s language),state.local_origin(a locally submitted message is never answered),state.spam.Outputs:
state.vacationrecording that a notice went out, for whom, for which range and in which language — so pepsi-stage-if can branch on it and pepsi-queue shows it. Nothing else instateis touched, andstate.dsnis preserved.Transitions: always advance to
NEXT_STAGE; a separate null-sender notice is injected atRESPONSE_STAGE.
46.8. Database¶
pepsi.vacation_reply (one row per answered correspondent) and
vacation_should_reply(), which claims and records the right to answer in one
statement so two workers cannot both answer the same correspondent. Aged rows are
pruned in passing; there is no job to schedule.
46.9. See also¶
pepsi-stage-detect-language, pepsi-stage-edit-settings, pepsi-settings, pepsi-config, Supported Features, pepsi-stage-vacation(1).