Compliant email
Standards and compliance
cmail implements the open standards that make email interoperable and the controls an organisation is expected to evidence. Every row marked Implemented was checked against the source you are running. Where something is not done, it is listed in the gap register at the end rather than left unsaid.
Standards, receiver policy and legal duty are three different things. Passing SPF, DKIM and DMARC does not prove a message was solicited or lawful. This page is operational documentation, not legal advice.
Interoperability
Message format
Mail leaves and arrives in the shapes every other mail system expects, so threads stay intact on the far side.
- Internet Message Format RFC 5322 Implemented
Message-IDs are validated as an addr-spec inside angle brackets. Message-ID, In-Reply-To and References are held within the 998-octet line limit, and a References chain that would overflow keeps its root plus the newest ancestors so threading survives.
- MIME RFC 2045–2049 Implemented
Every outbound message carries a text/plain alternative alongside the HTML part, with attachments as separate MIME parts.
- Encoded header parameters RFC 5987 Implemented
Attachment downloads send a UTF-8 filename* parameter with an ASCII fallback, so non-Latin filenames survive the round trip.
Authentication
Proving who sent the message
Outbound authentication is published by you at the DNS layer and applied by the sending transport. Inbound results are handled conservatively — see the gap register.
- SPF RFC 7208 Operator-configured
You publish exactly one SPF record at each evaluated domain. The deployment guide covers the record set and the checks.
- DKIM RFC 6376 + RFC 8301 Delegated to transport
Cloudflare generates, manages and rotates the signing keys and signs on send. RFC 8301 requires RSA-SHA256, forbids RSA-SHA1, and sets a 1024-bit floor with 2048-bit recommended.
- DMARC RFC 9989, 9990, 9991 Operator-configured
DMARCbis became the Standards Track specification in May 2026, obsoleting RFC 7489. It drops the pct, rf and ri tags, adds np, psd and t, and replaces the Public Suffix List with a DNS tree-walk for organisational-domain discovery. Existing v=DMARC1 records stay valid.
- Authentication-Results handling RFC 8601 Operator-configured
Inbound SPF, DKIM and DMARC verdicts are recorded only from a boundary you name in INBOUND_AUTHSERV_ID, and only from the topmost record carrying that identifier. Results are validated against the RFC 8601 registry, commas inside comments and quoted strings cannot split a record, and a forged header from any other authserv-id is discarded. Leave the setting unset and nothing is recorded — which is the safe default, because an unattributed "dkim=pass" is sender-controlled.
- Authenticated Received Chain RFC 8617 Not implemented
The boundary's own arc= verdict is parsed but not stored, and cmail performs no chain validation of its own. Mail relayed through a forwarder or mailing list cannot have a broken SPF or DKIM result reassessed here.
Transport
Protecting the connection
SMTP transport security is published in your DNS. Web transport is enforced by the application on every response.
- MTA-STS RFC 8461 Operator-configured
Requires authenticated TLS delivery to your declared MX hosts. The guide directs you to begin in testing mode and move to enforce only once every MX and certificate path is verified — a wrong enforce policy can stop legitimate inbound mail.
- SMTP TLS Reporting RFC 8460 Operator-configured
Aggregate reports on TLS negotiation and policy failures. Treat the reports as operationally sensitive and approve their destination, access and retention.
- Web transport hardening Implemented
HSTS, a hash-based Content-Security-Policy that permits no inline or third-party script and refuses remote fonts, X-Frame-Options, Cross-Origin-Opener-Policy, Cross-Origin-Resource-Policy, Referrer-Policy, Permissions-Policy, no-store on authenticated responses, and X-Robots-Tag.
Untrusted content
Handling mail as hostile input
Inbound HTML is never trusted at any stage.
- Allowlist sanitisation Implemented
Message HTML is parsed and rewritten against an allowlist. Scripts, embedded objects and event handlers are removed, and inline styles are restricted to a fixed property set with url(), expression(), @import, -moz-binding and behavior rejected. Both parser input and retained output are byte-bounded.
- Sandboxed rendering Implemented
The sanitised body renders inside a sandboxed frame carrying its own restrictive Content-Security-Policy, so even malformed mail reaches neither the application nor your session.
- Executable attachment blocking Implemented
A shared blocked-extension list is applied on both inbound delivery and outbound send, so the boundary cannot be crossed in either direction.
Access
Identity and session control
There is no password to steal, and access is enforced on the server for every request.
- OAuth 2.0 / OpenID Connect Implemented
Sign-in delegates to Google or Microsoft Entra ID. No password is set, stored or transmitted, so your existing multi-factor and conditional-access rules continue to apply.
- Session integrity Implemented
Session tokens are HMAC-SHA256 signed and stored only as a hash. Lifetime and concurrent sessions per person are configurable, and pausing or offboarding revokes every session immediately.
- Least-privilege delegation Implemented
Mailbox access is granted per person, per mailbox, as Read, Send as or Full access, and is checked server-side on every request rather than in the interface.
Governance
Evidence and retention
The records an auditor asks for are produced as a by-product of ordinary operation.
- Append-only audit log Implemented
Every administrative action and authentication event is recorded with actor, event type, target, source address and timestamp. The interface offers no way to edit or delete an entry.
- Message trace Implemented
Delivery metadata is recorded for every message in and out — envelope addresses, size, status and the relay response. Message content is never written to the trace.
- Configurable retention Implemented
Deleted messages, attachments, trace records and audit records each carry their own retention period, enforced on a schedule rather than by hand.
- Versioned acceptable use policy Implemented
Each published version is retained, and each acceptance is recorded against the person, version, timestamp and source address. Publishing a new version requires everyone to accept again.
- NIST SP 800-177 Rev. 1 Operator-configured
Trustworthy Email recommends exactly this combination — SPF, DKIM and DMARC published by the domain owner, with TLS for transport. It is guidance for administrators, not a certification scheme, and the DNS-layer work belongs to you.
Gap register
What is not done, and why
Each entry states the reason, the practical effect, and what would close it.
Inbound authentication results need INBOUND_AUTHSERV_ID before anything is recorded
- Why
- An Authentication-Results header is only meaningful if it can be attributed to an MTA you trust — any sender can write "dkim=pass". RFC 8601 §5 requires a consumer to ignore records whose authserv-id is not its own. The parser therefore refuses to produce a verdict until the boundary is named.
- Effect
- Until the setting is applied, the SPF, DKIM, DMARC and source-address columns in Investigate and Mail trace stay empty. Your DMARC policy is still enforced upstream by the receiving MX; it simply is not attributed per message here.
- Closed by
- Setting INBOUND_AUTHSERV_ID on the email Worker to the authserv-id your boundary stamps. Results then appear against every subsequent message.
No Authenticated Received Chain (RFC 8617)
- Why
- ARC lets a receiver trust an earlier authentication result after a forwarder or mailing list has broken SPF or DKIM alignment. The boundary's arc= verdict is parsed, but cmail seals and validates no chain of its own.
- Effect
- Legitimate mail relayed through a forwarder may fail authentication downstream with no chain to appeal to.
- Closed by
- Implementing ARC sealing and chain validation, which needs its own key management and cryptographic verification.
No one-click unsubscribe (RFC 8058)
- Why
- This is deliberate. cmail is organisational mail, not bulk-marketing tooling, and it lacks consent evidence, suppression precedence, feedback-loop processing and campaign rate control.
- Effect
- It must not be used for campaigns or subscription mail, and its recipient and hourly limits must not be raised to work around that boundary.
- Closed by
- A separate bulk feature with its own threat model, abuse controls, provider review and legal review.
DKIM2 is not implemented
- Why
- DKIM2 is still an IETF draft. It binds a message to its intended recipient and records send time to defeat DKIM replay, and closes the forwarding-breakage and DSN-routing gaps.
- Effect
- None today — no mailbox provider requires it yet. First deployments at major providers are projected for the end of 2026.
- Closed by
- Adoption once the specification is published and the sending transport supports it.
No independent certification
- Why
- No audit has been carried out against ISO 27001, SOC 2 or an equivalent scheme.
- Effect
- Everything on this page is an implementation fact you can verify in the source. None of it is an attestation by a third party.
- Closed by
- An audit commissioned by the organisation operating this deployment.
WCAG 2.2 AA is a target, not an audited result
- Why
- The interface is keyboard-operable with visible focus, honours reduced-motion and Windows High Contrast, and never uses colour as the only signal.
- Effect
- No formal conformance audit has been completed, so no conformance claim is made.
- Closed by
- An accessibility audit against WCAG 2.2 AA.