Deliverability & DNS

How to Set Up an SPF Record (With Examples and Checks)

How to set up an SPF record step by step: correct syntax, ~all vs -all, the 10 DNS lookup limit, merging includes, and how to test the result.

On this page
  1. What an SPF record does
  2. Anatomy of an SPF record
  3. Step-by-step: create your SPF record
  4. The 10 DNS lookup limit
  5. ~all or -all?
  6. Common SPF errors and fixes
  7. Setting up SPF with Zomail
  8. FAQ

An SPF record is a single DNS TXT record on your domain that lists which servers may send email for it. To set one up, collect every service that sends as your domain, write one record starting with v=spf1, add an include: or ip4: for each sender, end it with ~all or -all, publish it at your DNS provider and test it.

What an SPF record does

SPF (Sender Policy Framework) is defined in RFC 7208. When a server receives a message, it takes the domain from the envelope sender (the MAIL FROM address in the SMTP conversation, later shown as Return-Path), looks up that domain's SPF record, and checks whether the IP address that connected is authorised.

Note the detail: SPF checks the envelope sender, not the From: line people see. That is why SPF on its own does not stop display spoofing, and why it works together with DKIM and DMARC. If you want the big picture first, read SPF, DKIM and DMARC explained.

Anatomy of an SPF record

example.com.  3600  IN  TXT  "v=spf1 include:_spf.zomail.io ip4:203.0.113.25 ~all"

Reading left to right:

  • v=spf1 — the version tag. It must come first, exactly like this.
  • Mechanisms — each one matches a set of senders:
  • include:domain — also accept whatever that domain's SPF record accepts (the usual way to authorise a provider).
  • ip4:203.0.113.25 or ip4:203.0.113.0/24 — a specific IPv4 address or range.
  • ip6:2001:db8::/32 — an IPv6 address or range.
  • a and mx — the IPs of this domain's A/AAAA or MX hosts.
  • exists and ptr — rarely needed; ptr is discouraged by the RFC.
  • **The all mechanism** — matches everything not matched earlier, so it always goes last.

Each mechanism can carry a qualifier:

QualifierExampleResultMeaning
+ (default)+allpassAllowed. Never use with all.
--allfailNot allowed; receivers may reject.
~~allsoftfailProbably not allowed; accept but mark.
??allneutralNo statement either way.

Step-by-step: create your SPF record

1. List everything that sends as your domain

This is the step people skip. Besides your mailbox provider, think about:

  • your website (contact forms, WooCommerce or shop notifications),
  • newsletter and marketing tools,
  • helpdesk and CRM systems,
  • invoicing, payroll and e-invoice software,
  • scanners or printers that email documents,
  • any old server that still relays mail.

Each vendor documents what to add, normally an include: value. If a tool sends from its own domain (for example bounce.vendor.example) in the envelope sender, it does not need to be in your SPF, but you still want it to sign with DKIM for your domain so DMARC passes.

2. Check for an existing record

Look up the current TXT records on the root of your domain:

dig +short TXT example.com
nslookup -type=TXT example.com

If a v=spf1 record already exists, edit it rather than adding a second one. Two SPF records on the same name produce a permerror, and most receivers then ignore SPF completely.

3. Write the record

For a business using Zomail for mailboxes, plus a newsletter tool and one on-premises scanner:

v=spf1 include:_spf.zomail.io include:_spf.newsletter.example ip4:198.51.100.10 ~all

If you use Zomail, the exact SPF value is shown on your domain page in the admin console, and the page warns you if it finds more than one SPF record or an existing record that is missing the Zomail include.

4. Publish it at your DNS provider

Create (or edit) a TXT record:

  • Name / Host: @ or blank (some providers want the full example.com)
  • Value: the record text, without the surrounding quotes unless your provider asks for them
  • TTL: 3600 is fine; use 300 while you are testing

Do not create a record of type "SPF" (type 99). It was deprecated by RFC 7208; use TXT.

5. Test it

After a few minutes, check the published value with dig +short TXT example.com, then send a message to a Gmail address and open Show original. You should see SPF: 'PASS' with IP …. The Authentication-Results header gives the detail:

Authentication-Results: mx.google.com;
  spf=pass (google.com: domain of anna@example.com designates 203.0.113.25 as permitted sender)

The 10 DNS lookup limit

RFC 7208 caps the number of mechanisms and modifiers that trigger DNS lookups at 10 per SPF evaluation. The ones that count are include, a, mx, ptr, exists and the redirect= modifier, including every lookup inside the records you include. ip4, ip6 and all cost nothing. There is also a limit of two "void" lookups (queries that return no records); going over either limit gives permerror.

This is easy to exceed without noticing. A large provider's include can use three or four lookups by itself, so five vendors can push you past 10. Ways to stay under:

  • Remove vendors you no longer use. Old includes are the most common cause.
  • Prefer vendors that use their own envelope domain. Many marketing tools let you set a custom return-path subdomain (for example bounce.example.com) with its own SPF, which keeps them out of your root record.
  • Use subdomains for bulk mail. Sending newsletters from news.example.com gives that subdomain its own SPF record and its own lookup budget.
  • **Replace a and mx with explicit ip4:** where the IPs are stable.
  • Be careful with "SPF flattening" services that replace includes with IP lists: if the vendor changes IPs and the flattened list is not refreshed, legitimate mail fails.

~all or -all?

Both are valid. -all (hard fail) states that nothing else may send; ~all (soft fail) says unlisted senders are suspicious. Once DMARC is in place, receivers make the final decision based on your DMARC policy, and for DMARC both fail and softfail simply count as "SPF did not pass". A common, safe approach is:

  1. Start with ~all while you discover every sender.
  2. Watch your DMARC reports until all legitimate sources pass.
  3. Move DMARC towards p=quarantine and p=reject (that is where enforcement really happens), and optionally switch SPF to -all.

Avoid ?all (it says nothing useful) and never use +all, which authorises every server on the internet. Our DMARC policy guide explains the rollout.

Common SPF errors and fixes

  • "Multiple SPF records" — merge them into one v=spf1 record with all the includes.
  • **permerror: too many DNS lookups** — count lookups and trim as described above.
  • Record split across two TXT strings incorrectly — a single TXT string is limited to 255 characters. Long records must be split into several quoted strings inside the same record ("v=spf1 include:a … " "include:b … ~all"), which receivers join without adding a space, so put the space inside one of the strings.
  • Typos — a missing colon (include _spf.zomail.io), commas between mechanisms or a misspelled vendor domain make the record invalid or silently useless. Mechanisms are separated by single spaces only.
  • SPF on the wrong name — the record belongs on the domain used in the envelope sender, usually the root example.com, not www or mail.
  • Forwarded mail failing SPF — expected behaviour. Make sure DKIM is set up so DMARC still passes; see how to set up DKIM.

If mail still lands in junk after SPF passes, the cause is usually elsewhere; why emails go to spam lists the other checks.

Setting up SPF with Zomail

In Zomail, the domain page shows the SPF value to publish alongside your MX, DKIM and DMARC records, checks it live and marks it correct, missing or wrong, with a hint for duplicates or a missing include. You can download a zone file for Cloudflare and similar providers, or use one-click Domain Connect where your DNS provider supports it. The getting started guide walks through each record, and plans are on the pricing page.

FAQ

Can I have two SPF records on one domain?

No. RFC 7208 allows exactly one v=spf1 record per name. With two, receivers return permerror and your SPF is effectively ignored. Merge all the includes and IPs into a single record.

What is the SPF 10 lookup limit?

During one SPF check, the mechanisms include, a, mx, ptr, exists and the redirect modifier may trigger at most 10 DNS lookups in total, including lookups inside included records. Exceeding it makes SPF return permerror. ip4, ip6 and all do not count.

Should I use ~all or -all in my SPF record?

Start with ~all while you confirm all your senders, then consider -all once DMARC reports show every legitimate source passing. With DMARC in place, your DMARC policy matters more than the choice between the two.

Does SPF need to include the servers that receive my mail?

No. SPF is only about outgoing mail. Receiving is controlled by your MX records. Only add mx to SPF if those same servers also send mail for your domain.

How long does an SPF record take to work?

As soon as resolvers see the new record, usually within minutes, but cached old values can last up to the previous record's TTL. Lowering the TTL to 300 seconds a day before a change speeds this up.

  • SPF record
  • SPF
  • DNS
  • email authentication
  • deliverability