How do I set up an SPF record for my domain?
Publish a single DNS TXT record starting with v=spf1 that lists every server sending mail for the domain, then end the record with -all. Use include: for cloud providers and ip4: for static IPs, keeping the total DNS lookups at 10 or under to avoid a permerror.
Start with ~all while monitoring DMARC aggregate reports to catch missed senders, then tighten to -all once confident. SPF checks the envelope sender, not the visible From: header, so combine it with DKIM and DMARC to stop spoofing effectively.
Mail lands in junk or triggers spoofing alerts because the domain lacks a published Sender Policy Framework (SPF) record, or the existing record is broken. An SPF record is a single DNS TXT entry that lists which servers are permitted to send email on behalf of the domain. Receiving mail servers check this record to decide whether to accept or reject incoming messages. Without it, or with a misconfigured one, legitimate mail gets flagged as suspicious, and attackers can easily spoof the domain in the visible From: header.
The fix is one DNS record, but the order matters: published carelessly, an SPF record stops legitimate mail rather than forged mail. Find every system that sends as the domain first, publish a record that fails softly, and tighten it once the reports show nothing legitimate breaking.
What does an SPF record actually check?
Mail fails or lands in junk because the receiving server cannot verify the sender. SPF checks the envelope sender address, the address used in the SMTP MAIL FROM command, also known as the Return-Path. It does not check the From: header that the recipient sees in their email client. An attacker can pass SPF for their own throwaway domain in the envelope while putting your company domain in the visible From: field, and the recipient sees only the forged one. What ties the envelope back to the visible From: is DMARC alignment, which is why SPF is a component of anti-spoofing rather than the whole of it.
To check what is currently published, run a DNS lookup for the domain.
dig +short TXT example.com
Or on Windows PowerShell:
Resolve-DnsName -Type TXT example.com
Look for a single TXT record starting with v=spf1. The record ends with an all mechanism. Everything between is a list of permitted senders. A minimal example for a domain sending only through Microsoft 365 is:
v=spf1 include:spf.protection.outlook.com -all
If the output shows no SPF record, or multiple records, the check will fail.
What goes in the record?
The record lists mechanisms that define which servers may send mail. These mechanisms either cost DNS lookups or do not. Mechanisms that count against the 10-lookup limit are include:<domain>, a, a:<domain>, mx, mx:<domain>, exists:<domain>, ptr, and redirect=<domain>. The include mechanism is the most common cause of hitting the limit. It trusts whatever the specified domain's SPF record permits.
Mechanisms that cost no DNS lookup are ip4:<address or CIDR>, ip6:<address or CIDR>, and all. Using ip4 is efficient if the vendor publishes stable addresses.
Common provider includes are:
- Microsoft 365:
include:spf.protection.outlook.com - Google Workspace:
include:_spf.google.com - Mailgun:
include:mailgun.org - SendGrid:
include:sendgrid.net
Verify these against the vendor's current documentation before pasting. Vendor records change, and the vendor's own documentation is the authority.
A worked example for a company on Microsoft 365, sending invoices from an on-premises server at 203.0.113.10, and newsletters through SendGrid:
v=spf1 ip4:203.0.113.10 include:spf.protection.outlook.com include:sendgrid.net -all
This record has two DNS-costing mechanisms at the top level. The ip4 entry costs nothing.
Why does the 10 lookup limit break mail months later?
RFC 7208 caps SPF evaluation at 10 DNS-querying mechanisms. Crossing this limit results in a permerror, which means the SPF check does not pass. The record does not degrade gracefully; it stops working entirely. This often happens months after adding a new marketing tool or CRM that adds another include:. Nested includes count toward the limit. include:spf.protection.outlook.com is one lookup from your record, but whatever that record resolves also counts.
To fix an over-limit record, remove senders that no longer send. Old marketing platforms, unused CRMs, or replaced ticketing systems are the usual suspects. Move a sender onto a subdomain with its own SPF record. Bulk and transactional mail does not have to come from the apex. news.example.com with its own record costs the apex record nothing. Replace an include: with explicit ip4: entries only when the vendor publishes stable addresses and commits to them. Wholesale SPF flattening is a trap because flattened addresses go stale silently when the vendor renumbers.
Check the record for the number of lookup-costing mechanisms.
dig +short TXT example.com
Count the include, a, mx, and redirect entries, including those nested in the included domains. The total must be 10 or under.
Should the record end in -all or ~all?
Every mechanism can take a qualifier. The default is + (pass). - is a hard fail, ~ is a softfail, and ? is neutral. The ending mechanism sets the policy for any sender not listed above. -all means anything not listed fails. ~all means anything not listed is suspicious but not rejected. ?all means SPF expresses no opinion, which is close to having no record. +all allows anybody in the world to send as the domain.
Publish with ~all first. Watch DMARC aggregate reports for a few weeks until confident every legitimate sender is listed. Then tighten to -all.
Check the current ending.
dig +short TXT example.com | grep spf1
Ensure it ends in -all or ~all. If it ends in +all, fix it immediately.
What breaks an SPF record outright?
Two TXT records starting with v=spf1 cause a permerror. SPF fails completely for that domain. This is the most common self-inflicted break: adding a second record for a new vendor instead of editing the existing one. A single character string inside a TXT record is capped at 255 characters. Longer records are published as several quoted strings inside one TXT record, which the resolver concatenates. This is a formatting detail, not a second record.
Never use the ptr mechanism. RFC 7208 section 5.5 explicitly says it should not be used because it is slow, loads the .arpa name servers, and some receivers ignore it. If you inherit a record containing ptr, remove it.
Check for multiple SPF records.
dig +short TXT example.com
Look for more than one line starting with v=spf1. Merge them into one. Remove any ptr mechanisms.
Do subdomains need their own record?
SPF is not inherited. A record on example.com says nothing about mail.example.com. Every subdomain that sends mail needs its own record. Every subdomain and domain that does not send mail should publish v=spf1 -all to block spoofing. Parked domains the business owns but never uses need this too.
Create a separate TXT record for each sending subdomain. For non-sending subdomains, publish a hard fail record.
v=spf1 -all
Check subdomains individually.
dig +short TXT mail.example.com
Ensure sending subdomains have valid records and non-sending ones have -all.
Why does SPF fail on forwarded mail?
When a recipient auto-forwards a message, the forwarding server becomes the sender. Its address is not in the original SPF record, so the check fails at the final destination. This is a known structural limitation of SPF, not a misconfiguration.
Some forwarders implement SRS (Sender Rewriting Scheme) to work around it. The real mitigation is DKIM, which survives forwarding, combined with DMARC so a DKIM pass is enough on its own.
Do not chase SPF failures caused by forwarding by loosening the record. Rely on DKIM and DMARC instead.
Check if DKIM is configured. Look for DKIM signatures in the email headers. If DKIM is present and passes, the SPF failure on forwarding is expected and harmless.
How do I check what is published?
Use DNS lookup tools to verify the record.
dig +short TXT example.com
nslookup -type=TXT example.com
On Windows PowerShell:
Resolve-DnsName -Type TXT example.com
To see just the SPF line:
dig +short TXT example.com | grep spf1
Check for exactly one v=spf1 string. Ensure no ptr or +all is present. Count the lookup-costing mechanisms to stay at 10 or under, including nesting.
Moorfox publishes a free SPF, DKIM and DMARC checker at /tools/spf-dkim-dmarc-checker/ that reads the live records for a domain, so the counting above does not have to be done by hand. Moorfox itself is remote monitoring and management for the machines behind the mailboxes rather than a mail product: it will not fix a DNS record, but the endpoint that sends mail as the domain is the one worth knowing the patch age, anti-malware state and disk encryption of, and that is what the per-device security score reports.
What order should I roll this out in?
Inventory every system that sends mail as the domain. Mail platform, CRM, ticketing, accounting and invoicing, monitoring and alerting, scan-to-email on the office MFP, the web site's contact form, and any marketing platform. The MFP and the monitoring system are the two that get forgotten.
Publish a record ending ~all. Publish a DMARC record at _dmarc.example.com with p=none and an rua= address to receive aggregate reports. Reports reveal the senders missed in step one. Read reports for a few weeks. Add legitimate senders missed. Tighten to -all. Only then move DMARC towards p=quarantine and p=reject.
Set up DKIM. SPF and DKIM together, with DMARC on top, is the complete arrangement. SPF alone is the weakest of the three.
Use the Moorfox checker at /tools/spf-dkim-dmarc-checker/ to verify the final configuration. Use /tools/dns-lookup/ for reading raw TXT records.
Frequently asked questions
Can I have two SPF records?
No. A domain must have exactly one TXT record starting with v=spf1. A second record causes a permerror and SPF fails entirely for that domain. Merge all entries into a single record.
Should I use -all or ~all?
Start with ~all while discovering all senders, then move to -all once DMARC aggregate reports confirm no legitimate mail is failing. -all is the final destination for security.
Does SPF stop people spoofing my domain?
Not on its own, because SPF checks the envelope sender and not the From: header the recipient sees. SPF plus DKIM plus a DMARC policy of quarantine or reject is what stops spoofing.
Why does my SPF record fail when mail is forwarded?
The forwarding server becomes the sender and is not in your SPF record, which is expected behaviour. DKIM survives forwarding, so DMARC accepts a passing DKIM signature even if SPF fails.
What happens if I exceed 10 DNS lookups?
The evaluation returns a permerror and the SPF check does not pass. Remove dead senders first, move bulk mail to a subdomain second, and treat flattening as a last resort.
Do subdomains inherit the parent domain's SPF record?
No. Each sending subdomain needs its own record. Any domain or subdomain that never sends mail should publish v=spf1 -all to prevent spoofing.