Skip to content
couryo

Guides

How to set up SPF, DKIM and DMARC (with Cloudflare and registro.br)

What SPF, DKIM and DMARC are, the right record for each and the step by step on Cloudflare, registro.br and hPanel, with the most common mistakes and how to check that it works.

Updated

View as Markdown

SPF, DKIM and DMARC are three records in your domain's DNS. Together they tell email providers who may send on your behalf and what to do with anyone pretending to be you. Without them, your email is much more likely to land in spam or be refused.

The three in one sentence each#

Record Where it lives What it does
SPF TXT on the envelope domain (or subdomain) lists the servers allowed to send for that domain
DKIM TXT or CNAME at <selector>._domainkey.yourdomain publishes the key that checks each message's signature
DMARC TXT at _dmarc.yourdomain requires SPF or DKIM to be aligned with the From domain and says what to do when they are not

Alignment is the key word. DMARC passes when at least one of these holds:

  • DKIM passed and the signing domain (d=) is the From domain or a subdomain of it;
  • SPF passed and the envelope domain (the "return path") is the From domain or a subdomain of it.

SPF#

An example for a company that uses Google Workspace for its mailboxes plus a sending service:

TXT on example.com
v=spf1 include:_spf.google.com include:spf.sending-service.com ~all

Rules that save headaches:

  • One SPF record per name. Two v=spf1 records on the same domain invalidate both. Merge them into one.
  • At most 10 DNS lookups. Every include, a, mx and redirect counts, including those inside the includes. Above 10, SPF fails with permerror.
  • End with ~all or -all. Never +all: it authorizes the whole world.
  • SPF is checked on the envelope domain, not the From. Services that use a subdomain of yours as the return path (for example, bounces.example.com) take SPF there and do not need changes to your root domain's SPF.

DKIM#

The sending service generates the key and tells you which record to create. It comes in one of two forms:

TXT (the key published directly)
service1._domainkey.example.com   TXT   "v=DKIM1; k=rsa; p=MIIBIjANBgkqh..."
CNAME (the service keeps the key and can rotate it without you)
service1._domainkey.example.com   CNAME   service1.keys.sending-service.com
  • The part before ._domainkey is the selector. Each service uses its own; several can live on the same domain.
  • Prefer 2048-bit keys. Long keys in TXT sometimes need splitting into chunks of up to 255 characters; most panels do it for you.
  • Make sure the service signs with your domain (d=example.com), not only its own. Without that, DMARC does not align.

DMARC#

Start by observing:

TXT on _dmarc.example.com
v=DMARC1; p=none; rua=mailto:dmarc@example.com; adkim=r; aspf=r
Part Meaning
p=none observe and send reports only; nothing is blocked
p=quarantine failing messages go to spam
p=reject failing messages are refused
rua=mailto:... where providers send aggregate reports (daily XML)
adkim=r, aspf=r relaxed alignment: subdomains count as the same domain
pct=25 optional: applies the policy to only part of the messages, to step up slowly

Move from none to quarantine and then to reject only when the reports show that every service sending for your domain (company mailboxes, billing, CRM, your app) passes aligned. Moving too early makes legitimate email disappear.

Step by step on Cloudflare#

  1. Sign in, pick the domain and open DNS > Records.
  2. Click Add record.
  3. Choose the Type (TXT or CNAME).
  4. In Name, write only the part before the domain: @ for the root, _dmarc, service1._domainkey or bounces. Cloudflare fills in the rest.
  5. In Content (or Target, for CNAME), paste the value.
  6. For email CNAMEs, set Proxy status to "DNS only" (grey cloud). With the orange cloud, the record answers with Cloudflare's IPs and DKIM and the return path break.
  7. Save. On Cloudflare the change usually shows up within minutes.

Step by step on registro.br (.br domains)#

First, find out who answers for the domain's DNS. On registro.br, open the domain and look at its DNS servers:

  • If it uses registro.br's servers, edit the zone there: open the domain, go to DNS > Edit zone (turn on advanced mode if the panel asks) and use New entry for each record.
  • If the servers are elsewhere (Cloudflare, your host), editing on registro.br changes nothing: create the records in that other panel.

When creating the entry on registro.br:

Field Example
Name only the part before the domain: _dmarc, service1._domainkey, bounces (empty for the root)
Type TXT or CNAME
Data the record's value

Save the zone. Propagation can take from a few minutes to a few hours.

Step by step on hPanel (hosting panel)#

  1. In Domains, pick the domain and open DNS / Nameservers.
  2. In the record list, check what already exists: hosting panels often create an SPF (and sometimes a DMARC) for the host's own mailboxes.
  3. If an SPF exists, edit it and add the new include instead of creating another record. Same for DMARC: one per domain.
  4. For each new record, choose the Type, fill Name with only the part before the domain (@ for the root) and the value in Points to (CNAME) or TXT value (TXT).
  5. Save and wait for propagation.

Check that it works#

In a terminal:

Terminal
dig +short TXT example.com                    # SPF
dig +short TXT _dmarc.example.com             # DMARC
dig +short CNAME service1._domainkey.example.com

On Windows, nslookup -type=TXT _dmarc.example.com does the same. Then send an email to a Gmail account, open Show original and look for SPF: PASS, DKIM: PASS and DMARC: PASS.

Most common mistakes#

Mistake How it shows Fix
Two SPF records spf=permerror merge into one record
More than 10 SPF lookups spf=permerror remove includes you no longer use
Name with the domain repeated record at _dmarc.example.com.example.com write only _dmarc in the name field
Proxied CNAME on Cloudflare DKIM not found switch to "DNS only"
Two DMARC records DMARC ignored delete one
DKIM from the service, not your domain dkim=pass but dmarc=fail set up the custom signing domain in the service
p=reject too early billing or CRM email disappears go back to p=none, fix the services and step up again

Where Couryo fits#

With Couryo you do not touch your root domain's SPF: the envelope uses a subdomain of yours (bounces.), DKIM is published by CNAME (the key can be rotated without you touching DNS) and DMARC starts at p=none. With the domain on Cloudflare, the records are created for you. Then the deliverability agent reads the reports and tells you when it is safe to move to quarantine and reject, with the record ready. Details in Domains and DNS.

FAQ#

Do I need all three, or is one enough?#

All three. Gmail and Yahoo require SPF or DKIM from every sender, and SPF, DKIM and DMARC from senders of more than 5,000 a day; Microsoft requires all three from bulk senders. Even below that, the three together weigh the most for reaching the inbox.

Can I have more than one DKIM?#

Yes, and it is normal: each service uses a different selector (google._domainkey, service1._domainkey...). What you cannot have is more than one SPF or more than one DMARC on the same name.

How long does DNS take to propagate?#

It depends on the record's TTL and the panel. On Cloudflare it is usually minutes; elsewhere, from minutes to a few hours. If the record still does not show in dig after a day, check that you edited the right panel (the one for the domain's DNS servers).

What goes in DMARC's rua?#

An address that receives the providers' daily XML reports. Since they are hard to read by hand, the usual choice is a service that collects and explains them.

SPF with ~all or -all?#

Both work. With DMARC in place, DMARC makes the final call, so ~all is the safer choice while you have not checked every service that sends for the domain.