38. pepsi-stage-anti-spam¶
Gate a message behind a GNU Taler payment (pay-to-send).
38.1. Role¶
pepsi-stage-anti-spam requires a GNU Taler payment for an
otherwise-unclassified message before it may continue down the pipeline. On first
sight it creates a merchant order and pauses the message; once the message is
woken again (the pepsi-resume webhook on payment, or the deadline lapsing) it
forwards, rejects, or waits. Reference: pepsi-stage-anti-spam(1).
38.2. Decision¶
Driven by the message’s state JSON:
spam: true→ drop (delete the row).spam: falseorpaid: true→ forward toNEXT_STAGE(an explicit classification overrides the payment flow).paid: falsepresent → ask the merchant whether the order is paid:paid → forward to
NEXT_STAGE;unpaid past the stored deadline → reject: reroute to
BOUNCE_STAGE(a pepsi-stage-bounce rejection DSN, or a pepsi-stage-discard silent drop), or delete when noBOUNCE_STAGEis wired;unpaid but still before the deadline → with
DELAY_DSN_AFTERset, this is the delay checkpoint: e-mail the sender a one-shot delayed DSN (RFC 3461, only if they asked forNOTIFY=DELAY) without releasing the message, then re-pause untilPAYMENT_DEADLINE; otherwise re-queue aspendingwith a warning (should not happen).
no
paidfield → create a v1 order priced byORDER_CHOICES(order_idis the message token), pause untilPAYMENT_DEADLINE(recordingpaid: falseandpay_deadlineinstate), and e-mail the sender a payment request (see below).
The deadline is kept in state.pay_deadline because the dispatcher clears the
row’s timeout when it requeues a paused message.
A message with the null envelope sender (a bounce or auto-reply) is never
gated: the stage instead tries to verify it as a reply to mail this deployment
genuinely sent, using the Pepsi-Origin: proof-of-origin header (see
SMTP Protocol Extensions). A bounce whose embedded header verifies is forwarded
to NEXT_STAGE; an unverifiable bounce — a forged or expired header, or any
bounce when proof-of-origin is unconfigured — is routed to BOUNCE_TARGET_STAGE
(e.g. a quarantine), never relayed back to a sender and never silently dropped.
38.3. Payment-request reply¶
After that first pause, the stage originates an auto-reply to the sender (when
BLOCK_RESPONSE_STAGE is set). It explains that the recipient requires unknown
senders to pay first, and carries the taler://pay/<backend>/<token> URI as a
link and as a QR code (an inline image/png referenced by cid:, so it
renders in the widest range of clients while the message stays self-contained),
the acceptable payment options (the ORDER_CHOICES, omitting token-family
choices), and a pointer to https://wallet.taler.net/ for senders without a
wallet. When the original From: carries a display name, the sender is
addressed by it. The body is rendered from the
payment-request.<lang>.body Mustache template under
[pepsi] TEMPLATE_DIR (only en ships; it is the fallback). The reply uses
the null sender <> and enters at BLOCK_RESPONSE_STAGE (normally a
signing/relay chain), so it is signed and delivered like any other mail. Sending
is best-effort — a failure is logged but never blocks the pause.
The reply also carries two machine-readable headers so a sending Pepsi can settle
the demand automatically (see pepsi-stage-auto-pay): a Taler: header
with the taler://pay/… URI, and the original message’s Pepsi-Origin: header
copied verbatim (when present), letting the originating site verify the demand
is for its own mail and meter its per-message spend.
38.4. Configuration¶
[stage-<name>]: PROGRAM = pepsi-stage-anti-spam, NEXT_STAGE,
BOUNCE_STAGE, ORDER_CHOICES (the verbatim Taler v1 order choices
JSON array, required), PAYMENT_DEADLINE (h/m/s units; default
48h), DELAY_DSN_AFTER (h/m/s; optional, send a delayed DSN
mid-window — see above), SUMMARY and FULFILLMENT_MESSAGE. For the payment-request reply:
BLOCK_RESPONSE_STAGE (where to inject it; unset disables the reply),
BLOCK_RESPONSE_FROM (its From:; default the original recipient) and
BLOCK_RESPONSE_SUBJECT. Requires the shared [pepsi-payments] merchant
backend and, for the resume webhook, [pepsi-httpd]
RESUME_AUTHORIZATION_TOKEN. See pepsi-stage-anti-spam(1).
38.5. State¶
Inputs:
state.spam/state.paid(booleans),state.pay_deadline(epoch seconds),state.dsn(recipientnotify/orcpt).Outputs: on the first encounter,
{paid: false, pay_deadline}merged intostate, the row paused, and a payment-request reply injected atBLOCK_RESPONSE_STAGE; on rejection, astate.bounceobject (permanent) for the bounce stage.
38.6. See also¶
pepsi-stage-bounce, pepsi-stage-discard, pepsi-httpd, pepsi-setup, SMTP Protocol Extensions, pepsi-stage-anti-spam(1).