# SPF record: syntax, examples and ~all vs -all

> An SPF record is the DNS TXT record that lists which servers may send email for your domain. Its syntax term by term, copy-ready examples, and when to end it with ~all or -all.

Updated 2026-09-26 · Security · HTML version: https://getreport.app/guides/spf-record

An SPF record is a TXT record in your domain's DNS that lists the servers allowed to send email for your domain, such as `v=spf1 include:_spf.google.com ~all`. Receiving servers compare the server that delivered a message with that list, and treat mail from anywhere else as a soft fail (`~all`) or a fail (`-all`). A domain has exactly one SPF record, and it must stay within 10 DNS lookups.

This guide is for whoever edits the domain's DNS and has been asked to "add SPF" or to add a new sender to it. It covers the syntax term by term, examples you can copy, and the `~all` versus `-all` decision. SPF is the first of three records; the [SPF, DKIM and DMARC setup guide](https://getreport.app/guides/spf-dkim-dmarc-email-authentication) shows where it fits alongside DKIM and DMARC.

## Quick answer

- **Where:** one TXT record at the domain root (host `@` in most DNS panels).
- **Shape:** `v=spf1`, then the allowed senders, then one `all` term at the end.
- **Senders:** `include:` for a provider's list, `ip4:`/`ip6:` for your own addresses.
- **Ending:** `~all` (softfail) while you confirm your senders; `-all` (fail) when the list is complete. Never `+all`.
- **Limits:** one SPF record per domain, and at most 10 DNS lookups across all includes, or SPF fails with `permerror`.
- **What it does not do:** protect the From address your recipients see. That takes [DMARC](https://getreport.app/guides/what-is-dmarc), which uses SPF and [DKIM](https://getreport.app/guides/what-is-dkim).

## What SPF checks, and what it does not

SPF (Sender Policy Framework) is defined in RFC 7208. When a server connects to deliver mail, the receiver takes the domain from the envelope sender (the `MAIL FROM` address, which ends up in the `Return-Path` header), fetches that domain's SPF record, and checks whether the connecting IP address is on the list.

Two things follow from that:

- **SPF checks the bounce address, not the From line.** Many newsletter and transactional services send with their own bounce domain, so your SPF record never comes into play for them. They authenticate your domain with DKIM instead.
- **SPF breaks when mail is forwarded.** The forwarding server is not on your list, so the forwarded copy fails. DKIM survives forwarding; SPF does not.

That is why SPF alone is not enough, and why DMARC accepts either SPF or DKIM.

## SPF record syntax

An SPF record is one line of space-separated terms, read left to right. The first term that matches the sending IP decides the result, so the order matters only for the `all` at the end.

```dns
example.com.  3600  IN  TXT  "v=spf1 include:_spf.google.com ip4:203.0.113.25 ~all"
```

### Version

`v=spf1` must be the very first thing in the record. A TXT record that does not start with it is not an SPF record.

### Mechanisms: who is allowed

| Mechanism | Matches | DNS lookup? |
| --- | --- | --- |
| `include:domain` | Any server allowed by that domain's SPF record | Yes |
| `ip4:203.0.113.25` or `ip4:203.0.113.0/24` | One IPv4 address or a range | No |
| `ip6:2001:db8::/32` | One IPv6 address or a range | No |
| `a` or `a:host` | The address of your domain (or the named host) | Yes |
| `mx` or `mx:domain` | The servers in your MX records | Yes |
| `exists:domain` | Any server, if the domain resolves; used for advanced macros | Yes |
| `ptr` | Reverse DNS of the sender. RFC 7208 says not to use it | Yes |
| `all` | Everything; always last | No |

### Qualifiers: what a match means

Each mechanism can have a prefix that sets the result when it matches. Without one, `+` (pass) is assumed.

| Qualifier | Result | Typical use |
| --- | --- | --- |
| `+` (default) | pass | `include:`, `ip4:` and the rest |
| `-` | fail | `-all` |
| `~` | softfail | `~all` |
| `?` | neutral | `?all`, which says nothing useful |

### Modifiers

- `redirect=domain` uses another domain's SPF record instead of this one, when nothing else matched. Handy when many domains share one policy; it counts as a lookup.
- `exp=domain` points to an explanation text for rejected mail. Rarely used.

### The limits

- **One record.** Two TXT records starting with `v=spf1` make SPF return `permerror` for every message.
- **10 DNS lookups.** Every `include`, `a`, `mx`, `ptr`, `exists` and `redirect` counts, including the ones inside included records. Past 10, receivers return `permerror`.
- **2 void lookups.** RFC 7208 also recommends failing after more than two lookups that return nothing, which catches includes pointing at deleted records.
- **255 characters per string.** A longer record is split into several quoted strings inside the same TXT record; receivers join them without spaces, so leave a space at the end of the first string.

Merging duplicate records and getting back under 10 lookups is a job of its own; the [SPF, DKIM and DMARC setup guide](https://getreport.app/guides/spf-dkim-dmarc-email-authentication#multiple-spf-records-and-the-10-lookup-limit) covers both.

## SPF record examples

Each example is the complete value of the one TXT record at your domain root. Copy the include values from your provider's own help page, because they occasionally change.

**Google Workspace only:**

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

**Microsoft 365 only:**

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

**Google Workspace, a helpdesk and your own web server:**

```dns
v=spf1 include:_spf.google.com include:mail.zendesk.com ip4:203.0.113.25 ~all
```

The `ip4:` covers contact-form and order mail sent directly from the web server. It costs no lookup, unlike `a`.

**A domain that never sends email:**

```dns
v=spf1 -all
```

Publish this on parked domains and redirect-only domains, together with a DMARC record of `v=DMARC1; p=reject`. It tells receivers that no server may send as the domain.

**Newsletter mail on a subdomain:**

```dns
; On news.example.com, separate from the root record
v=spf1 include:sendgrid.net ~all
```

A subdomain has its own SPF record and its own 10 lookups, which is a clean way to keep the root record short. Only add an include like this when the service's setup page asks for one; many services need DKIM records only.

## SPF softfail vs hardfail: ~all or -all?

The `all` at the end decides what happens to mail from any server you did not list.

| Ending | Result | Meaning |
| --- | --- | --- |
| `-all` | fail (hardfail) | "Mail from anywhere else is not from us." |
| `~all` | softfail | "Mail from anywhere else is probably not from us." |
| `?all` | neutral | "No opinion." Offers no protection. |
| `+all` | pass | "Anyone may send as us." Never use it. |

On its own, SPF gives no instruction to reject or deliver; receivers decide. In practice, a softfail usually counts against the message in spam filtering, and a hardfail may be rejected outright.

Which to use:

- **Start with `~all`.** While you are still finding every service that sends as you, a softfail on a forgotten sender costs spam-folder placement, not a bounce.
- **Move to `-all` when the list is complete** and your DMARC reports show every real sender passing.
- **Once DMARC enforces, the difference is small.** DMARC makes the final decision, and it looks at whether SPF or DKIM passed and aligned, not at soft versus hard.

One reason many administrators keep `~all` even at `p=reject`: some receivers reject a `-all` failure during the SMTP conversation, before DMARC can see that DKIM passed. Forwarded mail, which fails SPF but keeps a valid DKIM signature, is the usual casualty. If you rely on DKIM for forwarded mail, `~all` is the safer ending.

## How to add or change your SPF record

1. **Look for an existing record.** In your DNS panel, filter TXT records at the root for `v=spf1`. If one exists, you edit it; you never add a second.
2. **List every sender.** Your mailbox provider, and any service that sends as your domain with its own servers and asks for an include: helpdesk, CRM, invoicing, web server.
3. **Write the record.** `v=spf1`, the includes and IP ranges, then `~all`.
4. **Save and check the lookup count.** Some providers' includes use several lookups each, because their record includes further records; count them with a tool rather than by hand.
5. **Send a test message** to a Gmail address, choose Show original, and look for `SPF: PASS` with your domain.

## How to check your SPF record

> **Free tool:** [DMARC, SPF, DKIM and MX record checker](https://getreport.app/tools/email-dns-check): Free DMARC checker that also tests SPF, DKIM and MX. See what is missing or broken and get the exact DNS records to add. No sign-up, results in seconds.

The email and DNS health check finds your SPF record, follows every include to the end, counts the DNS lookups and reads the `all` ending. When something is wrong, it writes the corrected record for you.

> **Check: The domain publishes an SPF record.** SPF tells receiving servers which servers may send mail for your domain. Without it, spoofed mail is harder to reject and your real mail is more likely to land in spam.
>
> 1. Add one TXT record at the domain root that starts with v=spf1, includes each service that sends for you (your mailbox provider, newsletter tool, shop) and ends with ~all.
> 2. Keep it to one record; two SPF records make both invalid.

> **Check: SPF syntax and lookup limit.** A broken SPF record counts as no record at all. The most common break is more than 10 DNS lookups once every include is followed, which makes receivers give up with a "permerror".
>
> 1. Remove include: entries for services you no longer use, and merge or flatten the rest until the count is 10 or less.
> 2. Replace mx, a and ptr mechanisms with the ip4 or ip6 ranges they stand for when you are close to the limit.

> **Check: SPF catch-all rule.** The last term of an SPF record decides what happens to mail from servers you did not list. +all allows everyone, ?all says nothing, and a missing all leaves receivers guessing.
>
> 1. End the record with ~all (soft fail) while you check your senders, then -all (fail) once every sender is listed.

From a terminal:

```bash
dig +short TXT example.com | grep spf1
nslookup -type=txt example.com
```

## Common SPF mistakes

- **A second SPF record** added by a new service's setup wizard. Merge its include into the existing record and delete the extra one.
- **Over 10 lookups** after adding one service too many. Remove includes for services you no longer use, and replace `a` and `mx` with `ip4:` ranges.
- **`+all` or `?all`** copied from an old tutorial. Both leave the domain open.
- **An include for a service that does not need it.** It costs lookups and changes nothing, because the service sends with its own bounce domain.
- **SPF only on `www`.** Mail uses the root domain (or the subdomain in the sender address), not `www`.
- **Quotes or `v=spf1` typed twice** when the DNS panel adds quotes itself.

## Questions people ask

### What is an SPF record?

An SPF record is a TXT record at your domain root that lists the servers allowed to send mail for it, such as `v=spf1 include:_spf.google.com ~all`. Receivers compare the sending server with that list. A domain may have only one SPF record, and it must stay within 10 DNS lookups, or SPF fails for every message you send.

### What is the difference between ~all and -all?

`~all` is a softfail: mail from servers not on your list is marked as suspicious but usually still accepted, often into spam. `-all` is a hardfail: such mail should be treated as not from you, and some receivers reject it outright. Start with `~all` while you confirm your senders, and switch to `-all` once your list is complete.

### What does SPF softfail mean?

Softfail means the server that sent the message is not in the domain's SPF record, and the record ends with `~all`, so the domain says the mail is probably not legitimate without asking for rejection. Receivers usually accept it but weigh it against the message. If your own mail shows softfail, add the sending service to your SPF record or send it with DKIM.

### Where do I add an SPF record?

At your DNS provider, which is often your domain registrar, Cloudflare or your web host. Create a TXT record at the root of the domain, usually shown as host `@` or left blank, with the SPF value. Your email provider only tells you what to include; the record itself must be in public DNS for receivers to find it.

### Do I need an SPF record if my domain sends no email?

Yes. Publish `v=spf1 -all`, which says no server is allowed to send for the domain, and add a DMARC record with `p=reject`. Without them, a parked or unused domain is an easy one to forge in phishing, because receivers have no way to tell that mail from it cannot be genuine.

### Does SPF work with forwarded email?

No, SPF usually fails on forwarded mail, because the forwarding server delivers the message from its own IP address, which is not in your SPF record. That is why DKIM matters: its signature travels with the message and normally survives forwarding, so DMARC can still pass. Some forwarders rewrite the envelope sender (SRS) so SPF passes for their own domain instead.
