Testing SPF requires two kinds of evidence: what DNS publishes and what a receiver evaluated for a particular message. Dig and nslookup help inspect the first. A trusted Authentication-Results field or receiver-side trace helps inspect the second. Keep those observations connected by the same envelope domain, sending route and time window.
Start with the right domain
Send a representative message through the application you are investigating and preserve its original headers. Identify the envelope identity from trusted receiver evidence, using Return-Path as a clue rather than confusing it with the visible From address. For an empty reverse path, SPF's identity handling involves HELO; do not assume ordinary-message inputs cover that case. RFC 7208 §2.3 and RFC 7208 §2.4 describe the identities.
Write down the sending IP observed by the receiver, the envelope identity, the recipient system and the message time. Do not upload full private headers to an unfamiliar public checker merely to obtain a coloured result. A minimal controlled fixture can often answer the technical question without disclosing unrelated message data.
Inspect the published TXT response
These are illustrative read-only commands. Replace the example name with the domain being evaluated; they are not evidence of tests already run:
dig TXT bounce.example.com.
nslookup -type=TXT bounce.example.com.
The BIND dig manual documents the query utility, and Microsoft's nslookup reference describes query options. Use a trailing dot for an absolute query name, avoiding unintended search-suffix expansion. Keep the full response when troubleshooting, including resolver, status, answer and TTL where shown. A shortened answer can be convenient for reading but omit diagnostic context.
Inspect the actual owner name and select the SPF value from unrelated TXT records. Multiple quoted character strings can belong to one TXT record; SPF treats those strings as concatenated without inserting spaces. Two separate applicable SPF records are a different problem. RFC 7208 §3.2 and RFC 7208 §3.3 define that distinction.
Read a paired synthetic result
The following is a fully synthetic fixture, not observed mail or a production record. Assume the receiver saw a direct connection from documentation address 192.0.2.10, MAIL FROM invoices@bounce.example.com and visible From invoices@example.com. Its DNS response contains one TXT resource record:
bounce.example.com. 300 IN TXT "v=spf1 ip4:192.0.2.10 " "-all"
The two strings within that one record join to v=spf1 ip4:192.0.2.10 -all. The trailing space in the first string separates the mechanisms. For the stated connection, the address mechanism matches and the expected SPF result is pass. A corresponding illustrative receiver result is:
Authentication-Results: mx.receiver.example;
spf=pass smtp.mailfrom=bounce.example.com
Treat this as trustworthy only under the explicit fixture assumption that mx.receiver.example is the destination's trusted authentication service. A sender could otherwise insert similar text. The example shows SPF evidence only; it does not assert a DKIM, DMARC or delivery result.
Contrast that with this different synthetic DNS answer, which contains two separate applicable records at the same name:
bounce.example.com. 300 IN TXT "v=spf1 ip4:192.0.2.10 -all"
bounce.example.com. 300 IN TXT "v=spf1 ip4:192.0.2.20 -all"
Record selection now returns permerror rather than combining the authorisations. Do not diagnose that situation by counting quotation marks alone; preserve the DNS resource-record boundaries.
Compare resolvers when publication is disputed
If the DNS editor and a recursive query disagree, identify the authoritative nameservers and query a verified authoritative server directly. Dig supports the form dig @server name TXT; substitute an actual verified server and target name. Compare the answer and timestamp with the recursive result. Do not assume the DNS account being edited hosts the delegated zone.
A current authoritative answer and an older recursive answer can indicate caching. A timeout, SERVFAIL and a successful response with no applicable record are different observations. Preserve the exact response before deciding the cause. Avoid repeatedly editing a correct record merely because one observation is stale.
Evaluate the message, not just syntax
A TXT lookup does not execute SPF. A standards-aware evaluator needs the connection IP and relevant SMTP identities, plus the DNS state it resolves. Inspect its trace for the matched mechanism, dependencies and errors. A static record validator may report a structurally acceptable policy without answering whether the real sender passes.
At the destination, read the Authentication-Results inserted by a trusted receiver, not an arbitrary earlier copy. RFC 8601 makes the trust boundary important. Record the SPF result and identity alongside DKIM and DMARC results without treating them as interchangeable.
Keep a reproducible test record
Save the commands, query times, DNS responses, evaluator inputs and redacted received-message evidence. Test each materially different application route and address family in use. Label synthetic fixtures separately from observed results. If the DNS view looks correct but the receiver disagrees, continue with tool pass versus recipient failure rather than declaring that the receiver must be wrong.
DNS background: RFC 1035 section 3.2.1 defines resource-record TTL; RFC 2308 §5 covers negative caching; RFC 8767 §4 updates TTL semantics and permits stale use when authoritative refresh fails. These describe DNS behaviour, not a universal completion time for a change.
Record the next decision
For the single-record fixture, keep the boundary showing two strings inside one record and the joining space; expected SPF is pass for 192.0.2.10. For the two-record fixture, selection fails with permerror before mechanisms are evaluated. Save the trusted-result assumption separately: the printed Authentication-Results text is not independently trustworthy. No command or mail verification was executed here.