48. pepsi-stage-autocrypt-learn

Learn correspondents’ keys from the mail they send us.

48.1. Role

pepsi-stage-autocrypt-learn is where an inbound message teaches Pepsi a public key: the sender’s Autocrypt: header, an attached application/pgp-keys part, the certificates an S/MIME signature carries, and — for a message that arrived encrypted — the Autocrypt-Gossip: fields introducing the other recipients (Autocrypt Level 1 §5.3). It learns and advances; it never drops, pauses, bounces or rewrites a message, so NEXT_STAGE is mandatory. Reference: pepsi-stage-autocrypt-learn(1).

48.2. Features

  • Placement. It runs after the spam checks and before delivery, because Level 1 §5.3 says peer state SHOULD be ignored for a message believed to be spam, and that can only be honoured once a spam verdict exists. pepsi-stage-decrypt runs first on the inbound path so everything downstream sees plaintext, which is before any stage has an opinion about whether the message is junk.

  • Honours the spam verdict: a message with state.spam = true teaches nothing, unless LEARN_FROM_SPAM says otherwise.

  • Only the sender’s own key from a message’s headers and attachments; introducing a third party is what gossip is for, and gossip lands on a lower rung.

  • Gossip only from ciphertext: believed only when pepsi-stage-decrypt recorded that the message arrived encrypted and that its arriving header block carried no Autocrypt-Gossip: field of its own. Neither is visible from the committed plaintext, so both are read from state.crypto.in.

  • Never a key for an address this host serves: a peer key for a local address is what our own outbound mail to that user would be encrypted with, so a gossip field naming one is a key substitution rather than an introduction.

  • Records that a correspondent holds our key: when a message was decrypted with one of our MTA keys and carries a valid signature by its From: address covering the plaintext, a pepsi.peer_has_own_key row is written, so pepsi-stage-encrypt stops attaching that key as a file (ATTACH_KEYS_AS_FILES). This happens whatever LEARN_KEYS and the spam verdict say, since it concerns our key, not theirs.

  • Unprivileged: it writes only public key material, so unlike the crypto stages it needs no setuid bit and is folded into the multi-call pepsi binary.

48.3. Configuration

LEARN_KEYS (default yes; off makes the stage learn no key at all), LEARN_GOSSIP (default yes, and only meaningful while LEARN_KEYS is on), LEARN_FROM_SPAM (default no — that is Autocrypt Level 1 §5.3’s SHOULD), the locality options (used only to refuse gossip about local users) LOCAL_DOMAINS (defaulting to [pepsi-ingress] ACCEPTED_DOMAINS) / TARGETS / RECIPIENT_DELIMITER, and a mandatory NEXT_STAGE. The whole message is loaded, since the key material is in it. See Configuration.

[stage-autocrypt-learn]
PROGRAM = pepsi-stage-autocrypt-learn
NEXT_STAGE = local

48.4. What a learnt key is worth

Little, deliberately. Harvested keys sit at rank inbound and gossiped ones at gossip — the bottom two rungs of the trust ladder. Such a key can never displace one from discovery or from an operator; a signature checked against one is reported valid-untrusted at best, so it never sets state.signature_verified; and a peer_key row is ignored entirely for an address this host holds an identity for. Within those two rungs the rule is newest wins on the message’s Autocrypt effective date, so a correspondent who reinstalls their client stops receiving mail encrypted to a key they no longer hold — protection against a passive adversary, which is all Autocrypt claims.