~ / blog / systems-administration / email-deliverability-checklist
email dns deliverability Mail Mail Checker 2026-08-04ยท5 min read

Email deliverability checklist

I added a Mail Check tool to this site. It takes a domain and reports what a receiving mail server sees before it decides whether to trust your mail. I ran it against my own domain and got a red line immediately, so here is what each check means and how to actually fix it.

Do them in this order: reverse DNS, then SPF, then DKIM, then DMARC. DMARC is the one that tells receivers to reject mail, and it only makes sense once SPF and DKIM are already correct. If you publish a strict DMARC policy first, the mail you block will be your own.

Reverse DNS (PTR)

Every IP address that sends your mail needs a PTR record, and that name has to resolve back to the same address. This is called forward confirmed reverse DNS. A lot of receivers reject mail from an address with no PTR at all, before they even look at your content.

bash
dig -x 203.0.113.10 +short
# mail.example.com.

# now check it points back
dig mail.example.com +short
# 203.0.113.10

If those two do not agree, fix the PTR record. You set it at your hosting provider or whoever owns the IP block, not in your own DNS zone. That is the part people miss.

SPF

SPF is a TXT record on your domain listing who is allowed to send for it. Publish exactly one, more than one is a permanent error and disables SPF completely.

plaintext
example.com.  TXT  "v=spf1 include:spf.messagingengine.com -all"

Two things to get right here. The ending, and the lookup count.

The ending is -all or ~all. -all means reject anything not listed, ~all means accept it but mark it. Start with ~all while you are still finding out which services send as your domain, then move to -all once the list is complete. Never publish +all, that authorises the whole internet to send as you and is worse than having no SPF at all.

The 10 lookup limit

SPF allows only 10 DNS querying mechanisms, and every include: counts, including the ones nested inside other includes. Go over it and receivers return permerror, which means your SPF stops working entirely. Add a few SaaS providers and you hit this faster than you expect. The Mail Check tool counts the whole chain for you.

If you are close to the limit, drop includes for services you no longer use, or replace an include with the ip4: ranges behind it. Avoid the ptr mechanism, it is deprecated and slow.

DKIM

DKIM signs your messages with a private key, and publishes the public key in DNS under a selector. Your mail provider gives you both the selector and the record, you just publish it.

bash
# a selector called "fm1" looks like this
dig fm1._domainkey.example.com TXT +short

Use a 2048 bit key if your provider offers it. Anything under 1024 bits gets rejected by most receivers now.

Why a checker cannot always find your DKIM

There is no way to list the selectors on a domain, DNS does not support that. Any tool, mine included, can only guess common selector names. If your check says no DKIM key found but you know you have one, it most likely uses a selector nobody guesses. That is fine, receivers read the selector from the message header.

DMARC

This is the one my own domain was missing. DMARC ties SPF and DKIM together and tells receivers what to do when a message fails both, and where to send reports. Without it, receivers are left guessing, and you never find out that someone is sending mail as you.

Start in monitoring mode. It changes nothing about delivery and just starts the reports flowing:

plaintext
_dmarc.example.com.  TXT  "v=DMARC1; p=none; rua=mailto:[email protected]"

Leave that for a few weeks and read the aggregate reports. They are XML, so use one of the free report viewers rather than reading them by hand. You are looking for legitimate sources that fail, usually some forgotten newsletter or ticket system nobody told you about.

Once the reports are clean, tighten it:

plaintext
_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; rua=mailto:[email protected]"

# and later
_dmarc.example.com.  TXT  "v=DMARC1; p=reject; rua=mailto:[email protected]"

p=none does nothing on its own

A record with p=none protects nobody. It is a useful first step because it gives you reports, but if you leave it there forever then anyone can still send mail as your domain and receivers will accept it. The point is to move to quarantine and then reject.

Two tags worth knowing. pct= applies the policy to only part of your failing mail, which is handy while rolling out but easy to forget about. And sp= sets the policy for subdomains, if you leave it at none then anything.example.com is still wide open.

MTA-STS and TLS-RPT

Mail servers use opportunistic TLS, which means an attacker on the path can strip the encryption and the message goes through in plaintext anyway. MTA-STS is how you say that TLS is required. It needs a TXT record and a policy file served over HTTPS.

plaintext
_mta-sts.example.com.  TXT  "v=STSv1; id=20260804000000"

# and at https://mta-sts.example.com/.well-known/mta-sts.txt
version: STSv1
mode: enforce
mx: mail.example.com
max_age: 604800

Publish it with mode: testing first, check the reports, then switch to enforce. TLS-RPT is the companion record that gets you those reports:

plaintext
_smtp._tls.example.com.  TXT  "v=TLSRPTv1; rua=mailto:[email protected]"

Blocklists

If your sending IP is on a blocklist, everything above will not help you. Check it, and if you are listed, use the delisting form on that list rather than waiting it out. Find out what caused it first, usually a compromised account or an open relay, because delisting without fixing the cause gets you relisted in a day.

Be careful reading blocklist results

Some lists, Spamhaus in particular, refuse queries that come from public DNS resolvers and answer with a special code instead. A checker that reads that code as a listing will tell you that a perfectly clean server is blacklisted. If a tool reports you as listed, confirm it on the blocklist operator own lookup page before you panic.

Also worth doing

Sign your zone with DNSSEC if your registrar supports it, otherwise all of these records can be spoofed on the way to the receiver. Keep a second MX so mail queues somewhere instead of bouncing while your main host is down. And make sure the TLS certificate on your MX actually covers the MX hostname, a mismatch still delivers today but breaks for anyone enforcing MTA-STS.

You can run all of this against your own domain with the Mail Check tool here. It caches results for five minutes, so if you just changed a record give it a moment before you check again.