Remediation Guides

SPF Record Missing: How to Create, Publish and Verify a Correct SPF Record

26 September 2026 8 min read

An “SPF record missing” finding means the scanner queried your domain’s DNS and found no TXT record beginning with v=spf1, so receiving mail servers cannot tell which hosts may send mail for it. Fix it by publishing one TXT record that lists every legitimate sender and ends in -all or ~all. Parked domains publish v=spf1 -all.

What the scanner is actually detecting

Sender Policy Framework (SPF, RFC 7208) is a DNS TXT record that names the IP addresses allowed to use your domain in the SMTP envelope sender (MAIL FROM). This finding usually arrives under one of these titles:

Scanner Finding title What triggers it
SecurityScorecard SPF Record Missing No SPF record found for a domain attributed to your organization
Nuclei (spf-record-detect) SPF Record – Detection An info-level presence check: it queries TXT for the target FQDN and matches the word v=spf1. A “missing” result is the absence of a match.
Nuclei (spoofable-spf-records-ptr) Spoofable SPF Records with PTR Mechanism The TXT answer contains both v=spf1 and the literal string ” ptr ” (with spaces)
Nessus (plugin 31658) DNS Sender Policy Framework (SPF) Enabled Informational; reports that SPF is present, not that it is missing

Two details matter. The Nuclei template checks the exact name you scanned, so a target of www.example.com tests www, not the apex. And the Nessus plugin is a positive signal: if a report builds “SPF missing” from its absence, check whether the DNS query simply failed.

Real-world risk

With no SPF record, receivers evaluating mail that claims your domain in MAIL FROM get the SPF result none (RFC 7208, section 4.5). They then fall back on DKIM, DMARC and reputation. Nothing on your servers is exposed; the risk is impersonation and deliverability:

  • Spoofed envelope senders using your domain cannot be rejected on SPF grounds.
  • DMARC needs an aligned SPF or DKIM pass. Without SPF, DMARC depends entirely on DKIM, which some of your senders may not sign with.
  • Your legitimate mail loses an authentication signal and is more likely to be filtered as spam.

SPF alone does not protect the visible From header that users read; that is DMARC’s job. Treat this as a low-effort, worthwhile hygiene fix rather than an emergency.

For the ptr variant, RFC 7208 section 5.5 states the mechanism “SHOULD NOT be published” because it is slow, less reliable during DNS errors and loads the .arpa servers. It authorizes any IP whose forward-confirmed reverse DNS name falls inside your domain, including subdomains, which is often wider than the set of mail servers you meant to approve.

How to confirm it

On Linux or macOS, query the name the scanner reported:

# All TXT records at the apex
dig +short TXT example.com

# Only SPF records (more than one line here is a separate error)
dig +short TXT example.com | grep -i 'v=spf1'

# Ask the authoritative servers directly, bypassing caches
dig +short NS example.com
dig @ns1.example-dns.net TXT example.com +norecurse

On Windows:

Resolve-DnsName -Name example.com -Type TXT -DnsOnly |
  Where-Object { ($_.Strings -join '') -like 'v=spf1*' } |
  ForEach-Object { $_.Strings -join '' }

nslookup -type=txt example.com

If an SPF record exists, look for ptr or ptr:domain in it, count the SPF records (there must be exactly one), and check that it is a TXT record. RFC 7208 section 3.1 says SPF must be published as TXT only; the old SPF record type (99) is not used.

How to fix it

Step 1: inventory every sender

List everything that sends mail with your domain in the envelope sender: Microsoft 365 or Google Workspace, on-premises Exchange or Postfix relays, ticketing and CRM platforms, invoicing and marketing services, web servers sending form mail, and multifunction printers that relay directly. A DMARC reporting service helps find the ones nobody remembers. Microsoft recommends putting third-party bulk senders on a subdomain with its own record.

Step 2: choose the record

Scenario TXT value at the domain
Microsoft 365 only (commercial and GCC) v=spf1 include:spf.protection.outlook.com -all
Microsoft 365 GCC High or DoD v=spf1 include:spf.protection.office365.us -all
Google Workspace only v=spf1 include:_spf.google.com ~all (Google’s documented value)
On-premises server plus Microsoft 365 v=spf1 ip4:203.0.113.10 include:spf.protection.outlook.com -all
Domain never sends mail v=spf1 -all

Qualifiers: -all is fail, ~all is softfail, ?all is neutral. Microsoft recommends -all when DKIM and DMARC are also deployed; Google documents ~all. A common path is ~all while you confirm the sender list, then -all. Never publish +all, which authorizes everyone.

Step 3: publish it

BIND zone file (increment the SOA serial first):

@   3600  IN  TXT  "v=spf1 ip4:203.0.113.10 include:spf.protection.outlook.com -all"

; a record longer than 255 characters is split into strings that are
; joined WITHOUT spaces, so keep the space inside a string
@   3600  IN  TXT  ( "v=spf1 ip4:203.0.113.10 ip4:198.51.100.0/24 "
                     "include:spf.protection.outlook.com -all" )
named-checkzone example.com /path/to/db.example.com
rndc reload example.com

Windows DNS Server (run against the zone that answers the Internet, not only an internal split-horizon copy):

Get-DnsServerResourceRecord -ZoneName "example.com" -Name "@" -RRType Txt

Add-DnsServerResourceRecord -ZoneName "example.com" -Name "@" -Txt `
  -DescriptiveText "v=spf1 ip4:203.0.113.10 include:spf.protection.outlook.com -all" `
  -TimeToLive 01:00:00

Hosted DNS (registrar, Cloudflare, Route 53 and similar): add a TXT record with host @ or blank, depending on the provider. Microsoft 365 has no portal or cmdlet for SPF; it is always set at your DNS host. Microsoft suggests a TTL of at least 3600 seconds.

Step 4: fix structural problems

  • Replace ptr. Identify the servers it was authorizing (your outbound relays) and list them explicitly with ip4: or ip6:, or use a or mx if those names really are your senders.
  • One record per name. If a vendor told you to “add an SPF record”, merge its include: into your existing record. Two records produce permerror.
  • Stay under 10 DNS lookups. include, a, mx, exists and redirect each count, nested includes count too, while ip4, ip6 and all do not. Exceeding the limit is also permerror.
  • Cover subdomains that send. SPF is not inherited; mail.example.com or marketing.example.com need their own records. For parked domains, Microsoft suggests a wildcard TXT v=spf1 -all at *.example.net if your DNS host supports it (a wildcard only answers for names with no records of their own).
  • Remove stale includes. An include: for a vendor you dropped keeps authorizing whoever controls that domain later, a risk covered in our guide to auditing a sprawling domain portfolio.

How to verify the fix and rescan

  1. Query the authoritative servers first, then a public resolver. Resolvers may cache the earlier “no record” answer for the zone’s negative TTL (from the SOA), so an older view can linger briefly.
  2. Confirm exactly one line comes back from dig +short TXT example.com | grep -i ‘v=spf1’ and that it contains no ptr.
  3. Send a test message from each sender to an external mailbox and read the Authentication-Results header. You want spf=pass.
  4. Rerun the scanner. For Nuclei: nuclei -u example.com -id spf-record-detect,spoofable-spf-records-ptr. The first should now match and the second should not. If Nessus scans the domain, plugin 31658 should now appear. External rating platforms refresh on their own schedule.

What can break and how to roll back

  • A forgotten sender fails SPF. With -all, its mail may be rejected or junked. Add the sender, or relax to ~all while you investigate.
  • permerror from duplicates or too many lookups. Receivers may treat this as a failure, which can be worse than having no record.
  • Forwarded mail. A forwarding server’s IP is not in your record, so forwarded messages can fail SPF. DKIM signatures survive forwarding, which is one reason Microsoft pairs SPF with DKIM and DMARC.

Record the old value before any change. Rolling back means restoring the previous value, not deleting the record, since deletion returns you to none. On Windows DNS:

Remove-DnsServerResourceRecord -ZoneName "example.com" -RRType Txt -Name "@" `
  -RecordData "v=spf1 ip4:203.0.113.10 include:spf.protection.outlook.com -all" -Force

Then add the previous value back with Add-DnsServerResourceRecord. On BIND, restore the zone file, increment the serial and run rndc reload. Old answers persist in caches for up to the record’s TTL.

Common false positive reasons

  • Wrong name scanned. The scan targeted a web hostname rather than the mail domain. The finding is technically true for that name; publishing v=spf1 -all there is cheap if it never sends mail.
  • Split-horizon DNS. An internal scanner resolved an internal zone that lacks the record the public zone has.
  • Query failure. A timeout or SERVFAIL looks the same as “no match” to a presence check.
  • Template matching limits. The ptr template matches the literal ” ptr ” with spaces on both sides, so it misses ptr:example.com and a trailing ptr. The match runs on the TXT answer, so text in another TXT record can contribute. Read the actual record before acting.
  • Not your domain. A rating platform attributed a domain you do not own or no longer use. Dispute the attribution with the vendor.

While you are in the zone, check for records pointing at deprovisioned resources, described in our guide to dangling DNS and subdomain takeover.

FAQ

Does a domain that never sends email need an SPF record?

Yes. Publish v=spf1 -all so receivers know no host is authorized. Microsoft documents exactly this for parked domains.

Should I use -all or ~all?

Microsoft recommends -all alongside DKIM and DMARC; Google documents ~all. Start with ~all if your sender inventory is uncertain, then tighten.

Can I add a second SPF record for a new vendor?

No. Multiple SPF records at one name cause permerror. Merge the vendor’s include: into the existing record, or give the vendor a subdomain.

Why is the ptr mechanism deprecated?

RFC 7208 says it should not be published: it is slow, unreliable when DNS errors occur and burdens reverse DNS servers. Use explicit ip4, ip6 or include entries instead.

Tracking this finding across many domains

SPF findings tend to reappear across dozens of domains and subdomains, often reported by more than one tool. SITEY, a self-hosted vulnerability management platform, imports findings from 16 scanners (Nessus results come in by uploading an exported .nessus file) and merges duplicates per scanner, not across scanners, so the same domain flagged by two tools remains two items to close.

Sources

SITEY closes the loop, not just the report.Discover, validate, fix and verify in your own infrastructure.

See pricing