Short answer: publish SPF, DKIM, and DMARC for the marketplace's sending domain, then compare the intended records with what authoritative DNS actually serves. A domain-verification TXT challenge proves that someone can cause a DNS value to appear. It does not prove that person was authorized to enroll the domain, approve a sender, or change the organization's mail policy. Treat verification as evidence of control, not an approval workflow.
| Approach | What it catches | What it cannot establish |
|---|---|---|
| One-time TXT challenge | Access to a DNS publishing path at verification time | The requester's organizational authority or later record drift |
| Periodic authoritative-record comparison | Drift between approved intent and published mail records | Whether the original approval was legitimate |
For a one-person marketplace shipping weekly, I would use the second approach alongside an explicit human approval for domain enrollment. Keep the approved record set in version control, compare it after each DNS change and on a schedule, and escalate unexpected differences. Outsource routine delivery infrastructure if that frees feature time; retain ownership of the authorization decision. A successful DNS lookup is a poor substitute for that decision.
What does domain verification actually prove about DNS control?
The verifier supplies a token and observes it at a specified DNS name. That observation supports a narrow claim: the token reached the DNS data the verifier queried. It says little about who asked for it. A contractor with temporary zone access, a compromised DNS account, or someone allowed to edit only a delegated subdomain could pass a challenge without permission to enroll the whole marketplace's mail identity. The scope of the queried name matters. For example, a request to verify market.example and a challenge under a delegated shops.market.example zone are different claims; neither tells you who approved sending account notices as the parent domain. Do not promote access to one editable record into authority over all mail streams.
Control has a scope.
Time matters too. A record visible yesterday does not prove that the person requesting a new sending configuration today still controls the zone. Conversely, DNS caches can retain an older answer until its TTL expires, so a single recursive-resolver lookup is not a clean snapshot of current authoritative publication. Record the exact queried name, answer, observation time, and authoritative nameservers when deciding whether publication matches intent.
SPF, DKIM, and DMARC answer different questions from enrollment. SPF authorizes hosts to send for the envelope domain; DKIM verifies a signature tied to a signing domain; DMARC checks alignment of those authenticated identifiers with the visible From domain and specifies a requested handling policy. Passing one of these checks does not certify that a staff member was authorized to configure the domain. RFC 7489 makes the alignment distinction explicit.
The first criterion is approved intent
For a marketplace, mail may include account notices and transaction receipts. Write down which domain each stream may use, who can approve a new sender, and who can alter the DNS zone. Those are policy decisions. The verification token is evidence collected after them. Keep an approval record separate from the TXT observation, with a domain, requested purpose, approver, and expiry or review date. Without that separation, a successful challenge can accidentally become its own permission slip.
The second criterion is drift. Store the expected SPF, DKIM selector records, and DMARC policy as an explicit set. Compare them against authoritative answers at deployment and periodically afterward. Compare parsed TXT values, not screenshots of a DNS dashboard: TXT data can be split into multiple character strings in one record, and DNS can contain multiple TXT records at a name. For SPF, RFC 7208 specifies that multiple SPF records at the same name produce a permanent error. Don't flatten an entire TXT answer set into one SPF string. A reviewer should be able to distinguish a second SPF record from another unrelated TXT value, and a changed DKIM selector from a changed key at the same selector. An exact byte-for-byte mismatch is a prompt to inspect the published records, not an automatic reason to assume a breach: some differences are formatting or planned key rotation, while others change authentication behavior. Record the reviewed reason before updating the expected set.
An initial DMARC policy of p=none can collect reports while alignment is assessed; moving to quarantine or reject is an operational decision after legitimate senders are accounted for. DMARC reports are feedback, not proof that every message reached an inbox. Delivery depends on more than authentication.
No inbox guarantee.
A small Node.js drift check
This example compares declared expectations with DNS TXT answers. It deliberately does not decide who may approve a change. Put that approval in the workflow that edits expected, then run the check in deployment and scheduled monitoring. The example uses a documentation-only domain; replace it with a domain you administer and the actual approved records.
import { Resolver } from "node:dns/promises";
const expected = new Map<string, string[]>([
["market.example", ["v=spf1 -all"]],
["_dmarc.market.example", ["v=DMARC1; p=none"]],
["mail._domainkey.market.example", ["v=DKIM1; k=rsa; p=REPLACE_WITH_APPROVED_KEY"]],
]);
const resolver = new Resolver();
resolver.setServers(["192.0.2.53"]); // Replace with an authoritative nameserver for the zone.
for (const [name, approved] of expected) {
const answers = (await resolver.resolveTxt(name))
.map((chunks) => chunks.join(""))
.sort();
if (JSON.stringify(answers) !== JSON.stringify([...approved].sort())) {
throw new Error(`Unexpected TXT records at ${name}`);
}
}
This approach has a limitation: an exact-set check flags unrelated TXT records at the same name. That is intentional for a narrowly managed mail name, but it may be too strict at a root domain that hosts other TXT records. In that case filter on the relevant protocol prefix and separately reject duplicate SPF or DMARC policy records. Resolve the zone's actual authoritative servers before configuring the resolver; the address above is a placeholder, not a public DNS service. A failed lookup is an unknown state, not evidence that a record has been removed. Retry or alert, and preserve the last successful observation. Continuous comparison also costs review time: if a separate DNS team already supplies audited change records and monitoring, another independent checker may produce duplicate alerts without improving the approval boundary. Use the one-time challenge for enrollment in that situation, and rely on the existing monitored change process for drift.
When is a one-time challenge enough?
Use a one-time challenge when the decision is genuinely limited to initial proof that a requester can publish a value at a particular name. It is the lighter choice when another process already owns approval and continuous DNS monitoring. It does not need to carry a security claim it cannot support.
If you are about to send marketplace receipts under a domain, though, a stale DKIM key, an unexpected SPF edit, or a DMARC policy change is a live operational issue. The extra check earns its maintenance cost when it protects a real sending stream. Keep alerts actionable: report the name, expected and observed values, authoritative server, and observation time. Review changes before treating them as authorized. Shipping weekly leaves little room to debug mail identity by guesswork.
Top comments (0)