← blog

authentication · 13 Sept 2026 · 5 min read

How to set up SPF, DKIM and DMARC for a sending domain, step by step

Four DNS records, published in a specific order, turn a domain from "anyone can send as this" into one that receivers can verify. Here is what each record contains, where it goes, and how to confirm it worked before you send anything real.

Publish SPF as a TXT record on the sending domain listing the servers allowed to send for it, publish the DKIM public key at selector._domainkey as the CNAME or TXT your provider gives you, then publish DMARC at _dmarc as a TXT record starting at p=none with a reporting address. Send one message and read its Authentication-Results header before sending anything real.

Three gates in a row; the first two stand open, the third is closed and lit amber.

A domain with no authentication records is a domain anyone can send as. Receivers know that, which is why unauthenticated mail from a new domain starts out competing with phishing rather than being judged on its own merits. Fixing it is four DNS records. The work is not hard, but the order matters and so does checking the result, because a record that is almost right fails exactly like one that is missing.

This is the whole procedure, from an empty zone to a message that passes all three checks.

Before you start: pick the domain you will send from

Decide this first, because every record below is published on it.

Send from a subdomain rather than the root: mail.yourapp.com, notify.yourapp.com, something that names the job. Three reasons:

  • The subdomain gets its own SPF record and its own lookup budget, so adding a sending service never collides with the office mail provider’s record on the root.
  • Reputation is tracked per domain. If the application’s mail ever has a bad month, the address your customers write to is unaffected.
  • DMARC in its default relaxed mode treats mail.yourapp.com as aligned with yourapp.com, so you lose nothing on alignment by doing this.

The From address on your mail will be something@mail.yourapp.com. If you want replies to land somewhere human, set Reply-To rather than sending from the root.

Step 1: SPF

SPF is a TXT record on the sending domain listing which servers may send mail for it. It authenticates the envelope sender, the Return-Path, which is not the address a recipient sees. That distinction becomes important in step 3.

mail.yourapp.com.   TXT   "v=spf1 include:_spf.your-provider.example -all"

Your provider tells you the include: value. Two rules:

One record per domain. Two TXT records both starting v=spf1 is a permanent error, and a permanent error counts as a failure. If a record already exists, add the include to it rather than publishing a second one.

End with -all. The ~all softfail was reasonable while you were still finding your sending sources. Once you know them, -all says “and nothing else”, which is the statement receivers want.

Check it:

$ dig TXT mail.yourapp.com +short
"v=spf1 include:_spf.your-provider.example -all"

SPF has a limit of ten DNS lookups per evaluation, and every include: spends one or more of them. A dedicated sending subdomain almost never gets near it, which is another argument for step zero.

Step 2: DKIM

DKIM signs each outgoing message with a private key the sender holds, and publishes the public key in DNS so a receiver can verify the signature. The record lives under a selector, which is just a name that lets one domain hold several keys:

selector._domainkey.mail.yourapp.com.   CNAME   selector.dkim.your-provider.example.

Most providers hand you a CNAME rather than the key itself. Publish it as given. The CNAME means the provider can rotate the key later without asking you to touch DNS, which is what you want.

If yours gives you a TXT record with the key inline instead, publish that. Either way, the check is the same:

$ dig TXT selector._domainkey.mail.yourapp.com +short
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."

You should see v=DKIM1 and a p= value. If you see a CNAME target and nothing else, the provider’s side is not yet published, and the fix is on their end.

Use a 2048-bit key. Receivers stopped trusting 1024-bit signatures years ago, and a provider still issuing them is telling you something.

Step 3: DMARC

DMARC is what ties the first two to the address the recipient actually sees. Without it, a receiver has no way to know that your domain expects to be authenticated, and no policy to apply when it is not.

_dmarc.mail.yourapp.com.   TXT   "v=DMARC1; p=none; rua=mailto:dmarc@yourapp.com"

Start at p=none. This publishes no enforcement, but it turns on aggregate reporting, and the reports are the point. Within a day or two you will receive XML summaries from every major receiver listing each source that sent mail as your domain, and whether it passed. That inventory is how you find out about the marketing tool someone connected in 2023.

One thing many setup guides get wrong: DMARC does not check that SPF and DKIM pass. It checks that at least one of them passes and aligns, meaning the domain it authenticated matches the From domain. A provider that signs with its own domain and bounces to its own domain gives you two green ticks and a DMARC failure. Alignment is the check to look at, and it is the one this whole procedure exists to satisfy.

Once the reports show your legitimate mail aligning cleanly, move to p=quarantine and then p=reject. Until then the domain is documented but not protected.

Step 4: the record nobody lists

If your provider offers a custom return-path or bounce domain, set it up. This is a CNAME like:

bounce.mail.yourapp.com.   CNAME   bounce.your-provider.example.

It puts the Return-Path on your domain instead of the provider’s, which is what makes SPF align rather than merely pass. With DKIM aligned you would pass DMARC anyway, but a message that survives on both is a message where one can break, in a forward or a rewrite, without the whole thing failing.

Step 5: send one message and read the headers

Do not trust the provider’s green tick. Send a message to an address you control at a large receiver, open the raw source, and find Authentication-Results:

Authentication-Results: mx.google.com;
  spf=pass   smtp.mailfrom=bounce.mail.yourapp.com;
  dkim=pass  header.i=@mail.yourapp.com;
  dmarc=pass (p=NONE) header.from=mail.yourapp.com

Three verdicts. If dmarc says anything other than pass, look at which of the two domains above it does not match header.from, and fix that one. The password reset post walks through reading a failing example line by line.

Keeping it true

DNS records do not stay correct on their own. A key gets rotated, a DNS clean-up drops a record that looked unused, a provider migration leaves an old include behind. Re-check the four records on a schedule, and read the DMARC reports when they arrive rather than filtering them into a folder.

Where Pharos fits

Pharos asks for the four records above when you add a sending domain: SPF, DKIM, DMARC and an aligned return path. It verifies every one before the domain can send, and re-checks them daily afterwards. The return path is on your domain, so SPF aligns as well as DKIM. A domain whose records stop verifying stops sending rather than sending unsigned, and you can confirm all of it from the headers of your first message.

Questions this raises

Should I send from my root domain or a subdomain?

A subdomain, such as mail.yourapp.com or notify.yourapp.com. It keeps the application's sending reputation separate from the domain people email you at, it gives the subdomain its own SPF record and lookup budget, and DMARC in relaxed mode still treats it as aligned with the organisational domain.

How long do the records take to work?

As long as your DNS TTL, usually minutes to an hour. A provider that verifies records for you may cache a failed lookup for longer, so if a record checks out with dig but the provider still shows it as pending, wait rather than editing it again.

Do I need all three, or is DKIM enough?

All three. DKIM is the strongest single check, but DMARC is what tells a receiver that your domain expects authentication at all, and SPF is what keeps a forwarding failure from also being a DMARC failure. Receivers who publish requirements ask for all three.

Sources

Written by the Pharos team · 13 Sept 2026 rss

Check your own headers first.

If authentication is failing, Pharos fixes it as a side effect of onboarding a domain. Free plan, 3,000 emails a month.

start free