55. pepsi-stage-edit-settings

Let an account owner change their own settings by e-mail.

55.1. Role

pepsi-stage-edit-settings lets the owner of an account change their own per-address overrides (the pepsi.settings table; see pepsi-settings) by sending a control e-mail. The message must be locally originated, carry the exact subject SUBJECT (default Pepsi), and be addressed to <CONTROL_LOCAL_PART>@<controlled-domain> (default local part pepsi, the domains being [pepsi-ingress] ACCEPTED_DOMAINS); its body is an INI snippet of the options to set. Any other message is passed through untouched, so the stage is safe to place anywhere on the local-submission path. Reference: pepsi-stage-edit-settings(1).

The address whose settings are edited is the envelope sender, and the reply goes back to it — so the operator’s submission authentication must bind the envelope sender.

55.2. Features

  • INI body, leniently parsed: [stage-<name>] sections and OPTION = value lines; greetings, comments and a trailing signature are ignored. An empty value (OPTION =) unsets an override (reverting to the INI default); any other value adds or overrides it.

  • Operator allowlist: only stages named in EDITABLE_STAGES may be changed.

  • Validate before adopt: the combined settings (INI defaults + existing overrides + the new INI) are checked by each affected stage’s real configuration parser (shared with pepsi-setup), on top of the operator’s configuration for the sender (domain:/address: overrides included).

  • Own whitelists only: a WHITELIST_NAME the sender sets for pepsi-stage-auto-whitelist or pepsi-stage-secretary – the stages that write a whitelist on the owner’s behalf – must name one in their own <login>/... namespace, or the one the operator’s configuration already names for them. A shared list or another user’s is refused, since it would let the owner fill it with addresses of their choosing. A value already stored in the row (the operator may have set it with pepsi-settings) does not block edits to other options. This stage is the only way an account owner writes pepsi.settings, so the rule is enforced here, and the operator’s own layers may name any whitelist.

  • All or nothing: on any error nothing is changed and a human-readable reply lists the problems.

  • Confirming reply: on success the merged overrides are stored and a reply quotes the full effective option set of every editable stage, in INI syntax. Both replies carry Subject: Pepsi, use the null sender, and are injected at RESPONSE_STAGE so they are DKIM-signed and relayed.

  • Localised replies: the framing prose comes from the edit-settings.<lang>.body template under [pepsi] TEMPLATE_DIR, chosen from the sender’s detected language (state.language, as pepsi-stage-detect-language recorded it) and falling back to English.

  • Safe by default: an e-mail may only point a stage’s PROGRAM at a pepsi-stage-* command, and may not touch the options that decide which identity a message is signed or sent as (SIGNING_DOMAIN). Both restrictions are lifted by the operator’s UNRESTRICTED_UNSAFE_STAGES = YES, which is what its name says it is.

55.3. Configuration

[stage-<name>]: PROGRAM = pepsi-stage-edit-settings, NEXT_STAGE (required — nearly every message is not a control message and is advanced unchanged), EDITABLE_STAGES (required, whitespace/comma-separated stage names), RESPONSE_STAGE (required, where the reply is injected), SUBJECT (default Pepsi), CONTROL_LOCAL_PART (default pepsi), RESPONSE_FROM (the reply’s From:; by default <CONTROL_LOCAL_PART>@<matched domain>) and UNRESTRICTED_UNSAFE_STAGES (default no). pepsi-setup checks that every EDITABLE_STAGES entry and RESPONSE_STAGE name a real stage, and that the edit-settings.en.body fallback template exists. The stage reads its own options from the base configuration, never from the per-address overrides, so a correspondent cannot e-mail themselves a wider allowlist. See pepsi-stage-edit-settings(1).

55.4. State

  • Inputs: state.local_origin (a message that is not locally originated is never a control message) and state.language (the reply’s language).

  • Outputs: none — a control message’s row is deleted once the reply has been injected; any other message is advanced with its state, including state.dsn, untouched.

55.5. See also

pepsi-settings, pepsi-dispatch, pepsi-stage-check-whitelist, pepsi-setup, Architecture, pepsi-stage-edit-settings(1), pepsi.conf(5).