52. pepsi-stage-block-language¶
Route a message by the human language(s) detected in its body.
52.1. Role¶
pepsi-stage-block-language is a language-policy filter. It scores the
language(s) recorded under state.language (written upstream by
pepsi-stage-detect-language) against a configured whitelist and blacklist
and routes the message: above the score THRESHOLD it advances to
NEXT_STAGE, otherwise ENFORCEMENT decides — hard (the default)
reroutes it to BOUNCE_STAGE carrying a failure-DSN state, soft
delivers it anyway with a marked Subject:. The body is never loaded (the
header block is, because soft mode rewrites a header) and the stage never pauses.
Reference: pepsi-stage-block-language(1).
52.2. Scoring¶
state.language is an HTTP Accept-Language-style string of code;q=quality
items, each quality being the detection probability of that language. The
stage collapses it to one number:
score = Σ q over languages listed in WHITELIST
− Σ q over languages listed in BLACKLIST
Languages on neither list contribute nothing. With English whitelisted and French
blacklisted, en;q=0.7, fr;q=0.3 scores 0.7 − 0.3 = 0.4. A message whose
score is strictly greater than THRESHOLD advances; otherwise it is blocked.
Undetected mail. When no language was detected (
state.languageabsent) the score is computed against the pseudo-distributionnone;q=1. The literalnonemay itself appear inWHITELIST/BLACKLIST, so the operator decides the fate of undetected mail (blacklistingnonescores it−1, whitelisting+1, listing it nowhere leaves it at0).Whitelist bypass. A message carrying an explicit
state.spam = falseverdict — set by an upstream pepsi-stage-check-whitelist match, or by ingress for the reserved<Postmaster>mailbox (RFC 5321 §4.5.1) — skips the language policy entirely and advances toNEXT_STAGE.Never bounce a bounce. A message that is already a bounce (the null envelope sender) advances to
NEXT_STAGEregardless of its score (RFC 5321 §6.1).
52.3. Hard and soft enforcement¶
ENFORCEMENT decides what happens to a message that fails the policy, and both
modes select exactly the same set of messages — which is the point: the flag
predicts the bounce, so an operator can tune WHITELIST/BLACKLIST/
THRESHOLD against real traffic before any mail is refused.
hard(the default) reroutes toBOUNCE_STAGEwith a permanent failure-DSNstate, so pepsi-stage-bounce emits a bounce only if the sender’sNOTIFYrequestsFAILURE(the default when absent). No header is touched.softadvances the message toNEXT_STAGEinstead, appendingSUBJECT_FLAG_LABEL(default[!LANG]) to itsSubject:and adding aX-Pepsi-Detected-Languagesheader. Nothing is bounced, so noBOUNCE_STAGEis needed.
Because ENFORCEMENT reaches the stage through the per-address settings layer,
one account can be in training while the rest of the deployment enforces.
Rewriting the Subject: breaks the originator’s DKIM signature and our own ARC
AMS, which both over-sign it — free on a branch that ends in local delivery,
not free on one that relays onward, so soft mode belongs on the former.
52.4. Fusion¶
The stage defaults to FUSION = yes: under the unified pepsi binary with
[pepsi] ALLOW_FUSION on (the default), a predecessor may run it in its own
worker process rather than dispatching it separately. See
pepsi-dispatch.
52.5. Configuration¶
[stage-<name>]: PROGRAM = pepsi-stage-block-language, NEXT_STAGE
(required — every message the stage does not block advances there, including a
whitelisted sender, a bounce, and every message merely flagged under
``ENFORCEMENT = soft``), BOUNCE_STAGE, the WHITELIST/BLACKLIST
language lists (at least one must be non-empty, or every message would fail),
the numeric THRESHOLD (default 0.0), ENFORCEMENT (hard — the
default — or soft) and SUBJECT_FLAG_LABEL (default [!LANG], used only
in soft mode). pepsi-setup rejects an invalid language code or an overlap
between the two lists, and warns about ENFORCEMENT = hard with no
BOUNCE_STAGE (the first blocked message would fail) and about a BLACKLIST
with an empty WHITELIST and a non-negative THRESHOLD.
See pepsi-stage-block-language(1) and Configuration.
52.6. State¶
Inputs:
state.language(treated asnone;q=1when absent) and, for a blocked message,state.dsnand the envelope recipient.Outputs: on the pass path
stateis untouched; on the hard block path the failure-DSN keys pepsi-stage-bounce consumes (state.bounce) are merged; on the soft pathstateis untouched and the header block is rewritten instead.Transitions: score above
THRESHOLD→ advance toNEXT_STAGE; score at or below → reroute toBOUNCE_STAGE(hard) or advance toNEXT_STAGEflagged (soft).
52.7. See also¶
pepsi-stage-detect-language, pepsi-stage-check-whitelist, pepsi-stage-bounce, Supported Features, pepsi-stage-block-language(1).