# SPF Record Generator and Policy Planner

> Build one ordered RFC 7208 SPF policy, inspect every mechanism and qualifier, calculate the visible DNS-lookup floor, split long TXT values safely, record deployment evidence, and export an exact change handoff. The generator reports what it can prove and labels the nested DNS work it cannot know statically.

- **Canonical page:** [https://emailbump.com/tools/spf-record-generator](https://emailbump.com/tools/spf-record-generator)
- **Interactive tool:** [Open the SPF policy generator](https://emailbump.com/tools/spf-record-generator)
- **Category:** Email authentication and DNS
- **Standard:** [RFC 7208 — Sender Policy Framework](https://www.rfc-editor.org/rfc/rfc7208.html)
- **Updated:** July 2026
- **Privacy:** Policy construction, validation, splitting, and exports run locally in the browser
- **Important boundary:** Provider include targets and nested DNS policies must be verified live

## The central principle

An SPF record is an ordered authorization policy, not a list of email brands.

The policy answers a specific question during an SMTP transaction:

> Is this connecting client IP authorized to use this SMTP MAIL FROM or HELO domain?

That boundary matters. SPF does not directly authenticate the visible address in the message's From header. A message can pass SPF for a provider-controlled return-path domain while showing a different visible From domain. DMARC can use SPF for its own pass only when the authenticated SPF domain aligns with the visible From domain.

The generator therefore asks for the exact policy domain and encourages an inventory of:

- SMTP MAIL FROM domains
- Return-path or bounce domains
- HELO or EHLO names
- Connecting IPv4 and IPv6 sources
- Provider include targets
- Application relays
- Marketing platforms
- Support systems
- Billing and identity systems
- Owners and retirement dates

Inventorying only the name visible to recipients is not enough.

## What the interactive tool produces

The tool generates:

- One logical SPF TXT value beginning with `v=spf1`
- An exact DNS owner name
- A configurable TTL for the deployment handoff
- An ordered mechanism ledger
- Qualifier meaning for every mechanism
- A terminal unmatched-sender result
- Optional `redirect` and `exp` modifiers
- A direct DNS-lookup floor
- A flag when nested lookup cost remains unknown
- UTF-8 byte and character counts
- One or more legal quoted DNS TXT character-strings
- A zone-file-style line
- Syntax and policy findings
- Deployment-readiness attestations
- A text change runbook
- A structured JSON report

It does not publish DNS, resolve provider policies, certify deliverability, or prove that the sender inventory is complete.

## Record model

The generated logical record has this shape:

```text
v=spf1 [ordered mechanisms] [terminal all] [optional modifiers]
```

Example:

```text
v=spf1 include:_spf.google.com ip4:192.0.2.64/28 ~all
```

The corresponding handoff could be:

```text
example.com. 3600 IN TXT "v=spf1 include:_spf.google.com ip4:192.0.2.64/28 ~all"
```

DNS control panels vary. Some expect `@` instead of the complete owner name. Some add quotes automatically. The logical TXT value is the portable artifact; the zone-file line is an explicit handoff, not a promise that every provider uses zone-file syntax in its interface.

## Supported mechanisms

### include

`include:domain.example` asks the receiver to evaluate another domain's SPF policy in a specific way. It is commonly used for an email provider.

An include:

- Contributes at least one DNS-querying term
- Can add more terms through the referenced policy
- Authorizes the current sender only when the included policy returns pass
- Creates an operational dependency on another domain
- Must be verified in current provider documentation

An include value copied from an old article, another customer's DNS, or a migration ticket can be stale or unrelated.

### ip4

`ip4` authorizes one IPv4 address or CIDR range.

Examples:

```text
ip4:192.0.2.10
ip4:198.51.100.0/28
```

The mechanism does not itself cause a DNS lookup during SPF evaluation. A range that is broader than the actual sender fleet authorizes more infrastructure than necessary, so record the system owner and intended range.

### ip6

`ip6` authorizes one IPv6 address or CIDR range.

Examples:

```text
ip6:2001:db8::10
ip6:2001:db8:1200::/48
```

The generator validates IPv6 structure and a prefix from zero through 128. As with IPv4, use the narrowest operationally correct range and keep ownership evidence.

### a

The `a` mechanism authorizes addresses returned for a domain's A or AAAA records. With no explicit target it uses the current policy domain.

```text
a
a:mail.example.com
```

This term causes DNS work. A blank target can also authorize web-hosting addresses if the policy domain's address records point at a web service. That is why the interface makes a blank target visible and calls for review.

### mx

The `mx` mechanism authorizes address records reached through a domain's MX exchangers. With no target it uses the policy domain.

```text
mx
mx:mail.example.com
```

Inbound and outbound mail infrastructure are often different. Publishing `mx` by habit can authorize servers that receive mail but should not originate it.

### exists

`exists` tests whether an A lookup for an expanded domain returns an address. It is commonly paired with SPF macros and specialized authorization infrastructure.

The tool preserves an intentionally supplied macro expression but does not execute the RFC macro transformer. An `exists` policy needs expert review for:

- Correct macro expansion
- DNS query volume
- Void lookups
- Privacy exposure
- Failure behavior
- Ownership of the backing DNS data

## Qualifiers and first-match behavior

SPF mechanisms are evaluated from left to right. Evaluation stops at the first matching mechanism. A qualifier determines the result returned by that match.

### Plus: pass

`+` means pass. It is the default and is usually omitted.

These two terms are equivalent:

```text
+ip4:192.0.2.10
ip4:192.0.2.10
```

The generator omits the plus sign in output while retaining the chosen meaning in the ledger.

### Minus: fail

`-` means fail. A negative qualifier on a source mechanism is different from terminal `-all`: it produces fail when that specific source term matches.

### Tilde: softfail

`~` means softfail. It expresses that the matching host is probably not authorized while leaving final message handling to receiver policy.

### Question mark: neutral

`?` means neutral. It makes no authorization assertion about a match.

### Why order changes meaning

Consider:

```text
v=spf1 -ip4:192.0.2.0/24 ip4:192.0.2.10 -all
```

The broader negative range appears first. The specific positive address can never authorize `192.0.2.10` because evaluation already matched the earlier range. Both mechanisms may be syntactically valid, but the ordering defeats the apparent exception.

The interface gives each term a numbered row with move controls so ordering is an explicit policy choice.

## The terminal all mechanism

`all` always matches. It belongs at the end of the mechanism list.

The generator offers:

- `~all` — an unmatched client produces softfail
- `-all` — an unmatched client produces fail
- `?all` — an unmatched client produces neutral

It deliberately does not offer `+all`. A pass-qualified all mechanism authorizes every client and defeats the authorization boundary.

Choosing `~all` does not automatically make a rollout safe, and choosing `-all` does not automatically make it correct. Safety comes from complete sender coverage, verified dependencies, representative tests, controlled DNS changes, and monitoring.

For a domain that must never originate SMTP mail, a compact no-mail policy is:

```text
v=spf1 -all
```

## DNS lookup accounting

RFC 7208 limits the combined number of terms that cause DNS queries during one SPF evaluation to ten. The relevant categories include:

- `include`
- `a`
- `mx`
- `ptr`
- `exists`
- `redirect`

The generator does not offer `ptr` because RFC 7208 says it should not be used.

`ip4`, `ip6`, and `all` do not themselves contribute a DNS-querying term.

### Direct floor

The interface counts the lookup-bearing terms visible in the candidate record. That number is a floor.

For example:

```text
v=spf1 include:_spf.example.net a:mail.example.com ip4:192.0.2.10 ~all
```

The visible floor is two:

- One for `include`
- One for `a`

The static IP contributes none.

The final evaluation path can cost more because the included domain can contain its own lookup-bearing mechanisms.

### Why the tool does not claim a final lookup count

A complete count requires live recursive evaluation with:

- Current TXT answers
- Nested include policies
- Redirect targets
- The first-match path for a specific client
- DNS errors
- Void lookup outcomes
- A and MX address results
- Macro expansion where present

Displaying “2 of 10” as if two were the final cost would manufacture certainty. The UI therefore says “direct lookup floor” and marks nested cost as unknown whenever include or redirect appears.

After publication, use the [SPF lookup budget checker](https://emailbump.com/tools/spf-record-checker.md) to trace the live dependency graph.

## Additional DNS limits

The ten-term rule is not the only resource boundary.

RFC 7208 also constrains:

- Void lookups
- The number of address records evaluated for `mx`
- The number of address records evaluated for `a`
- Overall processing behavior after limits are exceeded

A static builder cannot determine these live answers. Its export preserves this limitation so an agent or reviewer does not treat the candidate as a completed DNS test.

## TXT character-strings and long records

A DNS TXT resource record can contain multiple character-strings. Each individual character-string is limited in size, and their data is concatenated for consumers.

When the logical SPF value exceeds 255 UTF-8 bytes, the generator splits it at term boundaries and preserves one space at each boundary. It then produces output such as:

```text
example.com. 3600 IN TXT "v=spf1 ... " "include:next.example ..."
```

The quotes are separate DNS character-strings inside one TXT resource record. They are not multiple SPF records.

Splitting solves the per-string representation limit. It does not guarantee that the total DNS response is operationally small. Large policies, DNSSEC signatures, additional records, UDP response size, and TCP fallback still deserve live testing. The tool raises a review finding when the logical record grows operationally large.

## Multiple SPF records

A domain must not publish multiple SPF records for the same owner name.

This is wrong:

```text
example.com. TXT "v=spf1 include:first.example ~all"
example.com. TXT "v=spf1 include:second.example ~all"
```

SPF record selection cannot merge them. Multiple selected SPF records produce a permanent error.

Merge all legitimate sources into one ordered policy:

```text
v=spf1 include:first.example include:second.example ~all
```

This single record can still exceed the lookup limit through nested policies, so merging is necessary but not sufficient.

## redirect modifier

`redirect=domain.example` replaces policy evaluation with another domain's SPF record only after every mechanism in the current record fails to match.

Because `all` always matches, a redirect placed after any all mechanism is unreachable. The interactive generator keeps a terminal all mechanism in every standard candidate and therefore reports redirect as unreachable when both are present.

This is intentional. A redirect architecture without `all` can be valid, but it changes the normal template and deserves expert design. The tool does not silently remove the terminal policy or pretend both paths are active.

Redirect contributes a DNS-querying term and can lead to more nested work.

## exp modifier

`exp=domain.example` points to a TXT explanation that can be used after an SPF fail result.

The modifier:

- Does not authorize a sender
- Is relevant only to fail handling
- Causes conditional DNS work
- Can contain macro-expanded content
- Can disclose information if designed carelessly
- Is not a substitute for operational logs

When the terminal policy is softfail or neutral, the tool notes that the terminal path will not use the fail explanation.

## Provider include values

Provider values are operational data and can change.

The tool's examples are starting points, not a provider catalog or warranty. Before publication:

1. Open the provider's current documentation.
2. Confirm the include target applies to the exact product and sending stream.
3. Confirm whether the provider uses a customer-specific return-path domain.
4. Confirm whether SPF alignment will be available for DMARC.
5. Record the system owner.
6. Trace the live nested policy.
7. Subscribe to provider change notices where available.

Do not infer an include target from the provider's marketing domain, MX records, or another customer's SPF policy.

## SPF flattening

Flattening replaces dynamic DNS-based authorization with a snapshot of resolved addresses.

It can reduce nested SPF lookups, but it introduces a synchronization system. Provider IP ranges can change. A stale flattened record can:

- Reject legitimate provider infrastructure
- Retain authorization for retired addresses
- Drift silently
- Exceed record-size or response-size boundaries
- Hide who owns the refresh process

Flatten only when there is an explicit automated refresh, diff, validation, rollback, and alerting workflow. A one-time copy of provider addresses is not a durable fix.

## Deployment evidence checklist

The interactive checklist records five operator attestations.

### Every sender is inventoried

The candidate includes every application, provider, relay, and indirect system that can originate mail for the policy domain.

### Provider documentation is current

Every include target has been checked against current provider documentation for the correct product.

### Envelope identities are mapped

MAIL FROM, return-path, and HELO domains are understood. The review is not based only on visible From addresses.

### The candidate was staged

The policy has been tested through live DNS and representative mail paths, with cache behavior considered.

### Future ownership exists

A named owner will update or remove terms when services, networks, or architecture change.

These boxes record human evidence. They are not inferred from the string and do not create a compliance or deliverability score.

## Safer change workflow

### 1. Discover the current state

Resolve TXT at the exact policy domain and determine whether one SPF record already exists. Preserve the current value, TTL, timestamp, and authoritative DNS context.

### 2. Inventory before editing

Map each sender to:

- Business purpose
- SMTP service
- MAIL FROM domain
- HELO identity
- DKIM signing domain
- Expected client IP or provider include
- DMARC alignment path
- System owner
- Retirement date if temporary

### 3. Build one candidate

Add only justified sources. Put mechanisms in intended evaluation order. Record why each term exists.

### 4. Inspect static risks

Review:

- Invalid domains or networks
- Duplicate terms
- Negative source qualifiers
- Macro-bearing expressions
- Blank `a` or `mx` targets
- Direct lookup floor
- Nested-cost uncertainty
- Record size
- Modifier reachability

### 5. Resolve the complete graph

Use live DNS to trace includes and redirect. Count the actual lookup path and inspect void or address-record limits.

### 6. Plan DNS caching

Lowering TTL immediately before a change does not remove already cached answers. Wait through the previous TTL where the migration requires it. Keep old authorization valid while legitimate in-flight mail might still be checked.

### 7. Publish one record

Replace or merge the existing SPF record. Do not add a second independent `v=spf1` TXT value.

### 8. Send representative messages

Exercise each real stream and receiver class. Inspect raw `Authentication-Results`, SMTP responses, return-path domains, and DKIM signatures.

### 9. Monitor DMARC evidence

SPF pass is not the same as DMARC-aligned SPF. Use aggregate data and message headers to verify the intended alignment path. DKIM can provide the stable aligned method for streams where forwarding or return-path architecture complicates SPF.

### 10. Remove retired authorization

Every unnecessary mechanism expands trust, consumes lookup or record budget, or creates future confusion. Review the policy as infrastructure changes.

## Findings generated by the tool

The pre-publish review can report:

- Invalid policy domain
- Empty required mechanism value
- Invalid IPv4 or IPv6 network
- Invalid domain-spec
- Invalid `a` or `mx` target
- Duplicate terms
- Negative or neutral source qualifier
- Unreachable redirect
- Explanation modifier without a fail path
- Direct lookup floor over ten
- Limited lookup headroom
- Unresolved nested policy cost
- No explicit authorized sender
- Advanced `exists` use
- Blank `a` or `mx` target
- Macro-bearing policy
- Large logical record
- Incomplete deployment evidence

“No blocking syntax issue” means only that the locally inspected candidate is coherent. It does not mean the record is published, unique, live, complete, aligned, within its final lookup limit, or safe for every legitimate stream.

## JSON report

The downloadable report contains:

- Generation timestamp
- Method boundary
- Raw input domain
- Ordered source mechanisms
- Source notes
- Terminal policy
- Redirect and explanation targets
- TTL
- Logical TXT value
- Zone-file handoff
- Split character-strings
- Byte count
- Direct lookup floor
- Nested-cost flag
- Findings
- Readiness attestations

An agent can use the report as a proposed change artifact, but should still resolve live DNS and obtain operator approval before publication.

## Common questions

### Can I have more than one SPF record?

No. Multiple selected SPF records for the same owner name produce permerror. Publish one merged policy.

### Does a subdomain inherit SPF from its parent?

No. Every MAIL FROM or HELO domain that needs policy must publish its own SPF record or use a deliberate redirect architecture.

### Is softfail always the correct starting policy?

No universal terminal qualifier replaces sender inventory and testing. Softfail is less definitive than fail, but an incomplete policy can still create misleading authentication results and a complete policy can support a more definitive assertion.

### Is hard fail the same as rejecting a message?

No. `-all` produces an SPF fail result for unmatched clients. Final SMTP or delivery handling remains receiver policy and can incorporate other evidence.

### Why does the generator omit the plus sign?

Pass is the default qualifier. `ip4:192.0.2.10` and `+ip4:192.0.2.10` have the same meaning.

### Why is plus-all unavailable?

`+all` makes every client match with pass and defeats SPF authorization.

### Does include copy another record into mine?

No. It invokes evaluation of another domain's SPF policy and interprets that result according to include semantics. It also creates nested DNS work.

### Does the visible include count equal the SPF lookup count?

No. Includes can contain more lookup-bearing terms. The tool reports a direct floor and directs operators to live recursive analysis.

### Are ip4 and ip6 free?

They do not consume the ten DNS-querying-term limit by themselves, but they still expand authorization and record size. They need ownership and lifecycle review.

### Does splitting a long TXT value create multiple SPF records?

No. Multiple quoted character-strings inside one TXT resource record are concatenated. Multiple independent TXT resource records beginning with `v=spf1` are the invalid case.

### Can SPF authenticate the visible From domain?

SPF authenticates the SMTP MAIL FROM or HELO identity. DMARC separately checks whether the SPF-authenticated domain aligns with the visible From domain.

### Should every domain publish SPF?

Every domain used as an SPF identity needs a deliberate policy. A domain that must not originate SMTP mail can publish `v=spf1 -all`. Architecture and DNS ownership determine the exact owner names.

### Can this generator publish the record?

No. It creates a candidate and a change handoff locally. Publication remains an explicit DNS operation.

## Primary source

- [RFC 7208 — Sender Policy Framework (SPF) for Authorizing Use of Domains in Email, Version 1](https://www.rfc-editor.org/rfc/rfc7208.html)

## Related tools and guidance

- [SPF lookup budget checker](https://emailbump.com/tools/spf-record-checker.md)
- [DNS propagation checker](https://emailbump.com/tools/dns-propagation-checker.md)
- [DMARC record builder](https://emailbump.com/tools/dmarc-record-builder.md)
- [Email header analyzer](https://emailbump.com/tools/email-header-analyzer.md)
- [SPF glossary definition](https://emailbump.com/glossary/spf.md)
- [DKIM glossary definition](https://emailbump.com/glossary/dkim.md)
- [DMARC glossary definition](https://emailbump.com/glossary/dmarc.md)
- [Email authentication glossary definition](https://emailbump.com/glossary/email-authentication.md)
- [Fighting phishing with DMARC](https://emailbump.com/blog/dmarc-phishing-protection.md)
- [Deliverability documentation](https://emailbump.com/docs/deliverability.md)
