A parked domain sends no mail and can still be spoofed
A domain that sends no mail still needs SPF and DMARC, and it needs them more than the domains you send from. Nothing in DNS tells a receiving mail server that a domain is parked. The receiver sees a From: address, looks up two records, finds neither, and has no instruction to refuse.
A forger who wants a clean identity picks that kind of domain on purpose, because there’s no policy in the way and no owner reading a mailbox. Two records close it, and since a parked domain has no legitimate mail to protect, you can publish both at their strictest values on day one without a monitoring phase.
A receiver can’t tell the domain is parked
An MX record covers inbound only: where mail addressed to a domain should be delivered. Who may send as that domain is a separate question. A server handling a message with From: [email protected] doesn’t check whether parked.example has an MX. It looks up an SPF record at the apex and a DMARC record at _dmarc.parked.example, and when both come back empty it falls through to reputation and content scoring, which is the layer forged mail is written to pass.
Of the 316,600,902 graded and dead domains in the September 2026 census, 143,318,595 (45.3%) publish no MX record. 238,156,049 (75.2%) publish no DMARC record. Domains with no mail service and no policy sit in both groups, and that overlap is where a forger goes shopping, since a domain with no mailbox has no one noticing the replies.
A message forged from one of those domains arrives at the receiver with this in its Authentication-Results: header:
spf=none smtp.mailfrom=parked.example; dkim=none; dmarc=none header.from=parked.example
Three results of none means no evidence either way, and a receiver with no evidence either way delivers.
Record one: an SPF record that permits no sender
Publish a single TXT record at the apex of the domain:
parked.example 3600 IN TXT "v=spf1 -all"
It carries no mechanisms at all, so nothing like include: or ip4: sits in front of the -all. The record says that no host anywhere is permitted to send with this domain in the envelope. When a forger tries, the receiver evaluates it and writes:
Received-SPF: fail (parked.example does not designate 203.0.113.7 as permitted sender) client-ip=203.0.113.7;
Without the record that line reads Received-SPF: none, which is no verdict at all, and the message carries on to the next filter. A softer v=spf1 ~all produces softfail, which a receiver is free to treat as a mild negative and deliver anyway, and v=spf1 +all authorises the forger in writing. The difference between the four qualifiers is on the -all page.
SPF only checks the envelope sender, the address in MAIL FROM, and a forger can put any domain there, but the From: header the person reads still says yours. -all stops the lazy forgery. The careful one uses a throwaway envelope domain that passes SPF and walks straight past this record, and only DMARC catches that.
Record two: DMARC at reject on day one
_dmarc.parked.example 3600 IN TXT "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:[email protected]"
p=reject instructs the receiver to refuse any message whose From: domain is yours and which fails to authenticate in alignment with it. DMARC evaluates the From: header, the one the person sees, so the throwaway envelope trick stops working here. On a parked domain no message can authenticate, because no sender is authorised and no signature exists, so the policy applies to all of it. The receiver’s answer during the SMTP conversation looks like this:
550 5.7.509 Access denied, sending domain parked.example does not pass DMARC verification and has a DMARC policy of reject
adkim=s and aspf=s set strict alignment. On a live domain relaxed alignment earns its keep by letting mail.example.com count for example.com; on a parked domain there’s no subdomain that should count for anything, so strict costs you nothing and removes an edge case. sp=reject applies the same refusal to any subdomain, whether or not it exists.
Without this record an SPF fail is all the receiver has, and with no policy telling it what to do the decision is its own. At p=none the header reads dmarc=fail (p=NONE sp=NONE dis=NONE), which means the receiver saw the failure, delivered the message, and will tell you about it tomorrow. At p=quarantine the forgery goes to a junk folder instead, where the recipient can still open it.
The standard rollout for a live domain starts at p=none, reads a month of reports, and steps up. That ramp exists so you don’t bounce your own invoices, and a parked domain has no invoices. Any message claiming to come from it is forged by definition, so the ramp protects nothing and leaves the domain open for a month.
Confirm the domain is as idle as the client thinks before you publish: a contact form, a printer, an old ticketing tool or a marketing platform from a previous supplier can still be sending with that address, and the client’s account list is where those turn up. Once you’re sure, go straight to reject, and let the first week of reports be the audit.
The scan reads the SPF, DMARC and MX records live and tells you which of the verdicts above a receiver would reach for the domain today. Run it on the domain you’re least sure about.
Don’t copy the record from a live domain
A live SPF record carries include: mechanisms for whichever platform sends the client’s mail, and an include authorises that platform’s entire sending pool, which you don’t control and which is shared with strangers. Paste that onto a parked domain and you’ve handed a forger a permitted sender. On a parked domain the only correct SPF content is -all with nothing in front of it.
A live DMARC record has its own hazards. It may carry pct=10 from a rollout nobody finished, which leaves nine forgeries in ten at the next policy down. It may carry sp=none, put there because a client’s marketing subdomain wasn’t ready. On a parked domain sp=none means a forger sends as invoices.parked.example, the receiver finds no record at that name, walks up to yours, and reads a subdomain policy of none, whether or not the subdomain exists.
Leave sp=reject in the record above, or leave sp= out so the subdomains inherit p=reject. The reasons a live domain might want the two to differ are on the subdomain policy page, and none of them apply to a domain that sends no mail.
A null MX stops the bounces piling up on the parking host
The third record is optional and cheap:
parked.example 3600 IN MX 0 .
A single MX with priority 0 and a target of the root, ., is the null MX from RFC 7505. It tells any sending server that the domain accepts no mail, and the sender fails the message on the spot with 556 5.1.10 Recipient address has null MX rather than queueing it.
Without it, a sending server that finds no MX record at all falls back to the domain’s A record and tries port 25 there, which on a parked domain is the registrar’s parking web server. Bounces for forged mail carrying your domain in the envelope, and replies from people who fell for it, queue against a host that isn’t listening, and the sending servers retry for days before giving up. None of that reaches you, and some of it counts against the domain’s reputation.
A receiver may also check for a null MX on the way in, refusing with 550 5.7.27 Sender address has null MX when the MAIL FROM domain publishes one, which catches the lazy forgery a second time. It does nothing about the From: header, though, so a null MX on its own is no substitute for the DMARC record. It must be the only MX on the name, and the SPF record must not carry an mx mechanism, which would point at the null MX.
Send the reports somewhere one person reads
Two hundred parked domains means two hundred rua= tags, and every one of them should point at the same address on a domain you operate. Pointing it at a mailbox on the parked domain itself puts the report address behind your own null MX, and the reports bounce.
Reports only cross domains with permission. When rua= for parked.example names an address at msp.example, a receiver looks up parked.example._report._dmarc.msp.example before sending anything, and if no TXT record answers it drops the report without telling anyone. You can publish that record per client, or once as a wildcard:
*._report._dmarc.msp.example 3600 IN TXT "v=DMARC1"
Without that record the reports go nowhere, and the silence reads as though nobody is forging the domains. What does arrive, when it works, is a daily XML file per receiver with one row per sending address:
<source_ip>203.0.113.7</source_ip>
<count>31</count>
<disposition>reject</disposition>
Each of those rows is a forgery that was refused. A row with a disposition of none is a domain where the record hasn’t propagated or was mistyped, and either way it’s the next thing to fix.
Two hundred domains before the end of the afternoon
Start with the list and sort it before you touch DNS. For each domain, pull what’s there now:
dig +short MX parked.example
dig +short TXT parked.example
dig +short TXT _dmarc.parked.example
A domain with an MX pointing at a mail provider, or an SPF record with an include:, isn’t parked whatever the client says, and it goes on the live list, where you handle it with a ramp, as described on the DMARC page. A domain that answers with nothing on all three is the parked cohort, and each of those gets the three records above.
Push them through the DNS provider’s API or bulk import with a 3600 TTL, wait an hour, and run the same three lookups again. The output you want is 0 ., "v=spf1 -all" and a record starting "v=DMARC1; p=reject. A week after that, open the report mailbox and read the disposition column. Each reject is a forged message that a receiver turned away because you told it to.
Figures as of 5 September 2026, from the September 2026 edition of the defaults.exposed census. Census numbers move every month; the current values are on the census data page.