71. RFC Index

Pepsi aims to be a standards-compliant e-mail forwarder and a standards-compliant end-to-end crypto gateway. This chapter is the single place that maps every RFC Pepsi implements (or deliberately does not yet) to where in the system it is realised, so a reviewer can jump from a standard to its code and configuration.

The summary table lists every applicable RFC at a glance; the per-RFC notes below give the detail. RFCs that are planned but not yet implemented are collected under Applicable RFCs not yet implemented.

Not everything indexed here is an RFC, and that is deliberate. The OpenPGP Web Key Directory is an Internet-Draft; Autocrypt and the VKS key-server protocol are de-facto standards; NTLM is a Microsoft Open Specification; XOAUTH2 has no specification body at all; SRS and Maildir are published schemes that were never put through the IETF; FIPS 186-4 is a NIST publication. Each is what the deployed world actually speaks, so leaving them out would make this chapter describe a system nobody runs. They are listed after the RFCs, italicised, with their status named.

Implementing a standard is not the same as interoperating with the clients that claim to implement it. Client interoperability records which of these have been measured against real software, which are one-off observations, and which have never been run at all.

A note on what “implemented in” means: it names the module or program where the standard is realised, not every caller. Where a standard is only partly implemented — BINARYMIME of RFC 3030, Autocrypt gossip without its inbound-gossip reading half — the cell says so, and the boundary is stated rather than left for the reader to discover. Standards Pepsi deliberately does not implement are under Applicable RFCs not yet implemented with the reason.

71.1. Summary table

RFC

Title (subject)

Implemented in

RFC 1035

Domain names — implementation and specification (DNS)

All DNS lookups; domain/label syntax in pepsi-common::domain

RFC 1870

SMTP service extension for message size declaration (SIZE)

Advertised and enforced by pepsi-ingress; the outbound client honours the next hop’s announced limit, pepsi-common::smtp::client

RFC 1918

Address allocation for private internets

Together with RFC 6598 and RFC 2544, the address ranges an outbound fetch refuses so a key-discovery URL cannot reach inside the deployment (pepsi-keydisc’s SSRF guard)

RFC 1951

DEFLATE compressed data format

The bound on decompressing fetched key material — a compression bomb is refused rather than expanded (pepsi-keydisc)

RFC 2033

Local Mail Transfer Protocol (LMTP)

Local delivery to an MDA (Dovecot), pepsi-stage-relay-to-lmtp

RFC 2034

SMTP service extension for returning enhanced error codes

ENHANCEDSTATUSCODES, advertised by pepsi-ingress; every reply carries an RFC 3463 code

RFC 2045

MIME Part One: format of message bodies (transfer-encodings)

8-bit→7-bit body downgrade, pepsi-common::mime

RFC 2046

MIME Part Two: media types (multipart and boundary syntax)

MIME tree parsing and boundary validation, pepsi-common::mime and pepsi-crypto::mime

RFC 2047

MIME Part Three: message header extensions (encoded-words)

UTF-8 header downgrade, pepsi-common::mime

RFC 2104

HMAC: keyed-hashing for message authentication

The SRS envelope-sender MAC (pepsi-common::srs), the Pepsi-Origin proof-of-origin header, and the key-encryption-key derivation in pepsi-common::keystore::wrap (an HKDF-Extract-shaped construction with a fixed label)

RFC 2195

IMAP/POP AUTHorize extension for simple challenge/response (CRAM-MD5)

Outbound SMTP AUTH to a smarthost, pepsi-common::smtp::sasl

RFC 2231

MIME parameter value and encoded word extensions

Continued and character-set-tagged header parameters, pepsi-common::mime

RFC 2392

Content-ID and Message-ID uniform resource locators

The cid: reference from the payment-request auto-reply’s HTML to its inline QR-code image, pepsi-stage-anti-spam

RFC 2831

Using digest authentication as a SASL mechanism (DIGEST-MD5)

Outbound SMTP AUTH (deprecated; see RFC 6331), pepsi-common::smtp::sasl

RFC 2920

SMTP service extension for command pipelining

PIPELINING, advertised by pepsi-ingress; the outbound client writes the envelope and DATA in one go

RFC 2986

PKCS #10: certification request syntax

Certificate-signing requests for externally-issued S/MIME certificates, pepsi-crypto::keygen

RFC 3030

SMTP service extensions for large and binary messages (CHUNKING/BDAT)

pepsi-ingress (BINARYMIME not advertised)

RFC 3156

MIME security with OpenPGP (PGP/MIME)

multipart/encrypted and multipart/signed containers built and parsed by pepsi-crypto::mime; micalg from pepsi-crypto::pgp

RFC 3207

SMTP service extension for secure SMTP over TLS (STARTTLS)

pepsi-ingress listeners; outbound SMTP client

RFC 3339

Date and time on the Internet: timestamps

Report generation timestamps, pepsi-common::tlsrpt

RFC 3370

Cryptographic Message Syntax (CMS) algorithms

S/MIME digest and signature algorithm identifiers, pepsi-crypto::smime

RFC 3394

Advanced Encryption Standard (AES) key wrap algorithm

Wrapping the content-encryption key in an ECDH KeyAgreeRecipientInfo, pepsi-crypto::smime

RFC 3461

SMTP service extension for Delivery Status Notifications (DSN)

pepsi-common::dsn; ingress, relay stages, bounce stage

RFC 3463

Enhanced mail system status codes

DSN status codes, pepsi-stage-bounce

RFC 3464

An extensible message format for Delivery Status Notifications

multipart/report generation, pepsi-stage-bounce

RFC 3492

Punycode

IDNA label encoding for internationalized domains, pepsi-common::domain and pepsi-common::dns

RFC 3565

Use of AES encryption in CMS

AES-256-CBC EnvelopedData, the downgrade container when a recipient cannot read AEAD (pepsi-crypto::smime)

RFC 3676

The text/plain format=flowed media type

Body-text extraction and the -- signature cut, pepsi-common::mime_text

RFC 3834

Recommendations for automatic responses to electronic mail

Auto-Submitted: auto-replied auto-replies (anti-spam, edit-settings)

RFC 3848

ESMTP and LMTP transmission types (with clause)

Received: header (SMTP/ESMTP/ESMTPS), ingress

RFC 3864

Registration procedures for message header fields

The procedure Pepsi’s two private header fields (SMTP Protocol Extensions) are not registered under; both are unregistered by design

RFC 4013

SASLprep: stringprep profile for user names and passwords

SCRAM username/password preparation, pepsi-common::smtp::sasl

RFC 4055

Additional algorithms and identifiers for RSA in PKIX

RSAES-OAEP and RSASSA-PSS parameter encoding, pepsi-crypto::smime

RFC 4121

The Kerberos 5 GSS-API mechanism, v2

Outbound smarthost AUTH = gssapi (via system Kerberos), pepsi-common::smtp::gssapi

RFC 4155

The application/mbox media type

mbox mailbox reading for whitelist import, pepsi-helper-mailbox-scan

RFC 4422

Simple Authentication and Security Layer (SASL) — EXTERNAL mechanism

Outbound SMTP AUTH EXTERNAL via TLS client certificate (smarthost)

RFC 4511

LDAP: the protocol

LDAP key discovery, pepsi-keydisc’s ldap module (behind the ldap cargo feature, off by default)

RFC 4514

LDAP: string representation of distinguished names

Certificate subject/issuer DN rendering, pepsi-crypto::smime

RFC 4515

LDAP: string representation of search filters

Filter escaping for the LDAP discovery query — the injection guard, pepsi-keydisc

RFC 4616

The PLAIN SASL mechanism

Inbound (ingress) and outbound (smarthost) AUTH PLAIN

RFC 4648

The Base16, Base32, and Base64 data encodings

SRS hash encoding (pepsi-common::srs); key material

RFC 4752

The Kerberos V5 (GSSAPI) SASL mechanism

Outbound smarthost AUTH = gssapi, pepsi-common::smtp::gssapi

RFC 4954

SMTP service extension for authentication (AUTH)

Inbound AUTH PLAIN/LOGIN (ingress, TLS-only) and the full outbound smarthost SASL suite

RFC 5083

CMS AuthEnvelopedData content type

The default S/MIME encryption container (AES-256-GCM), pepsi-crypto::smime

RFC 5084

Using AES-CCM and AES-GCM in CMS

AES-256-GCM AuthEnvelopedData, the default S/MIME container, pepsi-crypto::smime

RFC 5228

Sieve: an email filtering language

Run by the MDA (Dovecot) on LMTP delivery; Pepsi implements no Sieve itself

RFC 5280

Internet X.509 PKI certificate and CRL profile

Certificate parsing, extension handling and path validation, pepsi-crypto::trust; issuance in pepsi-crypto::keygen

RFC 5321

Simple Mail Transfer Protocol

Core of ingress and both relay stages; envelope handling, MX, null sender

RFC 5322

Internet Message Format

Header/body model (pepsi-common::message); parsing and signing

RFC 5480

Elliptic curve cryptography subject public key information

EC public-key encoding in certificates, pepsi-crypto::smime

RFC 5652

Cryptographic Message Syntax (CMS)

SignedData/EnvelopedData/certs-only built and opened by pepsi-crypto::smime (the cms crate supplies the types only)

RFC 5753

Use of ECC algorithms in CMS

ECDH key-agreement RecipientInfo (P-256/P-384 + X9.63 KDF + AES-KW), pepsi-crypto::smime

RFC 5758

Additional algorithms and identifiers for DSA and ECDSA in PKIX

ecdsa-with-SHA256/-SHA384 signature identifiers, pepsi-crypto::smime

RFC 5802

Salted Challenge Response Authentication Mechanism (SCRAM)

Outbound SCRAM-SHA-1/-SHA-256 (±``-PLUS``), pepsi-common::smtp::sasl

RFC 5890

Internationalized Domain Names for Applications (IDNA2008): definitions

Domain handling throughout, via the idna crate; see also RFC 3492

RFC 5915

Elliptic curve private key structure

EC private-key encoding, pepsi-crypto::keygen

RFC 5929

Channel bindings for TLS (tls-server-end-point)

SCRAM -PLUS channel binding, pepsi-common::smtp::sasl

RFC 5958

Asymmetric key packages (PKCS #8)

Private-key encoding at rest, pepsi-crypto::keygen and pepsi-common::keys

RFC 5987

Character set and language encoding for HTTP header field parameters

filename* decoding in multipart form uploads, pepsi-httpd

RFC 6125

Service identity in TLS (certificate name checking)

MTA-STS certificate validation, pepsi-stage-relay-to-internet

RFC 6152

SMTP service extension for 8-bit MIME transport (8BITMIME)

Advertised by ingress; per-hop re-advertise/downgrade in the relay stages

RFC 6265

HTTP state management mechanism (cookies)

The administrative session cookie and the secure-link portal cookie, both __Host- prefixed; pepsi-httpd

RFC 6331

Moving DIGEST-MD5 to Historic

The reason DIGEST-MD5 is deprecated and excluded from AUTH = auto

RFC 6376

DomainKeys Identified Mail (DKIM) signatures

Verification (ingress) and signing (pepsi-stage-dkim-sign)

RFC 6409

Message submission for mail

Submission listeners (SUBMISSION = yes): mandatory AUTH, Date:/Message-ID: fixups, Sender: fixup and submission-identity enforcement

RFC 6531

SMTP extension for internationalized email (SMTPUTF8)

Advertised by ingress; per-hop re-advertise/downgrade in the relay stages

RFC 6598

IANA-reserved IPv4 prefix for shared address space

Part of the outbound-fetch address guard; see RFC 1918

RFC 6648

Deprecating the X- prefix in application protocols

Why Pepsi-Origin: and Taler: carry no X- prefix, while the verdict headers pepsi-stage-decrypt strips deliberately do (X-Pepsi-* is a namespace to be removed, not a field to be adopted)

RFC 6698

DNS-based authentication of named entities (DANE): TLSA

TLSA record types and matching, pepsi-common::smtp::dane; the SMTP profile is RFC 7672

RFC 6749

The OAuth 2.0 authorization framework

Smarthost token acquisition and refresh, pepsi-helper-token-refresh

RFC 6750

The OAuth 2.0 authorization framework: bearer token usage

The Authorization: Bearer form of the administrative API’s tokens, The administrative API — the wire form only; Pepsi mints them locally and runs no authorization server

RFC 6761

Special-use domain names

Names that must not be resolved on the public DNS, short-circuited in pepsi-common::dns

RFC 6840

Clarifications and implementation notes for DNSSEC

The AD bit read from the validating resolver’s response — Pepsi trusts a validating resolver rather than validating itself; pepsi-common::dns

RFC 6891

Extension mechanisms for DNS (EDNS(0))

UDP payload size on outgoing queries, pepsi-common::dns

RFC 6979

Deterministic usage of DSA and ECDSA

Nonce generation for ECDSA signatures, pepsi-crypto::smime

RFC 7208

Sender Policy Framework (SPF) for authorizing use of domains

Inbound SPF verification (ingress, via mail_auth)

RFC 7235

HTTP/1.1: authentication

The Authorization: Bearer scheme on /api/v1, pepsi-httpd

RFC 7489

Domain-based Message Authentication, Reporting, and Conformance (DMARC)

Inbound DMARC evaluation and optional enforcement (ingress)

RFC 7505

A “Null MX” no-service resource record

MX classification, pepsi-stage-relay-to-internet

RFC 7595

Guidelines and registration procedures for URI schemes

The procedure the taler:// scheme is not registered under; noted so its status is not mistaken for IANA-registered

RFC 7628

A set of SASL mechanisms for OAuth (OAUTHBEARER)

Outbound smarthost AUTH = oauth (OAUTHBEARER, de-facto XOAUTH2)

RFC 7672

SMTP security via opportunistic DANE TLS (TLSA)

DANE = off|warn|strict on both relay stages; pepsi-common::smtp::dane

RFC 7677

SCRAM-SHA-256 and SCRAM-SHA-256-PLUS SASL mechanisms

Outbound SCRAM-SHA-256 (±``-PLUS``), pepsi-common::smtp::sasl

RFC 7748

Elliptic curves for security (X25519)

Curve25519 key agreement in OpenPGP and TLS

RFC 7929

DNS-based authentication of named entities (DANE) bindings for OpenPGP

OPENPGPKEY records printed by pepsi-keys dns; AD-gated lookups by pepsi-keydisc@dane (pepsi-keydisc)

RFC 8017

PKCS #1 v2.2: RSA cryptography specification

RSA signature and key-transport primitives (via the rsa crate) for DKIM, ARC and S/MIME

RFC 8018

PKCS #5: password-based cryptography (PBKDF2)

SCRAM-SHA-* salted password derivation, pepsi-common::smtp::sasl

RFC 8162

Using secure DNS to associate certificates with domain names for S/MIME

SMIMEA records printed by pepsi-keys dns; AD-gated lookups by pepsi-keydisc@dane (pepsi-keydisc)

RFC 8314

Cleartext considered obsolete: use of TLS for submission and access

Implicit-TLS submission listener (MODE = tls), ingress; negotiated TLS version/cipher recorded in the Received: trace header (§4.3)

RFC 8446

The Transport Layer Security (TLS) protocol version 1.3

Every TLS listener and client, over rustls — inbound STARTTLS/implicit TLS, outbound relay, LMTP, HTTP and LDAP

RFC 8460

SMTP TLS Reporting (TLSRPT)

Outbound TLS-session recording (relay stages) + daily reports (pepsi-tlsrpt)

RFC 8461

SMTP MTA Strict Transport Security (MTA-STS)

Policy enforcement (pepsi-stage-relay-to-internet); publishing (pepsi-setup)

RFC 8463

A new cryptographic signature method for DKIM (Ed25519)

Ed25519 DKIM keys/signatures, pepsi-common::keys

RFC 8550

S/MIME 4.0 certificate handling

Path building, emailProtection EKU and rfc822Name binding (pepsi-crypto::trust); certificate issuance (pepsi-crypto::keygen, pepsi-keys::ca)

RFC 8551

S/MIME 4.0 message specification

application/pkcs7-mime / -signature and the smime-type parameter, pepsi-crypto::mime + pepsi-crypto::smime

RFC 8601

Message header field for indicating message authentication status

Authentication-Results (incl. iprev), pepsi-common::auth

RFC 8617

The Authenticated Received Chain (ARC) protocol

ARC verify/sign/seal, pepsi-stage-arc

RFC 8905

The payto URI scheme

Wire-transfer targets in the wallet self-service reply, pepsi-stage-auto-pay

RFC 8959

The secret-token URI scheme

The merchant access token’s form, pepsi-common::config

RFC 9051

Internet Message Access Protocol (IMAP) version 4rev2

Read-only mailbox scanning for whitelist import (EXAMINE + BODY.PEEK[HEADER], so nothing is marked \Seen), pepsi-helper-mailbox-scan

RFC 9106

Argon2 memory-hard function for password hashing and PoW

The secure-link content key derived from the recipient’s PIN (pepsi-secure-link::crypto) and administrator password hashing (pepsi-httpd’s admin module)

RFC 9110

HTTP semantics

Request/response handling in pepsi-httpd

RFC 9112

HTTP/1.1

The wire protocol served by pepsi-httpd, over hyper

RFC 9580

OpenPGP (the crypto refresh; successor to RFC 4880)

pepsi-crypto::pgp over sequoia-openpgp; explicit SEIPDv2/v1 container negotiation

Autocrypt Level 1

The Autocrypt: key-advertisement header (a de-facto standard, not an RFC)

Harvested from inbound mail at the lowest trust rank, pepsi-keydisc’s harvest module; emitted on outbound mail by pepsi-stage-encrypt’s autocrypt module, under [stage-encrypt] AUTOCRYPT. §5.3 key gossip is emitted by the same stage’s gossip module under [stage-encrypt] AUTOCRYPT_GOSSIP (default off) and read by pepsi-stage-autocrypt-learn under LEARN_GOSSIP (default on), onto a trust rung of its own

FIPS 186-4

Digital Signature Standard (a NIST publication)

The bits2int truncation rule shared with RFC 6979, pepsi-crypto::smime

draft-ietf-mailmaint-autoconfig

Mail account autoconfiguration (an Internet-Draft of the IETF mailmaint working group, intended for Informational status)

The config-v1.1.xml document served by pepsi-httpd on autoconfig.<domain> and under /.well-known/autoconfig/, built from [pepsi-autoconfig] and the submission listener

MS-NLMP

The NT LAN Manager authentication protocol (a Microsoft Open Specification, not an RFC)

Outbound smarthost AUTH NTLM, pepsi-common::smtp::sasl. NTLMv2 only — NTLMv1 is cryptographically broken — with channel binding, and never offered outside TLS

Maildir

D. J. Bernstein’s mailbox format (a specification, not an RFC — tmp/new/cur with the rename-into-new delivery rule)

pepsi-stage-relay-to-maildir via the setuid helper; Maildir++ recursion when scanning for whitelist import

SRS

The Sender Rewriting Scheme (a published scheme with no RFC; the SRS0/SRS1 envelope-address format)

pepsi-common::srs, pepsi-stage-srs, and the reverse decode at ingress. The MAC is RFC 2104 HMAC

VKS (keys.openpgp.org)

The verifying key server’s /vks/v1 HTTP protocol (a de-facto standard, not an RFC — it is not HKP)

Lookup by pepsi-keydisc@vks; upload and address verification by pepsi-keys, whose confirmation mail pepsi-stage-vks-confirm answers

XOAUTH2

Google’s and Microsoft’s pre-standard SASL bearer-token mechanism (no specification body; superseded by RFC 7628 OAUTHBEARER, which the same servers also accept)

Outbound smarthost AUTH, pepsi-common::smtp::sasl. Offered because some tenants still refuse OAUTHBEARER

draft-koch-openpgp-webkey-service

OpenPGP Web Key Directory (an Internet-Draft, not an RFC)

Client side: pepsi-keydisc@wkd-advanced / @wkd-direct. Serving side: the four endpoints of pepsi-httpd, answered from the stored pepsi_common::keystore::wkd_local_part_hash

71.2. Per-RFC notes

71.2.1. RFC 1035 — Domain Names (DNS)

All DNS resolution (MX, A/AAAA, TXT for SPF/DKIM/DMARC/MTA-STS, and reverse PTR) follows RFC 1035. Domain-name and label syntax limits are enforced in pepsi-common::domain. DNS is used by ingress (authentication), the ARC stage (re-verification) and pepsi-stage-relay-to-internet (MX discovery and address caching in the pepsi.dns_address table).

71.2.2. RFC 2045 / RFC 2047 — MIME bodies and header encoded-words

When a next hop does not advertise 8BITMIME (RFC 6152), pepsi-common::mime walks the MIME tree and re-encodes each 8-bit leaf part with a 7-bit content-transfer-encoding (RFC 2045: quoted-printable for text/*, base64 otherwise). When a hop does not advertise SMTPUTF8 (RFC 6531), UTF-8 header fields are rewritten as RFC 2047 encoded-words. See pepsi-stage-relay-to-internet.

71.2.3. RFC 3030 — CHUNKING / BDAT

Ingress advertises CHUNKING and accepts message bodies framed with BDAT chunks (in addition to DATA). The BODY=BINARYMIME body value of the same RFC is not advertised or accepted. See pepsi-ingress.

71.2.4. RFC 3207 — STARTTLS

Ingress listeners in starttls mode advertise the STARTTLS verb and upgrade a cleartext session in place. The outbound SMTP client uses STARTTLS opportunistically (or as required by MTA-STS). Implicit TLS is governed by RFC 8314 instead.

71.2.5. RFC 3461 / RFC 3463 / RFC 3464 — Delivery Status Notifications

Ingress advertises the DSN extension and validates/stores RET/ENVID/NOTIFY/ORCPT under state.dsn (pepsi-common::dsn). The relay stages propagate the parameters to a next hop that also advertises DSN (RFC 3461 §5–6). pepsi-stage-bounce emits the notification as an RFC 3464 multipart/report with RFC 3463 enhanced status codes, honouring NOTIFY (failure by default; success/delay only on explicit request). See Supported Features and pepsi-stage-bounce.

71.2.6. RFC 3834 — Automatic responses

The auto-replies Pepsi originates — the pepsi-stage-anti-spam payment-request message and the pepsi-stage-edit-settings confirmation/error replies — set Auto-Submitted: auto-replied per RFC 3834 and are sent with the null sender. A message that is itself an automatic response (null sender / Auto-Submitted) is never gated, bounced or auto-replied to, so the stages cannot form a reply loop. See pepsi-stage-anti-spam.

71.2.7. RFC 3848 — ESMTP transmission types

The Received: trace header ingress prepends records the transport in the with clause as SMTP, ESMTP, ESMTPS or — when the session authenticated over TLS with SMTP AUTHESMTPSA, per RFC 3848.

71.2.8. RFC 4648 — Base16/Base32/Base64

SRS addresses encode their truncated HMAC in base32 (RFC 4648) so the token is case-insensitive and address-safe; key material uses base64. See pepsi-stage-srs.

71.2.9. RFC 4954 — SMTP AUTH

Both directions are supported. Inbound: ingress implements the AUTH verb with the PLAIN (RFC 4616) and LOGIN mechanisms (SASL PLAIN initial-response and the prompted LOGIN exchange). It is advertised and accepted only on an encrypted session (implicit TLS or after STARTTLS); an AUTH attempt in cleartext is refused with 538. Credentials are verified against a configured SASL backend (Dovecot’s auth-client socket, SASL_TYPE/SASL_PATH); a successful AUTH marks the session locally originated, lets it relay to any domain, and stamps ESMTPSA in the Received: with clause.

Outbound: the SMTP client authenticates to a smarthost via the AUTH option of an […-mta-*] section. The full mechanism suite (all in pepsi-common::smtp::sasl, hand-rolled on the RustCrypto primitives already in-tree — no SASL/SCRAM crate) is:

  • plainPLAIN (RFC 4616) and loginLOGIN (cleartext password inside the TLS tunnel).

  • cram-md5CRAM-MD5 (RFC 2195), HMAC-MD5 challenge-response.

  • scram-sha-1 / scram-sha-256 and their -plus variants — SCRAM (RFC 5802) and SCRAM-SHA-256 (RFC 7677); the -PLUS forms add tls-server-end-point channel binding (RFC 5929). The server signature is verified for mutual authentication; usernames/passwords are SASLprep’d (RFC 4013).

  • digest-md5DIGEST-MD5 (RFC 2831), deprecated (RFC 6331 moved it to Historic): supported for legacy smarthosts but excluded from auto and warned about both at pepsi-setup validation and at runtime.

  • oauthOAUTHBEARER (RFC 7628), falling back to the de-facto XOAUTH2; the bearer token is read from TOKEN_FILE (see pepsi-helper-token-refresh).

  • external — SASL EXTERNAL (RFC 4422), authenticated by the configured TLS client certificate rather than a password.

  • ntlm — the de-facto Microsoft NTLM mechanism (no RFC; NTLMv2 only). Run only under TLS, so it always carries Extended Protection for Authentication: the tls-server-end-point (RFC 5929) channel-binding and smtp/<host> SPN AV pairs plus the MIC. Weak and without server authentication — flagged by pepsi-setup.

  • gssapi — SASL GSSAPI / Kerberos (RFC 4752, over the RFC 4121 Kerberos 5 GSS mechanism), via the system Kerberos library (pepsi-common::smtp::gssapi). The ticket comes from a credential cache kept fresh out of band; the SASL security layer is negotiated to no security layer (TLS already protects the session).

  • auto — negotiate the strongest mechanism the smarthost’s EHLO offers (SCRAM-SHA-256-PLUS > SCRAM-SHA-256 > SCRAM-SHA-1-PLUS > SCRAM-SHA-1 > CRAM-MD5 > LOGIN > PLAIN; DIGEST-MD5, NTLM and GSSAPI are never auto-selected).

As inbound, the outbound client refuses to send credentials over an unencrypted connection. A 5xx rejection of a password mechanism is treated as a permanent failure (bounce). See pepsi-ingress and pepsi-stage-relay-to-smarthost.

GSSAPI/Kerberos is the one mechanism that is not hand-rolled: it links the system Kerberos GSS implementation (MIT krb5 / Heimdal). The Debian package therefore build-depends on libkrb5-dev and depends on libgssapi-krb5-2.

71.2.10. RFC 2033 / RFC 5228 — LMTP local delivery and Sieve

pepsi-stage-relay-to-lmtp delivers a message to a local Mail Delivery Agent — typically Dovecot — over LMTP (RFC 2033): it offers every recipient in a single LMTP transaction (LHLO, optional STARTTLS and SASL, multi-reply DATA) and routes each recipient onward by the MDA’s per-recipient reply (delivered, or classified by its RFC 3463 status). The MDA, not Pepsi, runs each recipient’s Sieve (RFC 5228) filter as it files the mail; Pepsi implements no Sieve itself. The shared LMTP client is pepsi-common::smtp::deliver_lmtp. Because the MDA drops privilege, this stage needs no setuid/setgid helper (unlike pepsi-stage-relay-to-maildir). See Supported Features and pepsi-stage-relay-to-lmtp.

71.2.11. RFC 5321 — SMTP

RFC 5321 is the backbone: the ingress command grammar and replies; the envelope (MAIL FROM/RCPT TO, the null sender <>); the domainless <Postmaster> mailbox (§4.5.1); the Received: trace header (§4.4); implicit MX via address records (§5.1); and the “never bounce a bounce” rule (§6.1). It governs ingress and both relay stages.

71.2.12. RFC 5322 — Internet Message Format

Messages are stored split into a header block and a body at the first blank line (pepsi-common::message); header selection for signing and the parsed From:/Subject: follow RFC 5322. DKIM/ARC h= selection is bottom-up so a prepended header never disturbs an existing signature.

71.2.13. RFC 3156 / RFC 9580 — OpenPGP and PGP/MIME

RFC 9580 is the 2024 OpenPGP specification (the “crypto refresh”, succeeding RFC 4880); RFC 3156 is how an OpenPGP message is carried in MIME. Pepsi implements both over the sequoia-openpgp library, in pepsi-crypto::pgp (cryptography) and pepsi-crypto::mime (containers).

The MIME half (RFC 3156). Encryption emits multipart/encrypted; protocol="application/pgp-encrypted" with the Version: 1 control part and an application/octet-stream ciphertext part (§4). Detached signing emits multipart/signed; protocol="application/pgp-signature" with the micalg parameter computed from the hash actually used (§5) — pgp-sha256 for the default. Both forms are recognised on the way in, as is non-MIME inline armor, which [pepsi] CRYPTO_INLINE_PGP may refuse.

The container question (RFC 9580). The choice between the RFC 9580 SEIPDv2 container (AEAD) and the RFC 4880 SEIPDv1 container (an MDC) is made explicitly from the recipient keys’ declared capabilities rather than left to the library, so a downgrade is a decision that gets recorded rather than a silent one; [pepsi] CRYPTO_ALLOW_DOWNGRADE governs whether it is permitted at all. Reading a SEIPDv1+MDC message is never gated — most of the installed base still produces them — but the pre-MDC SED packet is refused outright.

See Key management, pepsi-stage-encrypt and pepsi-stage-decrypt; Client interoperability records what has been measured against gpg.

71.2.14. RFC 5280 — X.509 certificates and path validation

Every S/MIME decision rests on this one. pepsi-crypto::trust parses certificates, applies the extensions that matter for mail (basicConstraints, keyUsage, the emailProtection extended key usage of §4.2.1.12, and the rfc822Name subject alternative name that binds a certificate to an address) and builds a path to a configured anchor.

Two boundaries are worth stating because the code is deliberate about them:

  • The trust store is searched before the message’s own certificates. A CMS SignerIdentifier names a certificate by issuer and serial number, so a message can carry a forged certificate bearing a pinned one’s issuer and serial with a different key. A verifier that looked at the message first would accept it.

  • Revocation is not checked. Neither the CRL profile of §5 nor OCSP (RFC 6960) is consulted — see Applicable RFCs not yet implemented. The Revocation value on a validated path is always NotChecked, which is reported honestly rather than rendered as “not revoked”.

A certificate that chains to no configured anchor is untrusted, not invalid (Verdict::Untrusted): most of the world’s signed mail chains to a CA nobody handed us an anchor for, and reporting that as a failure would make the indicator useless.

71.2.15. RFC 5652 / 5083 / 5753 / 8550 / 8551 — CMS and S/MIME

S/MIME is Pepsi’s second end-to-end protocol, and its four standards divide the work cleanly.

RFC 5652 (CMS) is the container syntax. pepsi-crypto::smime builds and opens SignedData (detached and opaque), EnvelopedData, and the certs-only form used to publish a certificate. The cms crate supplies the ASN.1 type definitions only; the builders and openers are Pepsi’s own, so that what is emitted and what is accepted are decided here rather than inherited.

RFC 5083 (``AuthEnvelopedData``) is the authenticated-encryption container, and it is what Pepsi emits by default (AES-256-GCM). The RFC 5652 EnvelopedData with AES-CBC remains as the downgrade path for a recipient that cannot do better — again gated by [pepsi] CRYPTO_ALLOW_DOWNGRADE. Which clients can actually read AuthEnvelopedData is the largest open interoperability question in the tree; see The AuthEnvelopedData question.

RFC 5753 covers the elliptic-curve RecipientInfo: ECDH key agreement over P-256/P-384 with the X9.63 KDF and AES key wrap, alongside the RSA forms (RSAES-OAEP-SHA-256, and PKCS#1 v1.5 for a recipient that needs it).

RFC 8550 (certificate handling) is pepsi-crypto::trust: path building to a configured anchor, validity dates, basicConstraints, keyUsage against the operation being performed, the id-kp-emailProtection extended key usage, and the rfc822Name subject-alternative-name that binds a certificate to the From: address. Revocation is tri-state — “not checked” is never rendered as “not revoked” — and the module opens no sockets: there is no OCSP and no CRL fetching, only CRLs supplied to it.

RFC 8551 (message specification) is the MIME surface: application/pkcs7-mime with the smime-type parameter (signed-data/enveloped-data/authEnveloped-data/certs-only) and application/pkcs7-signature inside multipart/signed, with the conventional smime.p7m/smime.p7s/smime.p7c file names. The legacy application/x-pkcs7-* spellings are accepted on the key-harvesting path only.

Certificates for this deployment’s own users are issued by pepsi-crypto::keygen through the local CA in pepsi-keys. See Key management; Client interoperability records what has been measured against OpenSSL.

71.2.16. RFC 6125 — TLS service identity

When MTA-STS requires authenticated TLS, the recipient MX certificate is checked to validate for the expected host name per RFC 6125. See pepsi-stage-relay-to-internet.

71.2.17. RFC 6152 — 8BITMIME

Ingress advertises 8BITMIME and records the BODY= value under state.origin. Each relay stage re-advertises BODY=8BITMIME to a hop that supports it and otherwise downgrades the body (RFC 2045). See Supported Features.

71.2.18. RFC 6376 / RFC 8463 — DKIM (RSA and Ed25519)

Ingress verifies inbound DKIM signatures; pepsi-stage-dkim-sign signs outbound mail. Each domain has both an RSA-2048 key (RFC 6376) and an Ed25519 key (RFC 8463), provisioned by pepsi-setup; both signatures are added. The l= body-length tag is optional (COVER_BODY). See pepsi-stage-dkim-sign.

71.2.19. RFC 6409 — Message submission

A listener marked SUBMISSION = yes acts as a Message Submission Agent. It requires AUTH as RFC 6409 expects (an unauthenticated MAIL FROM is refused with 530; see RFC 4954 — SMTP AUTH) and applies the submission fixups to every accepted message: a missing Date: is added (§8.2) and a missing Message-ID: is generated (§8.3). Submission-identity enforcement (§6) and the Sender: fixup (§8.1) are driven by the USERNAME_MAP mapping of the authenticated SASL user to its allowed addresses: an envelope MAIL FROM or a From: the user is not permitted to use is refused with 550, and an allowed From: that differs from the user’s canonical identity gets a Sender: header naming that identity. See pepsi-ingress.

71.2.20. RFC 6531 — SMTPUTF8

Ingress advertises SMTPUTF8 and accepts UTF-8 in headers and the envelope. Each relay stage re-advertises it to a supporting hop and otherwise downgrades UTF-8 headers (RFC 2047); a non-ASCII address that cannot be represented to a non-SMTPUTF8 hop is a permanent failure (bounce). See Supported Features.

71.2.21. RFC 7208 — SPF

Ingress verifies SPF on the MAIL FROM identity using the connecting client’s IP (via the mail_auth library) and records the verdict in Authentication-Results and under state.auth.spf.

71.2.22. RFC 7489 — DMARC

Ingress evaluates DMARC and records the verdict. With DMARC_ENFORCE set, a definite DMARC failure under a quarantine/reject policy is rejected at SMTP time (550); otherwise the failing verdict is recorded and the mail is accepted (fail-open, suited to a forwarder).

The organizational domain that relaxed alignment compares against is found by the RFC 9989 (DMARCbis) tree walk, which mail_auth performs internally. Note this changed with mail-auth 0.11: the older interface asked the caller for an organizational-domain function and defaulted it to the identity, so before that upgrade relaxed alignment compared the two domains as given and a subdomain never aligned with its parent.

71.2.23. RFC 7505 — Null MX

pepsi-stage-relay-to-internet classifies a 0 . exchange as a permanent failure (an immediate bounce, never a retry).

71.2.24. RFC 7672 — DANE / TLSA for SMTP

Both relay stages support opportunistic DANE: a DANE = off|warn|strict option (default warn) looks up the next hop’s TLSA records — per-MX for pepsi-stage-relay-to-internet, per-[…-mta-*] for pepsi-stage-relay-to-smarthost — and matches them against the presented certificate chain. The verifier and TLSA types live in pepsi-common::smtp::dane; the AD-bit-aware TLSA/MX lookups in pepsi-common::dns (Pepsi trusts a validating resolver and reads the response AD bit rather than validating DNSSEC itself). DANE takes precedence over MTA-STS and TLS_VERIFY; a usable-record mismatch defers in strict and only warns in warn.

71.2.25. RFC 7929 / RFC 8162 — OPENPGPKEY and SMIMEA key records

Pepsi implements both halves: publishing our own addresses’ key records, and looking a correspondent’s up.

Publishing. pepsi-keys dns <address> prints the DNS records that publish an address’s stored public key material: an OPENPGPKEY record (RFC 7929) carrying an OpenPGP transferable public key, and an SMIMEA record (RFC 8162) carrying an S/MIME certificate in the TLSA (usage, selector, matching-type) shape — 3 0 0 (domain-issued certificate, full certificate, exact match), the form a self-signed or directly pinned certificate takes. Only published, active identities are emitted. pepsi-setup run prints the same records for every published identity alongside the DKIM, SPF and MTA-STS ones.

Looking up. The pepsi-keydisc@dane discovery instance queries the same two record types for a correspondent’s address, OPENPGPKEY first and SMIMEA if the domain publishes no OpenPGP record. It ranks second on the trust ladder — below only material an operator entered by hand — because DNSSEC is the one source with cryptographic provenance.

Both directions use the same hashed owner name — the hex of the first 28 octets of the SHA-256 of the local part, followed by ._openpgpkey. or ._smimecert. — so a zone does not enumerate the addresses it serves. That hash is case-sensitive (RFC 7929 §3), unlike the Web Key Directory hash below.

Both standards presuppose a DNSSEC-signed zone, and Pepsi treats that as binding in both directions. pepsi-keys dns says so in its own output, and a lookup is AD-gated: an answer the resolver did not validate is refused outright rather than accepted at a lower rank, because an unsigned key record is a key from whoever can answer for the zone. Pepsi trusts a validating resolver rather than validating DNSSEC itself, so a deployment without one gets no DANE results at all — pepsi-setup probes for this and reports it. See pepsi-keys, pepsi-keydisc and Key management.

71.2.26. OpenPGP Web Key Directory (draft-koch-openpgp-webkey-service)

The Web Key Directory is the HTTPS half of the same job: a correspondent’s key is fetched from the address’s own domain under a hash of its local part. Pepsi computes that hash in pepsi_common::keystore::wkd_local_part_hash — z-base-32 of the SHA-1 of the lower-cased local part — and stores it on each identity, indexed, so a request is answered with one lookup instead of by hashing every candidate row. (The SHA-1 there is a naming function the specification fixes, not a security one, so it is deliberately not gated by CRYPTO_ALLOW_WEAK_DIGESTS.)

The client side is implemented: pepsi-keydisc@wkd-advanced queries openpgpkey.<domain> and pepsi-keydisc@wkd-direct the domain itself. They are separate ranks and therefore separate concurrent lookups rather than a fallback chain, since running direct only “if advanced fails” would accept the weaker answer whenever the stronger one was merely slow. The fetch is hardened beyond the draft’s own requirements: HTTPS only with certificate validation and no insecure mode, at most one HTTPS-to-HTTPS redirect to the same host, refusal to connect to loopback/private/link-local addresses, a body cap enforced while streaming, a deadline on every step, and IDNA A-label conversion. A returned key whose User ID does not name the queried address is discarded — without that, a domain could answer every request with one key of its choosing — and the policy file’s mailbox-only and dane-only directives are honoured.

The serving side is implemented too, by pepsi-httpd: the direct and advanced forms of both the key and the policy path, answered by an indexed (domain, local-part hash) lookup over identities this deployment holds and has marked published. The response is the binary transferable key with Access-Control-Allow-Origin: *; the policy file is a zero-length 200, which has to exist because GnuPG reads its absence as “no Web Key Directory here”; an unknown hash is an empty-bodied 404. The ?l= parameter is read and ignored — honouring it would turn the endpoint into a lookup by caller-supplied address rather than by a hash the caller had to know.

Two properties of the serving side are deliberate and worth stating. It never serves a cached correspondent key, only our own identities: publishing material we did not verify, under our own domain name, is what a key server does and we are not one. And it applies no rate limiting, because a Web Key Directory is a public oracle by construction — see Key management.

The specification is an Internet-Draft rather than an RFC.

71.2.27. Autocrypt — the Autocrypt: header

Autocrypt is not an RFC but a de-facto standard, and it is how most PGP-using mail clients advertise a key today, which is reason enough to read it. Pepsi harvests the header — together with application/pgp-keys parts and the signer certificates inside an S/MIME SignedData — from mail that has already arrived.

Harvesting is deliberately not a discovery service: it costs no network I/O because the material is already in front of it, so it runs inline rather than as a pepsi-keydisc instance, and inbound is rejected in [pepsi-keydiscovery] SOURCES. It does write through the same path, so a harvested key also releases any message parked waiting on that address.

A harvested key sits at the bottom of the trust ladder — trust on first use — and the server-side conflict rule stops it displacing anything better attested. It is nevertheless usable by default, because the alternative to encrypting to a TOFU key is sending cleartext. See Key management.

Pepsi writes the header as well. Unless [stage-encrypt] AUTOCRYPT is turned off, pepsi-stage-encrypt advertises the From: author’s own OpenPGP key on every locally submitted message — including plain cleartext mail, which is the case that matters, since a correspondent has to learn the key before there is anything to encrypt with. What is advertised is the minimal five-packet transferable public key of Level 1 §2.1.1, only for an identity that still holds its private material, and never on a message that already carries an Autocrypt: field from the sender’s own client. Because the stage runs immediately before DKIM signing, the header is covered by our own signature.

prefer-encrypt=mutual is claimed only when the effective ENCRYPT policy is required. Level 1 §2.4 has a correspondent’s client encrypt by default only when both ends say mutual, so claiming it under an opportunistic policy — one whose ON_NO_KEY = cleartext says unencrypted mail is acceptable — would announce a preference the deployment does not enforce.

Level 1 §5.3 key gossip — the mechanism by which one message advertises the keys of the other recipients, so that two correspondents who have never written to each other can nevertheless answer encrypted — is implemented too, under [stage-encrypt] AUTOCRYPT_GOSSIP. It is off by default: unlike the Autocrypt: header, which publishes a key its owner asked this deployment to hold, gossip redistributes third parties’ cached key material to correspondents who did not ask for it, and that is an operator’s decision to take deliberately.

Two properties are worth stating, because both are what makes the feature safe to turn on. The fields ride inside the ciphertext and only there — an outer one would publish the recipient set of an encrypted message to every relay on the path — so there is no gossip on cleartext, on signed-only mail, or in an S/MIME container, which Autocrypt does not define. And the addresses gossiped are read from the message’s To: and Cc: fields alone: the envelope recipient list, which carries the Bcc recipients, is consulted only to remove an address from the set. A blind recipient can therefore never appear in any copy, which is exactly the rule Level 1 §5.3 also imposes on a receiver.

The receiving half is implemented as well, in pepsi-stage-autocrypt-learn under LEARN_GOSSIP (default on) — a stage of its own precisely so that it can run after the spam checks, which §5.3 also asks for and which pepsi-stage-decrypt, first on the inbound path by design, could never have honoured. The interesting part of it is not the parser. §5.3 requires a gossiped key to be kept in a peer state separate from one learnt from an Autocrypt: header, so that a third party’s introduction can never displace what an address’s owner said about themselves; Pepsi realises that as a rung of its own at the bottom of the discovery trust ladder (gossip, rank 8, below harvested), which the database’s conflict rule already knows how to enforce. A field counts only when it really was inside the ciphertext — an outer one could have been written by anything on the path — only when its addr is in the message’s own To:/Cc:, never for the sender’s own address, and never for an address this host serves. It never carries prefer-encrypt, and a signature checked against a gossiped key comes back valid-untrusted, so an introduction opens no gate.

71.2.28. VKS — the verifying key server protocol

keys.openpgp.org and its work-alikes speak a small HTTP protocol under /vks/v1, and it is deliberately not HKP: a key is only served for an address once the address holder has answered a confirmation mail, which is what makes the answer worth more than “somebody uploaded this”.

Pepsi speaks both halves. pepsi-keydisc@vks looks a correspondent up by address, discarding a key whose User ID does not name the address queried and skipping a revoked one; it ranks below DANE, both Web Key Directory methods and LDAP, because the confirmation proves control of the mailbox and nothing more. pepsi-keys uploads our own identities and requests verification — off by default ([pepsi-keys] VKS_PUBLISH), because publishing a user’s address to a third party is an operator’s decision and, unlike the Web Key Directory, it cannot be undone. The server’s confirmation mail then has to be answered, which is the whole job of pepsi-stage-vks-confirm — a stage that follows a link only after six independent checks, including that the envelope sender’s host is exactly the configured key server and that every link in the body points there too.

71.2.29. RFC 8446 — TLS 1.3

Every TLS-protected connection in Pepsi — inbound STARTTLS and implicit-TLS listeners, the outbound relay client, LMTP, the HTTP server and the LDAP discovery client — runs over rustls, which speaks TLS 1.3 and 1.2 and nothing older. There is no configuration knob to re-enable SSLv3 or TLS 1.0/1.1, because rustls does not implement them.

What varies between those connections is not the protocol but what authentication is required of the peer, and that is where the mail-specific standards take over: RFC 6125 for identity matching, RFC 7672 for DANE, RFC 8461 for MTA-STS, and the TLS_VERIFY option for the case where an operator knowingly relaxes it. Opportunistic STARTTLS to an arbitrary MX authenticates nothing by design — that is RFC 3207’s model, not a weakness here — which is precisely why DANE and MTA-STS exist and why the outcome of every attempt is recorded for RFC 8460 reporting.

71.2.30. RFC 8314 — Implicit TLS

A listener with MODE = tls performs the TLS handshake before the SMTP greeting (implicit TLS, e.g. the submissions port 465), as recommended by RFC 8314.

Following RFC 8314 §4.3, ingress also records the negotiated TLS version and cipher in the Received: trace header it prepends — as a (version=… cipher=…) comment after the ESMTPS keyword — since the bare ESMTPS transmission type does not convey which parameters were used.

71.2.31. RFC 8460 — SMTP TLS Reporting (TLSRPT)

When [pepsi-tlsrpt] SEND_REPORTS is on, the relay stages record the outcome of each outbound TLS session in the pepsi.tls_session aggregate-counter table. pepsi-tlsrpt(1), run daily from cron, groups a day’s rows into one RFC 8460 JSON report per policy domain, gzips it, looks up the domain’s _smtp._tls rua and ships it by mailto: (injected back into the pipeline so it is signed and relayed) or HTTPS POST. The advertising half is pepsi-setup printing our own _smtp._tls TXT record from [pepsi-tlsrpt] RUA. The shared types, failure classifier and report builders live in pepsi-common::tlsrpt. See pepsi-tlsrpt.

71.2.32. RFC 8461 — MTA-STS

pepsi-stage-relay-to-internet discovers and enforces recipient-domain MTA-STS policies: an enforce policy restricts delivery to the listed MX hosts over authenticated STARTTLS. pepsi-setup publishes our own _mta-sts TXT record and prints the policy file. See pepsi-setup.

71.2.33. RFC 8601 — Authentication-Results

Ingress prepends a standalone Authentication-Results header carrying the SPF, DKIM, DMARC and iprev (FCrDNS) verdicts, with the ingress hostname as the authserv-id. The ARC stage reproduces the same assessment in its AAR.

71.2.34. RFC 8617 — ARC

pepsi-stage-arc verifies any inbound ARC chain and seals the message as our ADMD by prepending an AAR/AMS/AS set, signed with the single ARC_ALGORITHM. This lets the final receiver trust the boundary verdict even after Pepsi’s forwarding breaks SPF/DKIM alignment. The ARC-Message-Signature’s RFC 6376 parameters — canonicalization (c=), covered headers (h=), the l= body-length tag and an x= expiration — are configurable on the stage (as they are on pepsi-stage-dkim-sign).

71.2.35. RFC 9051 / RFC 4155 — reading a mailbox (IMAP and mbox)

Pepsi is not a mail store and serves neither protocol. It reads mailboxes in one place only: pepsi-helper-mailbox-scan, which seeds a whitelist from the mail a user has already sent (see pepsi-whitelist).

The IMAP client is read-only in the strict sense — it issues EXAMINE rather than SELECT and fetches BODY.PEEK[HEADER], so no message is marked \Seen and no mailbox state changes. Only header blocks are read; every reader stops at the blank line, so message bodies never enter the process. The same helper reads local mbox (RFC 4155) and Maildir, and can consume a doveadm -f json stream.

LMTP (RFC 2033) is the delivery counterpart and has no fetch verb at all, which is why a mailbox on an LMTP-only MDA cannot be scanned; IMAP is the network option.

71.2.36. RFC 9106 — Argon2

Argon2id appears twice, for two different threats.

In the secure-link portal (The secure-link fallback portal) it derives the key that encrypts a stored message from the recipient’s PIN plus a per-message salt and a server-side pepper held outside the database. The cost parameters are chosen so that a PIN short enough to read over the telephone is still expensive to grind, and the pepper is what makes a stolen database insufficient on its own — which is why disclosing it is treated as seriously as disclosing the messages.

In the administrative API it hashes account passwords. That instance is also why the portal’s rate limiter matters: at 19 MiB per derivation, an unauthenticated attacker who could retry freely would consume memory as fast as they consume guesses.

71.3. Applicable RFCs not yet implemented

These standards are in scope for a forwarder or a crypto gateway and are tracked on the roadmap (docs/ROADMAP.md) but are not implemented today. Several are partial in a way worth stating precisely: a status object exists and is reported, which is easy to mistake for the check having been performed.

RFC

Title

Status in Pepsi

RFC 3030

BINARYMIME body value

CHUNKING/BDAT is supported, but BODY=BINARYMIME is not advertised or accepted.

RFC 6960

Online Certificate Status Protocol (OCSP)

Not implemented, and this is the one most likely to be misread. pepsi-crypto::trust carries a Revocation status on every validated path, but it is only ever NotChecked — no OCSP responder is queried and no CRL (RFC 5280 §5) is fetched. A revoked S/MIME certificate therefore still validates. The three-valued status exists so a report can say “we did not check” rather than imply “not revoked”; do not read it as a check having happened.

RFC 2634

Enhanced Security Services for S/MIME (triple wrapping)

Not implemented, by decision (plan 01 D6). Pepsi signs then encrypts, or encrypts then signs, but never sign-encrypt-sign. Signed receipts and security labels are likewise absent.

RFC 3161

Time-Stamp Protocol (TSP)

Not implemented. The S/MIME signingTime attribute is the signer’s own claim; it is clamped to the present so it cannot be postdated, but a backdated claim is indistinguishable from a genuinely old message. A deployment needing “signed when it says it was” needs a timestamp token, which Pepsi neither produces nor requires.

RFC 6541

DKIM Authorized Third-Party Signatures (ATPS)

Not implemented. The atps field is parsed off a DKIM record by the vendored mail-auth and carried in the verdict, but no ATPS lookup is performed and no policy consults it.

RFC 6651

Extensions to DKIM for failure reporting

Not implemented. The r= tag is parsed; no failure report is ever generated or sent.

RFC 5321

ETRN / on-demand queue starting

Not implemented and not planned. Pepsi’s queue is a database table drained by the dispatcher; there is no per-domain queue to release.

Autocrypt Level 1

Gossip peer-state promotion (§5.3)

Both halves of gossip are implemented, but one nuance of the peer-state model is not: Level 1 lets a client promote a gossiped key when the address’s owner later confirms it, and Pepsi has no such transition. A better-sourced answer replaces the gossiped row outright (which is the safe direction), and until one arrives the key stays on the gossip rung however many messages introduce it. Nothing is lost that a real Autocrypt: header would not fix in one message.