# SPF, DKIM and DMARC records

The three DNS records from Step 3. Add all three before you send a single cold
email. Missing authentication is the most common reason a technically perfect
sequence lands in spam.

Replace `yourdomain.com` and the placeholder values. Records go in your DNS
provider as TXT records.

---

## 1. SPF

Declares which servers may send mail as your domain. **One SPF record per
domain, ever.** If you already have one, merge the includes into it rather than
adding a second.

```
Host:  @
Type:  TXT
Value: v=spf1 include:_spf.google.com include:sendgrid.net ~all
```

| Sender | include to add |
|---|---|
| Google Workspace | `include:_spf.google.com` |
| Microsoft 365 | `include:spf.protection.outlook.com` |
| SendGrid | `include:sendgrid.net` |
| Postmark | `include:spf.mtasv.net` |
| Mailgun | `include:mailgun.org` |
| Amazon SES | `include:amazonses.com` |

End with `~all` (softfail) while you are testing, `-all` (hardfail) once you are
certain the list is complete. Never `+all`.

**The ten-lookup limit.** SPF allows ten DNS lookups. Each `include:` costs at
least one. Five senders is usually where domains start failing silently, so
check with an SPF validator after every change.

## 2. DKIM

Signs each message so the receiver can prove it was not altered. The public key
comes from your sending provider; the selector is the part before `._domainkey`.

```
Host:  crmsolid._domainkey
Type:  TXT
Value: v=DKIM1; k=rsa; p=[PASTE THE PUBLIC KEY FROM YOUR PROVIDER]
```

Each sending service gets its own selector, so multiple DKIM records are normal
and correct, unlike SPF.

## 3. DMARC

Tells receivers what to do when SPF or DKIM fails, and where to send reports.

**Start here** and leave it for at least seven days:

```
Host:  _dmarc
Type:  TXT
Value: v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com; fo=1; pct=100
```

`p=none` changes nothing about delivery. It only collects reports, which is
exactly what you want before tightening.

**After 7 clean days**, move to quarantine:

```
v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com; fo=1; pct=100
```

**After 30 clean days**, reject:

```
v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com; fo=1; pct=100
```

Going straight to `p=reject` will silently kill mail from any sender you forgot
to authorise, including your invoicing tool and your helpdesk. Do not skip the
ramp.

---

## Verify before you send

| Check | How |
|---|---|
| SPF resolves and is under ten lookups | Any SPF validator |
| DKIM signature passes | Send to a checker, look for `dkim=pass` |
| DMARC record parses | Any DMARC validator |
| Full-message score | mail-tester.com, target 9.5 or higher |
| Real inbox placement | Send to 50 seed addresses across Gmail, Outlook, Yahoo, Apple |

## Then warm the domain

A brand-new domain sending 200 messages on day one lands in spam whatever the
DNS says. Start at 10 to 20 a day and increase about 20% daily for two weeks,
mixing warm replies in with cold sends.
