oximail setupprovisions the full record set. With--cloudflare-tokenit writes the records straight into the zone through the Cloudflare API (idempotent — an existing record is left in place). Without a token it tells you to create the records by hand.oximail check-dnsperforms live lookups and scores the domain. It queries through Cloudflare (1.1.1.1/1.0.0.1) with DNSSEC validation on, deliberately bypassing stale local caches and split-horizon resolvers that mislead during setup. The report ends withn/n -- Ready for productionorn/n -- Fix the items above.
Run
oximail check-dns from the server after every DNS change. DNSSEC is enforced on the TXT lookups, so a zone with broken DNSSEC surfaces as a hard error rather than silently accepting forged records.The record set
For a mail domainexample.com served by the host mail.example.com at IP 203.0.113.10, the full set OxiMail provisions is:
The sections below explain the records that carry real policy. The MX, A, and SRV records are mechanical — publish them and verify with
check-dns.
SPF
OxiMail publishes a strict, single-source SPF record:ip4:203.0.113.10 authorizes exactly your mail host; -all is a hard fail — any other IP claiming to send as example.com is rejected outright. This is the right default for a single self-hosted server.
Adjust it by hand if your topology is wider:
- Send from more than one IP (a backup MX host, a separate relay): add each
ip4:/ip6:mechanism, e.g.v=spf1 ip4:203.0.113.10 ip4:203.0.113.20 -all. - Relay through a third party (a transactional provider): add their published
include:, e.g.include:_spf.example-relay.com. - IPv6 senders: SPF only authorizes what it lists. If your MX also sends over IPv6, add the matching
ip6:mechanism, otherwise IPv6 mail hard-fails SPF at the receiver.
DKIM
DKIM signs each outgoing message with a private key; receivers fetch the public key from DNS and verify the signature. OxiMail signs at delivery time in the outbound worker (see the SMTP layer). Generate the key and read back the record to publish:/etc/oximail/dkim/example.com.default.key and prints the matching DNS record:
- Selector is
default. The DNS name is always<selector>._domainkey.<domain>, so a rotation publishes a new selector alongside the old one, lets both verify during the cutover, then retires the old record. - Algorithm defaults to RSA (
k=rsa). The full setup wizard publishes the RSA record automatically when run with a Cloudflare token. - Oversigning. The signature’s
h=list namesFrom,To, andSubjectone extra time, so a downstream actor cannot inject a second copy of a display-critical header without invalidating the signature (RFC 6376 §8.15). No operator action needed; it is how OxiMail signs.
dkim=fail says why. The verification reason now travels alongside the verdict, into the Authentication-Results header and into the result stored per message — so a post-mortem can separate cases a bare verdict conflated, and which call for opposite actions:
The reason recorded is that of the first non-passing signature. A
pass carries none, deliberately: a bad signature sitting next to a good one is normal — mailing lists re-sign — and dkim=pass reason=… would read as a defect where there is none.
DMARC
DMARC tells receivers what to do when a message fails both SPF and DKIM alignment, and where to send aggregate reports. OxiMail’s default is:p=quarantine routes failing mail to the recipient’s Junk folder. Tune the policy to your rollout stage:
p=none— monitor only. Publish this first if you are unsure your SPF and DKIM are correct; read theruaaggregate reports, then tighten.p=quarantine— the OxiMail default. Failing mail is junked, not refused.p=reject— failing mail is refused at SMTP time. On the receiving side, OxiMail honours a sender’sp=rejectwith a550 5.7.26rejection (see the SMTP layer).
rua mailbox exists and is monitored — it is where you find out a legitimate source is failing before recipients stop seeing your mail.
MTA-STS and TLS-RPT
MTA-STS (RFC 8461) lets you require that other servers use validated TLS when they deliver to you, closing the downgrade-to-cleartext window that plain opportunistic STARTTLS leaves open. It has three moving parts, and OxiMail serves the policy itself:- The TXT record
_mta-sts.example.com=v=STSv1; id=<YYYYMMDD>announces that a policy exists. Theidchanges whenever the policy changes. - The policy host
mta-sts.example.com(a CNAME to your mail host) is where senders fetch the policy over HTTPS. - The server serves
/.well-known/mta-sts.txtfrom the[mta_sts]configuration block:
enforce— senders that honour MTA-STS refuse to deliver to you over unvalidated TLS.testing— policy is published but failures are reported, not enforced. Use this while validating, then switch toenforce.none— withdraw the policy.
rua address, which is how you detect a misconfigured policy or an active downgrade attempt. As with DMARC, monitor that mailbox.
DANE (TLSA)
DANE (RFC 7672) is the DNSSEC-anchored alternative to MTA-STS: aTLSA record under _25._tcp.mail.example.com pins your certificate so a sender validates TLS against DNS rather than a public CA list. It requires a DNSSEC-signed zone.
OxiMail enforces DANE on the outbound path by default and keeps your inbound TLSA records fresh automatically after each certificate renewal. Because a renewed certificate changes the pinned value, this requires a configured DNS provider:
cloudflare— auto-publishes the new TLSA records via the Cloudflare API after each ACME renewal. Recommended.manual— you update TLSA records out of band. The renewal logs a warning reminding you to do it.rfc2136— a v1 stub that currently behaves likemanual(logs the same warning); the dynamic-update implementation is deferred.
Reverse DNS (PTR) and deliverability
Reverse DNS is published by whoever controls the IP block (your hosting provider — Hetzner, OVH, AWS, …), not in your domain’s zone. It is one of the strongest reputation signals a receiver has.- Set the PTR for
203.0.113.10tomail.example.com— the same name your server uses in its SMTPHELO/EHLO. Many large receivers reject or heavily penalize a mismatch (no FCrDNS). check-dnspasses the PTR check when the record resolves to the mail domain or a subdomain of it; for best results make it resolve exactly to your mail host and confirm the forwardArecord points back to the same IP.- New IPs have no sending reputation. Warm up gradually and keep volume steady; a sudden spike from a cold IP looks like a compromised host.
Autodiscovery
Mail clients find your endpoints from the SRV records and theautoconfig / autodiscover CNAMEs in the table above. The full oximail setup run also publishes a CAA record restricting certificate issuance to Let’s Encrypt, which both hardens the domain and matches OxiMail’s ACME setup. None of these carry tunable policy — publish them and let check-dns confirm.
Verifying with oximail check-dns
- PTR mismatch — fix the reverse record at your hosting provider, not in your zone.
- DKIM “no record” — you generated the key but did not publish the TXT record. See the DKIM section above.
- SPF “does not include IP” — your sending IP is not listed; add the
ip4:/ip6:mechanism. - Lookup failed — a propagation delay (wait and re-run) or a broken DNSSEC zone (the lookup fails hard rather than trusting an unvalidated answer).
Standards
- RFC 7208 — Sender Policy Framework (SPF).
- RFC 6376 — DomainKeys Identified Mail (DKIM).
- RFC 7489 — Domain-based Message Authentication, Reporting, and Conformance (DMARC).
- RFC 8461 — SMTP MTA Strict Transport Security (MTA-STS).
- RFC 8460 — SMTP TLS Reporting (TLS-RPT).
- RFC 7672 — SMTP Security via Opportunistic DANE TLS.