40. pepsi-stage-check-whitelist

Mark mail from trusted senders as non-spam.

40.1. Role

pepsi-stage-check-whitelist consults a named whitelist of trusted senders and, when the message’s From: header matches, records state.spam = false so a later pepsi-stage-anti-spam lets the message through without payment. Place it ahead of the anti-spam stage. It only annotates the state and advances — it never drops, bounces or pauses a message. Reference: pepsi-stage-check-whitelist(1).

40.2. Features

  • Database-backed whitelists: the pepsi.whitelist table groups rows under a whitelist_name; the stage’s WHITELIST_NAME option selects the group.

  • POSIX ERE matching: each whitelist_regex is an extended POSIX regular expression matched case-insensitively against the From: header (evaluated by PostgreSQL’s ~* operator, in a single round-trip). The expression is unanchored; anchor it with ^/$ to match the whole value.

  • Optional signature conditions per row:

    • dkim_required → matches only if the From: domain is authenticated: state.auth.dkim = pass, or an ARC pass that DMARC also confirms (state.auth.arc = pass and state.auth.dmarc = pass). ARC pass alone is only chain integrity (a one-hop chain can be self-minted over a forged From:), so it does not satisfy the row by itself.

    • signature_required → matches only if state.signature_verified is true, which pepsi-stage-decrypt sets for a message whose end-to-end signature verified against a trusted key. A valid-untrusted verdict deliberately does not set it, so such a row is a genuine “this correspondent signs, verifiably” gate rather than a “someone signed this” one. Place a decrypt stage before this one, or the row never matches.

  • Non-destructive: on a match it merges spam: false and advances to NEXT_STAGE; on no match it advances unchanged. A message with no From: header matches nothing.

40.3. Configuration

[stage-<name>]: PROGRAM = pepsi-stage-check-whitelist, WHITELIST_NAME (required — the whitelist_name group to consult) and NEXT_STAGE. See pepsi-stage-check-whitelist(1).

40.4. State

  • Inputs: state.auth.dkim / state.auth.arc / state.auth.dmarc (for dkim_required rows) and state.signature_verified (for signature_required rows; written by pepsi-stage-decrypt). The From: header comes from the from_header column.

  • Outputs: on a match, spam: false merged into state; otherwise state is unchanged.

40.5. See also

pepsi-stage-anti-spam, pepsi-stage-arc, Supported Features, pepsi-stage-check-whitelist(1).