How to lock down a domain that neither sends nor receives mail
A null MX, an empty SPF and DMARC at reject — on the apex and on a wildcard, because apex records do not cover subdomains. Plus the DKIM record most guides tell you to add and M3AAWG says not to.
Yowl reads what your domain publishes today and tells you which records to replace, in what order,
and never edits your DNS itself. We did exactly this to yowl.io on 24 September 2026, the day the
domain was bought — you can check it yourself as you read.
Nobody ever audits a parked domain, which is the actual problem
The records below take ten minutes. The reason parked domains stay forgeable anyway is that nobody looks at them again. There is no inbox to notice, no user to complain, no bounce to investigate — a parked domain is precisely the thing with no feedback loop, and the note at the bottom of this page is the reason that matters: registrar email-forwarding and one-click parking panels insert MX records without asking. Your lockdown lasts until somebody clicks something in a dashboard you forgot you had.
So the useful version of this job is not “publish three records”. It is “know, at any moment, which of
my domains are still locked down” — across the brand-protection registrations, the misspellings you
bought defensively, the .email variant and the one from the rebrand three years ago.
Yowl measures the live answer per domain, per record, with the published value beside the expected one — and it distinguishes missing from present but different from could not check, which matters more here than anywhere: a parked domain whose nameservers have quietly stopped answering looks identical to one with no records, and the advice for the two is opposite.
Ask it rather than remembering it
Connect Claude to Yowl over MCP and the audit becomes a question:
“Go through every domain we own and tell me which ones can still be forged.”
That reads the live records for each, compares them against what a locked-down domain should publish, and names the ones that have drifted. Run it when you remember; run it monthly; have your agent run it without being asked. The trail is kept too, so “when did this change?” has an answer rather than a shrug.
The same surface registers the domain in the first place, which is where this ideally happens — buy the name and have the three records published before it has ever resolved to anything, rather than some months later when you read a guide like this one. A domain that has never been forgeable is better than one you rescued.
Why an empty domain needs records at all
Every domain you own can be written into a From line by anyone. SMTP carries no authenticated
identity until SPF or DKIM supplies one, so until your DNS says otherwise a receiver has nothing to
check the claim against. Parked domains, brand-protection registrations and the .email you bought
last week and never pointed anywhere are the usual holes.
The three records
1. A null MX (RFC 7505) — one MX, priority 0, pointing at a bare dot:
@ MX 0 .
This matters more than it looks. Under RFC 5321 §5 a sender that gets an empty MX list falls back to
the A record and treats it as an implicit MX at preference 0 — so mail to a domain whose only record is
a website goes to that web server on port 25, and retries for about a week. A null MX makes that an
immediate permanent failure, generated by the sender’s own MTA without ever connecting to you; anything
that connects anyway gets 556 / 5.1.10. There is a registered code for the sending side too —
550 / 5.7.27 — so this is not purely an inbound control.
2. An SPF record that authorises nobody:
@ TXT "v=spf1 -all"
Nothing may send with this domain as the envelope sender. Note this is the one context where -all
is straightforwardly correct — on a domain that does send,
~all is the better default.
3. DMARC at reject:
_dmarc TXT "v=DMARC1; p=reject; sp=reject; np=reject"
p covers the domain itself, sp covers subdomains that exist, and np — new in
RFC 9989 — covers subdomains that don’t. np inherits from
sp when omitted, so on this record it changes nothing a correct receiver does; it is worth writing
because it states the intent and survives a later edit that drops sp.
⚠ Our own record still carries adkim=s; aspf=s, and on a parked domain that is cargo cult. Alignment
is only consulted after SPF or DKIM passes, and here nothing can pass. Harmless, but it does not
close a lookalike gap the way we originally claimed.
Apex records do not cover subdomains
This is the gap most lockdown guides leave open. SPF is not hierarchical: v=spf1 -all on the apex
says nothing about www or about a name a forger invents. And any hostname with an A record and no MX
is an implicit MX by the rule above — so www.example.io is a mail destination whether you meant it
to be or not.
M3AAWG’s own guidance is to use wildcards for exactly this:
* MX 0 .
* TXT "v=spf1 -all"
A DNS wildcard is only consulted where no other record sits at an intermediate level of the queried
name, so this covers the ordinary cases and not every conceivable one. DMARC’s tree walk is what
actually reaches invented names, which is why np earns its place above.
The DKIM record you should not publish
A great deal of parked-domain advice, and an earlier version of this page, recommends a wildcard
revoked key — *._domainkey TXT "v=DKIM1; p=" — and attributes it to M3AAWG.
M3AAWG says the opposite. From
Protecting Parked Domains
(update 2022-06): “There is no need to publish any DKIM record for a parked domain and in fact none
should be published.” The reasoning is that an absent public key already fails every signature, so
the record buys nothing an empty zone does not already give you. Empty p= is real revocation syntax
— it is the right tool for retiring a selector on a domain that used to sign. It is not a
parked-domain control, and we do not publish it on yowl.io.
One thing a null MX takes away
RFC 2142 expects postmaster@ and abuse@ to work. On a domain that accepts no mail they cannot. So
M3AAWG’s guidance is to put contact details in the zone’s SOA record instead, which is the only
remaining way for someone to reach the domain’s owner about it.
Check it
dig +short MX example.io # 0 .
dig +short MX www.example.io # 0 . ← the one people miss
dig +short TXT example.io # "v=spf1 -all"
dig +short TXT _dmarc.example.io # p=reject; sp=reject; np=reject
Then mail anything@example.io from a personal account. The bounce is generated by your provider,
not by us, and usually arrives in under a minute — though some paths queue first.
Reports are optional and mostly theoretical here — a parked domain is forged rarely enough that you
may wait months for one, and an off-domain rua needs an authorisation record on the receiving domain
first. If you run many parked domains, publish one DMARC policy and point the rest at it by CNAME.
Undoing it, when the domain starts sending
⛔ Not MX first. A null MX governs receiving; sending needs none of it touched.
- Publish the provider’s DKIM key before the first message goes out (why).
- Replace
v=spf1 -allwith the provider’s include — and on a sending domain, end it~all. - Send. Read the headers, confirm an aligned pass.
- Only then swap the MX records, and only if you intend to receive.
- Keep
p=rejectif the first messages align. If not,p=nonewith aruafor a week, then climb back (the traps on the way).
⚠ The lockdown is only as durable as whatever last wrote the zone. Registrar email-forwarding and one-click parking panels insert MX records without asking.