2.5 KiB
spf-checker
(no submodules)
Purpose
Implements the SPF (RFC 7208) evaluation algorithm: parses the
record, walks each mechanism in order, follows include: and
redirect= with bounded depth and lookup limits, and matches the
candidate IPv4 / IPv6 address against ip4: and ip6: CIDR ranges.
The DNS resolver is fully injectable so the package can be embedded
in browsers, edge workers, or sandboxed runtimes that need to route
lookups through DoH or a service mesh.
Features
- Parses every mechanism token (
ip4,ip6,a,mx,include,all,exists,redirect) and their qualifier prefixes (+ - ~ ?). - Bounded recursion:
MAX_INCLUDE_DEPTH = 10andMAX_DNS_LOOKUPS = 10to surface RFC 7208 §4.6.4 permerror conditions instead of hanging. - IPv4 matching with
Number.parseInt+ bitmasks; IPv6 matching by expanding::shorthand and comparing bit prefixes. - Records
email_processing.spf.result_totalattributed byresultfor every outcome.
Usage: Basic
import { checkSpf } from "@suaveplan/email-processing/spf";
const out = await checkSpf(senderIp, fromDomain, async (d) => {
const recs = await dns.resolveTxt(d);
return recs.map((parts) => parts.join(""));
});
Usage: Advanced
import { checkSpf, parseSpfRecord } from "@suaveplan/email-processing/spf";
const recs = await dnsResolver(domain);
const v = recs.find((r) => r.startsWith("v=spf1"));
if (v) {
const mechs = parseSpfRecord(v);
if (mechs.some((m) => m.type === "all" && m.qualifier === "+")) {
log.warn({ domain }, "open SPF policy (+all)");
}
}
const out = await checkSpf(ip, domain, dnsResolver);
API Reference
parseSpfRecord(record): SpfMechanism[].ipv4Matches(ip, cidr): boolean.ipv6Matches(ip, cidr): boolean.checkSpf(ip, domain, resolver, depth?, lookupCount?): Promise<SpfCheckResult>.
Implementation Notes
a / mx / exists mechanisms are recognised but treated as
non-matches because resolving them requires additional DNS lookups
the caller may not want to fund — most real-world SPF records lean on
ip4: / ip6: / include: anyway. The lookupCount parameter is
exposed so callers can compose checkSpf across multiple top-level
domains in a single run without re-instantiating the budget. The
function records the SPF outcome to the OTel counter before returning,
including the permerror paths, so dashboards can distinguish "bad
record" from "no record".