How it worksPricingLog InSign Up Free

What is SPF? The practical difference from DKIM

Definition

SPF, or Sender Policy Framework, lets a domain publish which mail servers are authorized to use that domain in the SMTP MAIL FROM or HELO identity. A receiving server compares the connecting IP address with the domain's SPF policy and returns a result such as pass, fail, softfail, neutral, temperror, or permerror.

SPF

What is SPF? The envelope identity behind email authorization

The part that causes the most confusion is the identity SPF authenticates. SPF does not directly authenticate the visible `From:` address that a person sees in their inbox. DMARC is what connects a successful SPF result to that visible identity through alignment.

There are 2 From identities in ordinary email

A simplified SMTP transaction can contain both:

Figure 1

SPF checks the envelope, not the address a person reads

What SPF checks
MAIL FROM:<[email protected]> 1
What the recipient sees
From: Store <[email protected]> 2
1
SPF-authenticated domain

The receiving server checks DNS for mailer.example and evaluates the connecting IP against it.

2
Not checked by SPF

The visible From domain is compared to the SPF and DKIM results later, by DMARC alignment, not by SPF itself.

Empty reverse path: When MAIL FROM is null, the HELO/EHLO identity becomes the identity SPF evaluates instead.
SPF authorizes the MAIL FROM or HELO identity. The visible From header is a separate field that only DMARC compares against the SPF and DKIM results.

They have different jobs.

  • MAIL FROM is an SMTP envelope identity. It is commonly reflected later as the Return-Path and is where delivery status information can be directed
  • From: is an RFC 5322 message header intended for the reader. DMARC calls its domain the Author Domain

SPF normally evaluates the domain in MAIL FROM. When the reverse path is null, as in some delivery-status messages, the HELO/EHLO identity becomes important. RFC 7208 also recommends checking HELO separately where appropriate.

So an ESP can legitimately send a message that visibly comes from brand.example while SPF passes for a vendor-controlled return-path domain. That is an SPF success, but it is not automatically an SPF-aligned DMARC success for brand.example.

How an SPF check works

At a high level:

  1. The receiving mail server sees the connecting sender IP
  2. It determines the SPF identity to check, usually the MAIL FROM domain
  3. It retrieves that domain's SPF policy from DNS TXT records
  4. It evaluates the record from left to right according to SPF's mechanism rules
  5. It returns an SPF result

A simple policy might be:

v=spf1 ip4:192.0.2.25 include:_spf.vendor.example -all

This says, conceptually:

  • this is an SPF version 1 policy
  • authorize the listed IPv4 address
  • also evaluate the sending infrastructure authorized by _spf.vendor.example
  • if no preceding mechanism matches, return fail because of -all

Do not copy an example record literally. Your SPF record should describe your real outbound architecture.

Qualifiers change what a match means

SPF mechanisms can use a qualifier:

OptionQualifierCommon interpretation when the mechanism matches
++pass; this is the default when no qualifier is written
--fail
~~softfail
??neutral

That makes -all meaningfully different from ~all. A record ending in -all makes a definitive negative authorization statement for hosts that matched nothing earlier. A record ending in ~all says those hosts are probably not authorized but yields softfail rather than fail.

The receiver still decides how an SPF result affects final handling. SPF produces authentication information. It is not, by itself, an inbox-placement command.

The 10-lookup limit is about evaluation, not characters

SPF has a DNS-query budget to protect receivers from records that trigger excessive DNS work. RFC 7208 says implementations must limit the total number of terms that cause DNS queries to 10 during one SPF evaluation. Exceeding the limit produces permerror. The lookup-causing terms include:

  • include
  • a
  • mx
  • ptr
  • exists
  • redirect

Terms such as ip4, ip6, and all do not consume that same lookup budget during evaluation. The RFC also says the ptr mechanism should not be published.

The practical lesson is that "my SPF TXT record is short" does not mean it is cheap. One include: can expand into another record, which can include several more records, which can in turn trigger a or mx lookups. The receiver counts the evaluation path, not just the mechanisms visible in your top-level record.

Figure 2

The limit counts terms, not characters

  • include: 1 lookup

    Also expands into that record’s own lookups

  • a: 1 lookup
  • mx: 1 lookup
  • ptr: 1 lookup

    And should not be published

  • exists: 1 lookup
  • redirect: 1 lookup
  • ip4 / ip6: 0 lookups
  • all: 0 lookups
Does the full evaluated path exceed 10 lookup-causing terms?
  • No
    SPF evaluates to pass, fail, softfail, or neutral
  • Yes
    permerrorRegardless of how short the top-level record looks
A short-looking record can still fail. Each include, a, mx, ptr, exists, or redirect spends from the same 10-term budget, and nested includes spend from it too.

One domain should not publish multiple SPF records

A common mistake is to add a second v=spf1 TXT record when connecting a new sending platform. RFC 7208 requires selection of a single SPF record for the owner name; multiple SPF records are not a way to combine authorization policies. Instead, you need one policy that represents all legitimate sending sources without exceeding SPF's processing limits. For example, these are not 2 independent permissions that receivers should merge:

v=spf1 include:_spf.platform-a.example -allv=spf1 include:_spf.platform-b.example -all

The correct design is one valid SPF policy that incorporates the sources you truly need, then is tested for the resulting lookup path and semantics.

SPF pass is not the same as DMARC pass

Consider:

From: [email protected]MAIL FROM: [email protected]

The provider's IP is authorized by provider.example, so SPF passes. But the SPF-authenticated domain is provider.example, while the visible From domain is brand.example.

Under DMARC, an SPF pass helps only when its authenticated domain aligns with the Author domain. If DKIM signs with an aligned d=brand.example, DKIM can supply the DMARC pass instead. If neither SPF nor DKIM has an aligned passing identity, DMARC fails even though SPF may have passed for the provider's own domain.

This is one reason branded return-path support matters at some ESPs. It can make the SPF identity align with the visible From domain. It is also why a dashboard statement like "SPF is configured" is incomplete without identifying which domain is being authenticated.

Why forwarding is hard for SPF

SPF authorizes sending hosts for an envelope domain. A straightforward forwarder receives a message and then sends it onward from the forwarder's own IP address. The original domain's SPF policy may never have authorized that forwarding IP.

The visible From header can remain unchanged, but the transport path has changed. That can make the forwarded copy fail SPF even though the original sender was legitimate.

DKIM often provides a more durable DMARC authentication path through forwarding because its signature travels with the message. That is only true if the forwarding or mailing-list system does not change signed content in a way that invalidates the signature.

The operational conclusion is not "SPF is bad." The better conclusion is simpler: SPF authenticates a transport identity whose path can change. Use DKIM and DMARC alongside it rather than expecting SPF to solve every indirect-mail scenario.

How to read a real SPF record

Take this illustrative record:

v=spf1 ip4:203.0.113.0/24 include:mail.example-provider.com mx -all

Read it left to right:

  1. v=spf1 declares the record format
  2. ip4:203.0.113.0/24 authorizes that IPv4 network directly
  3. include:mail.example-provider.com evaluates the provider's SPF policy for a match
  4. mx can authorize hosts referenced by this domain's MX records
  5. -all fails anything not matched earlier

The record does not say that every message sent from those IPs belongs in the inbox. It only states which hosts are authorized to use the SPF identity under this domain.

`permerror`

Check for malformed records, multiple SPF records, recursive include problems, and more than 10 lookup-causing terms in the evaluated path.

SPF passes but DMARC fails

Inspect identity alignment. The SPF-authenticated domain may be the provider's return-path domain rather than your visible From domain. Also inspect DKIM because an aligned DKIM pass can satisfy DMARC.

SPF fails only after forwarding

The forwarded copy is arriving from a server not authorized by the original SPF policy. Diagnose this as an indirect-mail-path issue rather than blindly adding arbitrary forwarding IPs to your policy.

A provider says to add another SPF record

If that instruction literally creates a second v=spf1 record at the same DNS owner name, stop and reconcile the policies. The domain needs one valid SPF record.

An SPF record worked yesterday and now returns `permerror`

Nested provider records can change. Recalculate the full lookup path and check whether a vendor include expanded enough to push the evaluation over SPF limits.

A practical SPF rollout

Six steps, in order.

  1. Map senders before editing DNSInventory every system that uses the target domain in MAIL FROM or HELO. Include SaaS tools, transactional mail, support systems, internal MTAs, monitoring tools, and legacy infrastructure.
  2. Decide which sources really need this SPF domainDo not accumulate include: mechanisms forever because a service was once connected. Removing abandoned senders makes the policy smaller and limits who is authorized to use the domain.
  3. Build one policyCombine necessary authorization into one SPF record. Prefer direct IP mechanisms when they genuinely describe fixed infrastructure, and provider includes when the provider owns a changing pool that it publishes for customers.
  4. Count the complete lookup pathExpand nested includes in your test, not just the top-level text. A provider can change its own SPF record later, so a policy that is near the lookup ceiling has less safety margin.
  5. Test the actual identityVerify which MAIL FROM domain production messages use. Testing brand.example is irrelevant if your ESP actually sends with bounce.mail.brand.example or a vendor domain.
  6. Re-check DMARC alignmentAfter SPF passes, confirm whether the SPF domain aligns with the visible From domain. If not, make sure a valid aligned DKIM path exists.

Common mistakes

  1. Thinking SPF authenticates the visible From: header directly
  2. Publishing multiple v=spf1 records for one name
  3. Counting only top-level includes instead of the expanded DNS evaluation path
  4. Treating ~all and -all as equivalent
  5. Copying a vendor's sample record without mapping other legitimate senders
  6. Assuming SPF pass guarantees DMARC pass
  7. Adding forwarding infrastructure to SPF without understanding who is actually authorized to send for the domain

Questions we get asked

What does SPF stand for?

Sender Policy Framework. It is the mechanism defined by RFC 7208 for authorizing hosts to use domains in SMTP MAIL FROM and HELO identities.

Does SPF verify the address users see in the From field?

Not directly. SPF normally authenticates the SMTP MAIL FROM identity. DMARC compares the successful SPF identity with the visible Author domain to determine SPF alignment.

How many DNS lookups can SPF use?

RFC 7208 requires implementations to limit the evaluation to 10 terms that cause DNS queries, including include, a, mx, ptr, exists, and redirect. Exceeding that limit results in permerror.

Can I have 2 SPF records?

You should not publish multiple SPF policies for the same owner name and expect receivers to merge them. Build one valid policy representing the authorized sources.

Is SPF enough for modern bulk email?

No. Major mailbox-provider requirements for bulk senders go beyond SPF. For example, Gmail currently requires both SPF and DKIM plus DMARC and alignment for bulk senders to personal Gmail accounts.

OnVoard's take

The key SPF debugging question is not "Is there an SPF record?" Ask instead: "Which domain is SPF authenticating?" What path did the receiver evaluate?

That question immediately exposes 2 problems that simple checklists miss. A record can be technically valid but authenticate the wrong identity for DMARC. A record can also look short while its nested DNS path exceeds SPF's limits. Treat SPF as a transport-authorization map, not a branding field.

Try OnVoard free

Every app on every plan. Connect your store and switch on the flows in an evening.

Sign Up Free
Share
Commonly confused with

Sources

GoogleEmail sender guidelinessupport.google.com/mail/answer/81126?hl=en
Google Gmail HelpEmail sender guidelinessupport.google.com/a/answer/81126?hl=en
IETF / RFC EditorRFC 7208: Sender Policy Framework (SPF) for Authorizing Use of Domains in Email, Version 1rfc-editor.org/rfc/rfc7208.html
IETF / RFC EditorRFC 9989: Domain-Based Message Authentication, Reporting, and Conformance (DMARC)rfc-editor.org/rfc/rfc9989.html
IETF / RFC EditorRFC 7208: Sender Policy Frameworkrfc-editor.org/rfc/rfc7208