# How to Create an SPF Record (Step-by-Step + Examples)

> Build a valid SPF record in minutes: syntax, the 10-lookup limit, real examples for Google Workspace and Microsoft 365, and a checker to verify it.

An [SPF record](/tools/spf) is a single line of DNS that tells receiving mail servers which servers are allowed to send email for your domain. Get it right and unauthorised senders fail authentication. Get it wrong and it is easy to get wrong and your own legitimate mail starts landing in spam. This guide covers the syntax, the limits that actually break records in production, and copy-ready examples.

## What SPF actually checks

This is the most misunderstood point about SPF, and it is worth getting straight before you write a record.

SPF does **not** check the `From:` address your recipient sees in their mail client. It checks the **envelope sender**: the address given in the SMTP `MAIL FROM` command, variously called `RFC5321.MailFrom`, the return-path, or the "P1 sender". SPF also optionally checks the domain given in the `HELO`/`EHLO` command.

A message can therefore pass SPF cleanly while displaying a completely different, spoofed `From:` address to the reader. That gap is exactly why [DMARC](/tools/dmarc) exists: DMARC requires the SPF-authenticated domain to *align* with the visible `From:` domain. SPF on its own is not an anti-spoofing control. SPF plus DMARC is.

## Steps to create an SPF record

### Step 1: Identify every sending source

List every system that sends email using your domain, not just your mailbox provider. The ones people forget:

- The mailbox platform itself (Google Workspace, Microsoft 365)
- Marketing and newsletter platforms
- Transactional mail from your application
- Helpdesk, CRM, invoicing, and applicant-tracking systems
- Scanners, copiers, and monitoring systems that email alerts

Missing a source is the most common cause of a "why did our invoices go to spam" incident. If you are not certain the list is complete, publish DMARC in monitoring mode first and read the reports, they name every source sending as you.

### Step 2: Choose your mechanisms

An SPF record is a TXT record that begins with [the SPF version tag](/learning/glossary/spf-v-spf1), `v=spf1`, and ends with an `all` mechanism. In between, you authorise sources with:

- `include:`: [authorise another domain's SPF record](/learning/glossary/spf-include) (how nearly every provider is added)
- `ip4:` / `ip6:`: authorise a literal IP address or CIDR range
- `a`: authorise the domain's own A/AAAA records
- `mx`: authorise the hosts in the domain's MX records

Avoid `ptr`. RFC 7208 says this mechanism "SHOULD NOT be published"; it survives only for backwards compatibility, and many receivers ignore it.

### Step 3: Choose how strictly to fail

The final `all` mechanism decides what happens to servers *not* on your list:

- `-all` (**fail**). The sender is explicitly not authorised. Receivers are expected to reject.
- `~all` (**softfail**): the sender is probably not authorised. Receivers usually accept but mark the message.
- `?all` (**neutral**): no assertion at all. Effectively pointless.

There is no single "correct" answer, and the two large providers genuinely differ: Google's published example for Google Workspace ends in `~all`, while Microsoft recommends `-all` for Microsoft 365. Start at `~all` while you confirm your source list is complete, then tighten to `-all`.

### Step 4: Write and publish the record

Publish it as a **TXT** record on the root of your domain. The host field is `@` or `yourdomain.com`, depending on your DNS provider's interface.

![SPF record examples](/images/figures/spf-record-examples.webp "1200x512")

Google Workspace only:

`v=spf1 include:_spf.google.com ~all`

Microsoft 365 only:

`v=spf1 include:spf.protection.outlook.com -all`

Google Workspace plus one of your own mail servers:

`v=spf1 ip4:203.0.113.25 include:_spf.google.com -all`

Then confirm it resolves and parses with the [SPF checker](/tools/spf), or check every authentication record at once with the [Email Security Score](/tools/email-security-score) tool.

## The limits that break SPF records

These are hard limits from RFC 7208, not guidelines. Exceed them and your record returns `permerror`, and receivers treat a `permerror` record as an authentication failure.

**Ten DNS lookups.** SPF evaluation must not perform more than 10 DNS-querying terms. The terms that count are `include`, `a`, `mx`, `ptr`, `exists`, and the `redirect` modifier. The terms that do *not* count are `all`, `ip4`, `ip6`, and `exp`. Critically, the count is recursive: an `include:` whose own record contains three `include:` statements spends four of your ten. Adding a fourth or fifth vendor is what usually tips a record over.

**Two void lookups.** A void lookup is a DNS query that returns either no records or NXDOMAIN. More than two is also a `permerror`. In practice this means a vendor you stopped using has removed their SPF record while your `include:` still points at it.

**One SPF record per domain.** Publishing two `v=spf1` TXT records on the same name is a `permerror`. The receiver cannot choose between them, so it rejects both. When you add a vendor, merge their `include:` into the existing record. Never publish a second one.

**255 characters per string.** A single DNS TXT character-string cannot exceed 255 bytes. Longer SPF records are published as multiple quoted strings inside one TXT record, which resolvers concatenate with no space inserted. Most DNS providers handle this splitting for you.

## Common issues with SPF records

### Why does my SPF record return "permerror" or "too many DNS lookups"?

You have exceeded ten DNS-querying terms. Count recursively, each `include:` costs one lookup plus whatever its own record spends. Fix it by dropping vendors you no longer use, replacing an `include:` with the specific `ip4:` ranges the vendor publishes (those cost zero lookups), or moving a vendor onto a subdomain that sends with its own envelope domain.

### Why does my mail fail SPF even though the sender is in the record?

Almost always because SPF is checking a different domain than you think. SPF validates the envelope sender, not the visible `From:`. Bulk platforms and ticketing systems frequently send with their own bounce domain in `MAIL FROM`, so SPF authenticates *their* domain and passes, while DMARC then fails your message for non-alignment. A [DMARC report](/resources-post/how-to-understand-dmarc-reports) shows which domain was actually checked.

### Why did mail break after I added a second SPF record?

Two `v=spf1` records on one name is a `permerror`, and a `permerror` counts as an authentication failure. This usually happens when a vendor's setup wizard publishes its own record instead of editing yours. Delete one and merge the `include:` into the survivor.

### Why does forwarded mail fail SPF?

Because forwarding changes the delivery path but not the envelope sender. The forwarding server is not in your SPF record, so SPF fails at the final destination. This is expected behaviour, not a misconfiguration you can fix in DNS, and it is precisely why DMARC accepts a DKIM pass *or* an SPF pass. [DKIM](/tools/dkim) signatures survive forwarding, so a properly signed message still authenticates.

## Best practices

- **Keep the record current.** Remove vendors as you stop using them. Stale `include:` statements burn lookups and cause void-lookup errors.
- **Never publish more than one SPF record.** Merge, don't append.
- **Pair SPF with DKIM and DMARC.** SPF alone protects nothing the recipient can see. All three together, as covered in [what are DMARC, DKIM, and SPF](/learning/what-is-email-authentication-and-why-does-it-matter), are what stop [spoofing](/learning/what-is-email-spoofing-and-how-can-you-prevent-it).
- **Monitor rather than assume.** DMARC aggregate reports tell you which sources pass and fail. Guessing does not.

## Frequently asked questions

### Do I need an SPF record on domains that never send email?

Yes. A parked or brand-protection domain should publish `v=spf1 -all`, which authorises nothing at all. Without it, someone can send mail as that domain and no receiver has grounds to reject it. Pair it with a DMARC record at `p=reject`.

### Do subdomains inherit my SPF record?

No. SPF is looked up on the exact domain in the envelope sender, and there is no inheritance. If `mail.yourdomain.com` sends mail, it needs its own SPF record. This differs from DMARC, which *does* fall back to the organisational domain's policy.

### Does a longer SPF record hurt deliverability?

Length itself does not, but the ten-lookup limit does, and long records are usually long because they carry many `include:` statements. A record that stays under the limit is fine at any character count.

### Will `-all` cause my legitimate mail to be rejected?

Only mail sent from a server you did not authorise. The risk is not the qualifier, it is an incomplete source list. Confirm from DMARC reports that every legitimate source passes before tightening `~all` to `-all`.

### Does SPF stop someone spoofing my `From:` address?

On its own, no. SPF authenticates the envelope sender, which the recipient never sees. Only DMARC ties the authenticated domain back to the visible `From:` address. Check what your domain publishes today with the [DMARC checker](/tools/dmarc).

## Related reading

- [What are DMARC, DKIM, and SPF?](/learning/what-is-email-authentication-and-why-does-it-matter)
- [How to understand DMARC reports](/resources-post/how-to-understand-dmarc-reports)
- [Email deliverability is not set and forget](/resources-post/email-deliverability-is-not-set-and-forget)
