Standards and RFC coverage
SithBit changes email’s economics — sender-paid postage settled on-chain and addresses you control — while changing as little as possible about the wire. Existing mail clients already speak SMTP, IMAP, and POP3, and SithBit’s servers implement those protocols against their published specifications. The goal is to add postage without requiring people to abandon Thunderbird, Outlook, Apple Mail, or the mobile client they already use. Keep the client; change who pays.
Standards-completeness matters more for email than for almost any other protocol. Email’s interoperability is adversarial — a message crosses servers written by strangers, in languages you’ll never see, and a single misread reply code or dropped capability turns into a silently lost message or an open relay. So the reference servers don’t implement “enough of” each protocol to pass a smoke test; they implement the published grammar, advertise exactly the capabilities they honor, and reject out-of-sequence commands structurally rather than hoping clients behave. Where a specification is only partially implemented, this page says so plainly in the Notes column — no overclaiming.
The tables below enumerate every RFC each SithBit
server and subsystem implements, grouped by the component that owns it. Each
entry links to the canonical text at the RFC Editor. If you are
weighing a from-scratch server or an existing MTA
against simply running sithbitd, this is the coverage
you’d be matching — and if you are building a product on the protocol rather
than a server, it defines the interoperability target your product can rely on.
SMTP — sending and relaying mail
The SMTP surface is the sans-io smtp_session state machine (the wire
grammar and its extensions) driven by the smtp_server binary (STARTTLS,
SASL, delivery, and the SithBit sender-authentication policies). Enhanced
status codes are structural: the class digit is derived from the reply code so
a mismatch is unrepresentable.
| RFC | Title / feature | Notes |
|---|---|---|
| RFC 5321 | Simple Mail Transfer Protocol | Core command sequencing and reply codes; null sender and postmaster envelope forms. |
| RFC 3463 / RFC 2034 | Enhanced mail system status codes | ENHANCEDSTATUSCODES; class digit derived from the reply code. Every emitted code is listed in the RFC 5248 IANA registry. |
| RFC 4954 | SMTP authentication (AUTH) | Submission mode requires AUTH over TLS. |
| RFC 3207 | Secure SMTP over TLS (STARTTLS) | Pre-TLS buffer discard per §4.2/§6. |
| RFC 6152 | 8-bit MIME transport | 8BITMIME. |
| RFC 3030 | Chunking and binary MIME | CHUNKING/BDAT, BINARYMIME. |
| RFC 1870 | Message size declaration | SIZE. |
| RFC 2920 | Command pipelining | PIPELINING; inherent to the sans-io design. |
| RFC 3461 | Delivery status notification parameters | DSN: RET/ENVID/NOTIFY/ORCPT carried on the envelope. |
| RFC 3464 | Delivery status notification report format | Failure DSNs generated by the relay on exhausting the retry schedule. |
| RFC 6522 | The multipart/report media type | Container for both DSN and ARF reports. |
| RFC 7505 | Null MX (no-service resource record) | A null MX is the domain’s standing “no mail, ever”: the relay refuses such recipients outright instead of dialing. |
| RFC 7504 | 521/556 “server does not accept mail” reply codes | Null-MX refusals bounce with 556 and enhanced status 5.1.10 (§2.2); the client send machine classifies both codes as permanent. Never emitted by the server session — a SithBit node that accepts no mail simply runs no listener. |
| RFC 3848 | ESMTP transmission types | with keywords in the Received: trace header. |
| RFC 8601 | Authentication-Results header | Records SPF/DKIM/DMARC verdicts on accepted mail. |
| RFC 7208 | Sender Policy Framework (SPF) | Inbound-relay sender authentication (via the adopted mail-auth). A published hardfail rejects at MAIL FROM with 554 and enhanced status 5.7.23, the code RFC 7372 §3.2 registers for exactly this outcome; anything short of Fail lands in Authentication-Results instead. |
| RFC 6376 | DomainKeys Identified Mail (DKIM) | Verified inbound; signed once on outbound spool entry. The RFC 8301 algorithm floor holds on both sides: signing is rsa-sha256 only by construction, and a verified rsa-sha1 signature is downgraded to failure before it reaches reporting or DMARC input. RFC 8463 ed25519-sha256 signatures verify, and outbound entries can opt into dual-signing. See the conformance appendix for the full posture. |
| RFC 9989 | Domain-based Message Authentication (DMARC) | Full evaluation and disposition: alignment folded by the §4.10 DNS tree walk, p=reject/p=quarantine, the subdomain policies sp=/np=, and test mode t=y. Enforcement is all-or-nothing — 9989 retires the pct= sampling tag, and a published pct= is inert. The §5.3.1 From-extraction termination cases (zero or multiple differing author domains) produce no verdict — see the conformance appendix. Obsoletes RFC 7489. Selectable via sender_auth = "dmarc". |
| RFC 9990 | DMARC aggregate reporting | §3.1 aggregate (rua) reports — gzip XML in the urn:ietf:params:xml:ns:dmarc-2.0 namespace, one per policy domain per interval, with the §4 external-destination check enforced on every target. Ingesting other operators’ reports is an optional operator feature; both dmarc-1.0 and dmarc-2.0 report bodies are accepted. |
| RFC 9991 | DMARC failure reporting | §2 failure/forensic (ruf) reports — one per DMARC failure, headers-only by default per the §7.1 exposure guidance, with the §5 external-destination check enforced on every target. |
| RFC 5965 | Abuse Reporting Format (ARF) | message/feedback-report body of each forensic report. |
| RFC 6591 | Authentication-failure reporting via ARF | The auth-failure report emitted per DMARC failure. Sent only where solicited, per the RFC 6650 applicability statement: ruf= targets are addresses the policy domain itself published, and out-of-domain targets must additionally pass the external-destination check. |
| RFC 6692 | Source ports in ARF reports | Source-Port in each forensic report — the SMTP peer’s TCP source port, captured at accept and emitted alongside Source-IP; an unknown port omits the field rather than reporting 0. |
| RFC 7435 | Opportunistic security | Best-effort TLS posture for MX-to-MX relay. |
IMAP — reading and managing mail
The IMAP surface is the sans-io imap_session semantics core over the typed
imap-types AST, driven by imap_server over the imap-next flow layer. The
baseline is IMAP4rev1; the rev2 extensions SithBit implements are advertised
individually rather than by claiming rev2 as a whole.
| RFC | Title / feature | Notes |
|---|---|---|
| RFC 3501 | IMAP4rev1 | States, mailbox semantics, and the full command set. |
| RFC 2177 | IDLE | Push notification of mailbox changes. |
| RFC 6851 | MOVE | Atomic message move. |
| RFC 3691 | UNSELECT | Close a mailbox without expunging. |
| RFC 5161 | ENABLE | Capability negotiation. |
| RFC 2342 | NAMESPACE | A single fixed personal namespace. |
| RFC 4315 | UIDPLUS | UID EXPUNGE, APPENDUID/COPYUID response codes. |
| RFC 7888 | Non-synchronizing literals (LITERAL-) | Framing lives in the imap-next driver; the capability is advertised here. |
| RFC 7889 | APPENDLIMIT | APPENDLIMIT=<n> in §2’s form (a): one ceiling for every mailbox, carried in the capability name itself, advertised both before and after authentication. The value is the enforced one — imap.max_message_size (25 MiB by default), the same setting the driver caps literals with. Partial: the per-mailbox form and its STATUS (APPENDLIMIT) item are not implemented, and §4’s [TOOBIG] response code is met only in prose, and only on one of the two literal forms: an oversize synchronizing literal draws a tagged BAD whose text names TOOBIG and the ceiling it exceeded, but unbracketed — human-readable, not the machine-readable resp-text-code §4 asks for — while an oversize non-synchronizing (LITERAL-) literal draws no TOOBIG, no ceiling and no tagged response at all. Both are limits of the adopted imap-next flow layer — see the conformance appendix. |
| RFC 5530 | IMAP response codes | Extended NO/BAD response codes for precise failure signalling. |
| RFC 4959 | SASL initial client response | One-round-trip AUTHENTICATE; SASL-IR is advertised wherever the AUTH= mechanisms are. |
| RFC 6154 | SPECIAL-USE mailbox attributes | Tier 1: a name heuristic marks the well-known top-level names — Sent, Trash, Drafts, Junk (also Spam), Archive — with their \Sent-style attributes in LIST responses, case-insensitively. The LIST (SPECIAL-USE) selection filter and CREATE-SPECIAL-USE are not supported. |
| RFC 7162 | CONDSTORE / QRESYNC | CONDSTORE implemented; QRESYNC queued as its own follow-up wave (its SELECT parameters and VANISHED are refused). Mod-sequences are tracked per message on every store backend: ENABLE CONDSTORE, SELECT/EXAMINE (CONDSTORE), STATUS (HIGHESTMODSEQ), SEARCH MODSEQ, the MODSEQ fetch item and CHANGEDSINCE modifier, and STORE UNCHANGEDSINCE with the MODIFIED response code. The §3.1.4.1 follow-up untagged FETCH after a non-PEEK fetch’s implicit \Seen persist is sent too — see the conformance appendix for the echo’s shape and the one known wire deviation. |
| RFC 2595 / RFC 8314 | TLS for IMAP | LOGINDISABLED until the connection is protected; implicit TLS is the primary deployment. |
| RFC 9208 | QUOTA | GETQUOTA/GETQUOTAROOT over one per-wallet quota root (the conventional ""), advertised as QUOTA QUOTA=RES-STORAGE. The root exists exactly while max_wallet_bytes sets a cap — an unbounded account (the default) reports no roots. SETQUOTA parses but is always refused, and QUOTASET is never advertised: quota limits are operator configuration. Deliberate deviation: STORAGE usage is the enforced, per-blob-deduplicated stored-bytes meter — the very number [OVERQUOTA] refusals are measured against — not the per-copy message-size sum a client computes from its own folder listings; units are 1024-octet blocks, usage rounded up and the limit rounded down. See the conformance appendix for the reconciliation caveat. |
| RFC 9051 | IMAP4rev2 | Not advertised. rev1 is the baseline; the rev2 extensions above are advertised individually. Of the extensions rev2 folds into its base (Appendix E), NAMESPACE, UNSELECT, UIDPLUS, ENABLE, IDLE, SASL-IR, MOVE, LITERAL-, the RFC 5530 response codes and the SPECIAL-USE attribute list are implemented; ESEARCH, SEARCHRES, LIST-EXTENDED, LIST-STATUS, the FETCH side of BINARY, STATUS SIZE/STATUS DELETED, 64-bit sizes and the CLOSED response code are deferred behind the parser fork. CONDSTORE/QRESYNC (RFC 7162, above) are not part of rev2 — it borrows only their CLOSED response code — so they are extensions on top of either baseline. Rev2 keeps STARTTLS and LOGINDISABLED mandatory (§6.1.1); implicit TLS is the RFC 8314 recommendation, not a rev2 requirement. |
POP3 — simple mailbox download
The POP3 surface is the sans-io pop3_proto typestate machine driven by
pop_server. Commands invalid for the current session state are
unrepresentable rather than merely rejected at runtime.
| RFC | Title / feature | Notes |
|---|---|---|
| RFC 1939 | Post Office Protocol version 3 | The AUTHORIZATION → TRANSACTION → UPDATE state machine, plus APOP (§7). |
| RFC 1957 | Observations on POP3 implementations (updates RFC 1939) | Its one server-side recommendation — real clients depend on the optional UIDL command, so provide it — is implemented in both forms: the whole-maildrop listing and the per-message query, advertised via the UIDL capability. |
| RFC 2449 | POP3 extension mechanism | CAPA, capability limits, extended response codes. |
| RFC 2595 | TLS for POP3 | STLS with pre-TLS buffer discard. |
| RFC 5034 | POP3 SASL authentication | The AUTH command. |
| RFC 3206 | POP3 SYS/AUTH response codes | AUTH-RESP-CODE. |
| RFC 6856 | POP3 support for UTF-8 | UTF8, and LANG in both AUTHORIZATION and TRANSACTION states. |
Authentication (SASL)
SASL mechanisms are shared by all three protocol servers through
server_common. Wallet-signature SASL PLAIN is verified against the connecting
address with no stored secret; CRAM-MD5/APOP serve clients limited to
challenge-response.
| RFC | Title / feature | Notes |
|---|---|---|
| RFC 4422 | SASL framework | Mechanism-neutral hooks shared across SMTP/IMAP/POP. |
| RFC 4616 | SASL PLAIN | The primary wallet-signature mechanism. |
| RFC 2195 | CRAM-MD5 | Challenge/response for clients without PLAIN-over-TLS. |
| RFC 4422 §5.1 | SASL EXTERNAL | Identity proven at the TLS layer by a client certificate. |
The LOGIN mechanism (widely deployed, never standardized as an RFC) is also supported for legacy clients. DIGEST-MD5 and NTLM are deliberately dropped.
Message format and abuse-report handling
Message parsing and generation are adopted rather than hand-rolled — every
consumer names one set of versions through mail_message, which itself owns
only the RFC 5321 envelope layer (source routes, the null reverse-path, the
domainless postmaster recipient) that the format crates don’t model.
| RFC | Title / feature | Notes |
|---|---|---|
| RFC 5322 | Internet Message Format | Header and message parsing/generation. Group syntax in From:/Sender: parses per RFC 6854; every generated message carries a singleton mailbox. |
| RFC 2045–2049 | MIME (parts 1–5) | Structure, media types, encodings. |
| RFC 2047 | MIME encoded-words | Non-ASCII header field values. |
| RFC 2231 | MIME parameter value extensions | Continuations and charset/language in parameters. |
| RFC 6531 | Internationalized email addresses (SMTPUTF8) | Validated in addr-spec parsing (email_address). |
Anti-abuse and transport hardening
Connection-level abuse policy, plus the TLS posture shared by all three
servers (through the server_common acceptors) and the outbound relay.
| RFC | Title / feature | Notes |
|---|---|---|
| RFC 5782 | DNS blocklists (DNSBL) | Address-reversal query conventions for the connection blocklist. |
| RFC 7817 | Updated TLS server-identity check for email protocols | On the stack’s one email TLS client — the outbound relay under strict verification — the verified name is the connected MX host or smarthost, never the recipient domain, matched against DNS-ID subjectAltNames with no CN fallback. |
| RFC 8996 | TLS 1.0 and 1.1 deprecated | Neither version can be negotiated anywhere: every acceptor and connector rides rustls, which has never shipped TLS ≤ 1.1. |
| RFC 8997 | TLS 1.2 as the minimum version for email | The ≥ 1.2 floor is asserted rather than inherited: test fences hold it at the shared acceptors and the outbound connector, and the spooler’s HTTPS report fetchers pin the same rustls backend in code. |
Beyond these wire standards, the on-chain layer is where SithBit’s own
contribution lives: the MailInstruction ABI, PDA derivations, and sealed-box
encryption described in the Program & PDA reference
and How sealed-box encryption works. Any server
that speaks the RFCs above and those on-chain conventions is a first-class
participant — see
Protocol conformance for custom mail servers.