How to Set Up SPF, DKIM and DMARC: A Guide With Real Tests (2026)

How to Set Up SPF, DKIM and DMARC: A Guide With Real Tests (2026)

Setting up SPF, DKIM and DMARC is no longer a nice extra. If you want your mail to arrive, it is mandatory. These three DNS records tell every mail server in the world which servers may send on your behalf (SPF), that a message was not altered in transit (DKIM), and what should happen to mail that fails both checks (DMARC). Miss one of them and your messages quickly land in spam at Gmail, Outlook and Yahoo, or get rejected outright. On top of that, anyone can forge mail with your sender address.

The good news: all three are just TXT records in DNS. You don’t need your own mail server, no expensive software, and usually less than half an hour. The bad news: the syntax is strict, and many mistakes go unnoticed because the mail still gets delivered somehow.

For this article we measured instead of copying. On 11 November 2026, from our production server (Hetzner, Ubuntu 24.04), we queried the records of 13 domains, including our own and those of big providers, ran SPF evaluations with a test library, and sent a real test email through our mail provider. Then we tampered with its DKIM signature on purpose. Three findings up front:

1. A single extra space in the body of a message breaks the DKIM signature. A changed date does not, because our provider doesn’t sign the Date header at all.

2. github.com’s SPF record needs exactly 10 DNS lookups to evaluate, the permitted maximum. One more include: and the check ends in an error instead of “pass”.

3. Two of our own domains have neither SPF nor DMARC. A forgery using their address doesn’t get “fail” from SPF, it gets “none”. For a spam filter that’s no reason to reject anything.

If you’re not yet comfortable with DNS record types, read What is DNS? first. And how mail finds its way to you in the first place is covered in What is an MX record?. This article is about the other direction: your outgoing mail.

A glowing envelope on a device, flanked on the left and right by two protective shields

SPF, DKIM and DMARC: what does each record do?

Before we set anything up, let’s get the picture straight. Email is a protocol from the 1980s, and back then nobody thought about forgery. Whoever runs a mail server can write anything into the sender field: ceo@yourcompany.com, service@paypal.com, whatever. SMTP doesn’t check. The three standards plug that hole, each at a different point.

StandardQuestion it answersWhere it livesWhat gets checked
SPFIs this server allowed to send for the domain?TXT on the domain itselfIP of the delivering server against a list
DKIMDid the mail really come from the domain, unchanged?TXT on selector._domainkey.domainCryptographic signature in the header
DMARCWhat to do if SPF and DKIM don’t match? Who gets reports?TXT on _dmarc.domainWhether SPF or DKIM passed and matches the visible sender domain

An analogy that helped us: SPF is the guest list at the door. If the delivering server is on it, it gets in. DKIM is the wax seal on the letter. Break it and the damage shows. DMARC is the house rules telling the bouncer what to do with guests who have neither, and it writes the owner a report every morning.

None of them is enough on its own. SPF only checks the technical sender address on the envelope (the envelope from or Return-Path), not the address your recipient sees in their mail client. DKIM only proves that some domain signed the message, not the one in From:. Only DMARC ties both to the visible sender address. That’s called alignment, and we’ll get to it shortly.

Why this stopped being optional in 2024

Since February 2024, Google and Yahoo require anyone sending more than 5,000 messages a day to their users to have SPF and DKIM and at least a DMARC record with p=none. Microsoft followed for Outlook.com, Hotmail and Live in May 2025. Smaller senders face fewer formal rules, but in practice almost the same: mail without SPF or DKIM goes to spam far more often. If you run a newsletter, a shop or a contact form, there’s no way around it.

What we measured: 13 domains compared

Before you write your own record, it’s worth looking at how others do it. On 11 November 2026 we queried the SPF and DMARC records with dig and used the Python library pyspf to count how many DNS lookups a full SPF evaluation triggers:

DomainSPF ends withSPF DNS lookupsDMARC policy
getmind.io (us)~all2p=none
tacilytics.com (us)-all2p=quarantine
heynyx.dev (us)no SPF0no DMARC
gmail.comvia redirect1p=none, sp=quarantine
outlook.com-all1p=none, sp=quarantine
web.devia redirect6p=quarantine
gmx.netvia redirect6p=quarantine
t-online.de~all0p=none
posteo.de~all0p=none
mailbox.org~all1p=reject
proton.me~all2p=quarantine
paypal.com~all9p=reject
github.com~all10p=quarantine, sp=reject

Three things stand out. First: even the giants aren’t all on p=reject. Gmail and Outlook protect their main domain with just p=none (“monitor only”) and their subdomains with quarantine. For free mail that makes sense: millions of people send through mailing lists and third-party services with @gmail.com as the sender, and a strict policy would break huge amounts of legitimate mail.

Second: PayPal and mailbox.org, the ones whose addresses get forged most often or who sell security as a product, are on p=reject. A forgery is turned away there before it reaches any inbox.

Third: the number of DNS lookups ranges from 0 to 10. And 10 isn’t random. It’s the limit in the SPF standard (RFC 7208). More on that below.

How to set up SPF, step by step

An opened metal gate in neon light with several envelopes attached to it, like a guest list at an entrance

SPF stands for Sender Policy Framework. You publish a TXT record on your domain that starts with v=spf1 and lists the permitted senders. A recipient receiving mail from someone@yourdomain.com checks whether the IP of the delivering server is on that list.

Step 1: Find out who sends on your behalf

This is the most important and most underestimated step. Typical senders for an ordinary business domain:

  • your mail provider (Google Workspace, Microsoft 365, Fastmail, Proton, your own server)
  • your shop or CMS if it sends order confirmations or password resets
  • your newsletter service (Mailchimp, Brevo, Kit, MailerLite)
  • ticketing, CRM, invoicing tools (Zendesk, HubSpot, QuickBooks, Stripe)
  • contact forms on your web server

Forget one and exactly that one’s mail fails. Write the full list before you publish anything. Ours is short: all mail from getmind.io goes through our mail provider, including mail generated by our own server. The server logs in with username and password (authenticated submission on port 587) and lets the provider deliver.

Step 2: Build the record

The building blocks:

MechanismMeaningExample
v=spf1Required, always firstv=spf1
ip4: / ip6:Fixed IP or networkip4:203.0.113.10, ip6:2001:db8::/32
a / a:hostThe A records of the domain or a hosta:mail.example.com
mxThe servers from the MX recordmx
include:Pull in a provider’s SPF listinclude:_spf.google.com
redirect=Hand off completely to another SPF recordredirect=_spf.example.net
-allEverything else: reject (fail)
~allEverything else: suspicious (softfail)
?allEverything else: no statement (neutral)

For common providers it looks like this:

# Google Workspace only
example.com.  TXT  "v=spf1 include:_spf.google.com ~all"

# Microsoft 365 only
example.com.  TXT  "v=spf1 include:spf.protection.outlook.com -all"

# Google Workspace + newsletter service + your own web server
example.com.  TXT  "v=spf1 include:_spf.google.com include:spf.brevo.com ip4:203.0.113.10 ~all"

Our own record is v=spf1 a:ff-web.de mx ~all. Translated: the server behind ff-web.de is allowed, and so is everything in the MX record. Everything else is suspicious.

Step 3: Publish exactly one record

A domain may have only one SPF record. Adding a second TXT record with v=spf1 for each new service causes a permerror, and then SPF counts as broken for every sender. New services always go into the existing record as another include:.

You create the record at your DNS provider as a TXT on the domain itself (name @ or blank). You can check it right away:

$ dig +short TXT getmind.io | grep spf
"v=spf1 a:ff-web.de mx ~all"

What happens with typos? We tried it

Using pyspf, we evaluated several records against a foreign IP (one from the documentation range that’s guaranteed not to be on any list):

RecordResult
v=spf1 ip4:203.0.113.0/24 ~al (typo)permerror
v=spf1 include:doesnotexist-xyz-4711.example ~allpermerror
v=spf1 ip4:198.51.100.1 (no all)neutral
v=spf1 +allpass for every IP on earth

The typo ~al instead of ~all invalidates the whole record. So does an include: pointing at a domain that doesn’t exist (anymore). This happens more often than you’d think: you cancel a newsletter service, at some point it deletes its SPF record, and your old include: is still there. And +all is the most dangerous record of all, because it explicitly allows every server in the world to send as you. It tends to show up as a supposed “fix” when something didn’t arrive. That isn’t a fix, it’s an open barn door.

The 10-lookup limit

Every include:, a, mx, exists: and redirect= costs the receiver one DNS lookup, and includes can contain further includes. The standard allows at most 10 such lookups. After that the result is permerror.

github.com shows how tight this gets in practice: their record pulls in Microsoft, Google (twice), Zendesk, Salesforce, Mailchimp, Marketo and SendGrid, and lands at exactly 10 lookups. As a test we built a record that includes GitHub’s list plus Google Workspace. Result:

('permerror', 550, 'SPF Permanent Error: Too many DNS lookups')  # 11 lookups

What helps once you hit the limit:

  1. Clean up. Remove services you no longer use. That almost always gains the most.
  2. Drop mx and a if those servers are already covered by an include.
  3. Use subdomains. Newsletters from news.example.com, invoices from billing.example.com. Each subdomain has its own limit.
  4. Fixed IPs instead of includes, but only if the provider guarantees they won’t change. Otherwise things will quietly fall apart one day.

~all or -all?

The honest answer: combined with DMARC, the difference is smaller than forum debates suggest, because DMARC decides what actually happens. We still recommend starting with ~all as long as you’re not sure your sender list is complete. Once your DMARC reports show no unknown legitimate senders for a few weeks, switch to -all. Our newer domains (tacilytics.com and one more) have had that from day one, because only a single server ever sends from them. getmind.io is still on ~all, and switching it is on our list.

One trap you should know: SPF breaks on forwarding. When a recipient forwards mail from old@company.com to Gmail, it’s now company.com’s server delivering the message to Gmail, and that server isn’t in your SPF. That’s exactly why you need DKIM: the signature travels with the message and survives forwarding as long as nobody alters the content.

How to set up DKIM: a signature on every message

A white envelope with a golden key on it, surrounded by violet light

DKIM stands for DomainKeys Identified Mail. Your mail server signs every outgoing message with a private key. You publish the matching public key in DNS. The recipient fetches it, verifies the signature and then knows two things: the message was signed by someone holding the domain’s key, and it hasn’t been changed since.

Step 1: Have a key generated

With Google Workspace, Microsoft 365 and almost every hosting provider, you generate the key in the admin console with one click. The provider then shows you the DNS record to create. With Microsoft 365 it’s two CNAME records (selector1._domainkey and selector2._domainkey) pointing at Microsoft’s own keys. The advantage: Microsoft can rotate keys without you touching your DNS. You can see that exact pattern on outlook.com itself: the selector is a CNAME to outbound.protection.outlook.com.

If you run your own mail server with Postfix, OpenDKIM usually handles this:

# Generate a key (2048 bit, selector "mail")
opendkim-genkey -b 2048 -d example.com -s mail -D /etc/opendkim/keys/example.com/

# mail.txt contains the ready-made DNS record
cat /etc/opendkim/keys/example.com/mail.txt

For OpenDKIM to actually sign the domain, it must appear in both the KeyTable and the SigningTable. Sounds trivial, but this is exactly where we tripped ourselves: our mail provider uses an admin panel that doesn’t automatically write new domains into those two files. The DNS record existed, mail went out, nothing got signed. We only noticed because we looked at a test message’s headers. Our rule since then: After setup, always send a test message and look for the DKIM-Signature header.

Step 2: Publish the public key in DNS

The record doesn’t live on the domain itself but on selector._domainkey.yourdomain. The selector is a name you choose freely, letting you run several keys in parallel. Ours is simply called default:

$ dig +short TXT default._domainkey.getmind.io
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..." "...IDAQAB"

Two details from our measurement that many guides skip:

  • Key length. getmind.io’s key is 2048 bits, the keys of two newer domains of ours only 1024 bits, even though all three are with the same provider. The panel evidently picked a shorter default for newer domains. 1024 bits is still accepted by all major receivers but is on its way out. If you’re setting up fresh, use 2048.
  • Record length. A 2048-bit record is 410 characters long for us. But a single string inside a TXT record may hold at most 255 characters. That’s why the key sits in DNS as two strings that the receiver concatenates. Many DNS interfaces split it automatically, some don’t. If yours throws an error or truncates the key, that’s why.

Step 3: Test it, properly

We sent a test message to ourselves through our provider and looked at the header:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=getmind.io;
    s=default; t=1794384428; bh=jyFIZOmU9cBrJGS/...; h=From:To:Subject;
    b=LZUiMBgDRom6Rn4FrZwX5npto7MIRei7...

The important fields: d=getmind.io is the signing domain, s=default the selector, bh= a hash of the body, h= the list of signed header fields, and c=relaxed/simple how headers and body are normalised before hashing.

Then we verified the received message with the Python library dkimpy and altered it on purpose:

Change to the messageDKIM result
Original valid
One character in the body changed (. → !) invalid
One extra space in the body invalid
Subject changed (Auth → AUTH) invalid
Blank lines appended at the end valid
Date: field renamed valid

The space result follows from c=relaxed/simple: the second part, simple, applies to the body and forgives almost nothing there, only trailing blank lines. With relaxed/relaxed the double space wouldn’t have broken the signature. That’s why some mailing lists and virus scanners that append footers or rewrap lines destroy DKIM signatures.

The second result honestly surprised us: our provider only signs From, To and Subject. Date, Message-ID and every other field are unprotected. That’s allowed (only From is required), but weak: someone who intercepts a signed message can resend it with a new date and the signature stays valid. On your own servers it’s worth extending the list of signed fields in OpenDKIM (SignHeaders or OversignHeaders).

Another pitfall from the same test: because sender and recipient were on the same server, it added no Authentication-Results header. If you rely only on that header, testing against yourself shows nothing. For a meaningful test, send the message to a mailbox at a big provider (Gmail, for example) and use “Show original” to look for dkim=pass, spf=pass and dmarc=pass.

Rotating keys

DKIM keys shouldn’t live forever. Once a year is a sensible rhythm. The trick is the selector: create a new key with a new selector (say 2026a), publish it in DNS, switch the server over, and leave the old record in place for a few days so messages still in transit remain verifiable. Then delete it.

How to set up DMARC: the policy and the reports

Isometric scene with a control tower directing green, yellow and red envelopes onto different paths

DMARC (Domain-based Message Authentication, Reporting and Conformance) is the piece that makes SPF and DKIM effective in the first place. It does three things:

  1. It requires SPF or DKIM to pass and the checked domain to match the visible From: address (alignment).
  2. It tells the receiver what to do with mail that fails: nothing (none), spam folder (quarantine) or reject (reject).
  3. It has reports sent to you about everyone sending mail in your name.

Understanding alignment

This is where most setups fail. An example: your newsletter service sends your mail with From: news@example.com, but with the technical sender address bounce@mail.newsletterservice.com, signed with d=newsletterservice.com. SPF passes (for newsletterservice.com), DKIM passes (for newsletterservice.com). DMARC still fails, because neither domain matches example.com.

The fix is almost always the same: set up your own sending domain in the service (usually called “authenticate your domain”) so it signs with d=example.com. You create the CNAME or TXT records the service shows you.

Our test message had everything lined up: From: thenyx@getmind.io, technical sender (Return-Path) also getmind.io, DKIM with d=getmind.io. So either check alone would have satisfied DMARC.

There are two strictness levels: adkim=r / aspf=r (relaxed, the default) also accepts subdomains, so mail.example.com matches example.com. adkim=s / aspf=s (strict) requires the exact same domain. Posteo and Proton run strict; relaxed is fine for most businesses.

Step 1: Start with p=none

Create a TXT record on _dmarc.yourdomain:

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

p=none changes nothing about delivery. But from now on Gmail, Microsoft, Yahoo and many others send a daily aggregate report to the address in rua=: an XML file, usually zipped, listing every IP that sent mail with your domain in the last 24 hours, and whether SPF and DKIM matched. That’s exactly how getmind.io is set up: p=none with reports to a dedicated mailbox.

A practical tip: use a dedicated mailbox or alias for rua=. An active domain gets several reports a day, and you don’t want them burying your normal inbox. If the address lives on a different domain, that domain has to permit it explicitly (with a record example.com._report._dmarc.otherdomain.com), otherwise many receivers silently drop the reports.

Step 2: Read the reports

Isometric analytics dashboard with bar charts, donut charts, a magnifying glass and an envelope icon

The XML reports are hard for humans to read. There are free parsers (parsedmarc, for instance, as an open-source tool you can self-host) and commercial services with free starter plans. What you’re looking for:

  • Unknown but legitimate senders: the CRM nobody mentioned, the old contact form. Add them to SPF or set up DKIM for them.
  • Senders with DKIM failures: often forwarders or mailing lists that alter content. You can usually ignore those.
  • Foreign IPs forging your domain: those are what the next step is aimed at.

Plan two to four weeks for this phase. For small domains with a single mail provider, one week is often enough.

Step 3: Tighten step by step

# Phase 2: forgeries to spam, only a quarter of them at first
_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@example.com"

# Phase 3: all to spam
_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"

# Goal: reject
_dmarc.example.com.  TXT  "v=DMARC1; p=reject; rua=mailto:dmarc@example.com"

pct= is a tool for the transition period, but some receivers only roughly honour it and it’s contested in the revision of the standard. Don’t rely on it; read the reports instead.

With sp= you set a separate policy for subdomains. That matters because attackers like to dodge onto subdomains that don’t even exist (billing.example.com). Gmail, Outlook and GitHub do exactly this on purpose: the main domain is more lenient than its subdomains.

The tags at a glance

TagMeaningExample
v=DMARC1Required, first
p=Policy for the domainnone, quarantine, reject
sp=Policy for subdomainssp=reject
rua=Address for aggregate reportsrua=mailto:dmarc@example.com
ruf=Address for forensic reports (rarely supported, mind privacy)
adkim= / aspf=Alignment relaxed or strictadkim=s
pct=Percentage the policy applies topct=25
fo=When forensic reports are sentfo=1

A clear word on ruf=: forensic reports can contain parts of real messages, including recipient addresses. In the EU that’s a GDPR headache, and most large providers don’t send them at all. We recommend leaving ruf= out.

Domains that send no mail at all

Almost everyone forgets this part, and we forgot it for our own domains too. heynyx.dev and nyx.fish send no mail. Yet anyone can create a message from sender@heynyx.dev. Our SPF test for an arbitrary foreign IP:

203.0.113.9  heynyx.dev      ('none', '')
203.0.113.9  tacilytics.com  ('fail', 'SPF fail - not authorized')

“none” means: the domain has no opinion. No spam filter rejects mail because of it. “fail” on tacilytics.com means: this IP is explicitly not allowed. For domains that send no mail, three records are enough to make forgery practically impossible:

example.com.         TXT  "v=spf1 -all"
_dmarc.example.com.  TXT  "v=DMARC1; p=reject;"
*._domainkey.example.com.  TXT  "v=DKIM1; p="

The first says “nobody may send”, the second “reject everything”, the third (optional) declares all DKIM keys revoked. Pair it with a null MX if the domain shouldn’t receive anything either. We tested that in depth in our MX record article. Doing exactly this for our two domains is on our list.

The most common mistakes when setting up SPF, DKIM and DMARC

From our measurements and our own stumbles:

  1. Two SPF records on the same domain. Result: permerror, SPF useless. Always merge into one.
  2. Typos at the end (~al, -al, all without a qualifier). We measured it: ~al invalidates the entire record.
  3. More than 10 DNS lookups. No error when you create it, but permerror at the receiver. Recount regularly, especially after adding services.
  4. +all as a supposed fix. Lets every server on earth send as you.
  5. DKIM in DNS but not active on the server. Happened to us. Send a test message, read the headers.
  6. Truncated DKIM key, because the DNS interface can’t handle strings over 255 characters.
  7. Newsletter service without its own domain authentication. SPF and DKIM pass, DMARC still fails.
  8. Starting straight with p=reject. Legitimate mail you never knew about will fail. Always start with p=none and reports.
  9. Staying on p=none forever. The most common mistake of all. none protects nobody; it only watches.
  10. Leaving non-sending domains unprotected. They’re especially attractive to forgers, because nobody notices odd reports there.
  11. Your own server delivering directly instead of through the provider. Our VPS isn’t in our SPF record. If it delivered directly, every receiver would give it softfail. We checked: the provider’s IP evaluates to pass, our own server’s IP to softfail. That’s why every script of ours sends through the provider, logging in on port 587.

Checklist: set up SPF, DKIM and DMARC in 30 minutes

  1. List every service that sends mail with your domain.
  2. SPF: create one TXT record v=spf1 … ~all on the domain, with every service as include: or ip4:. One record only!
  3. Count the DNS lookups (with an SPF checker) and stay under 10.
  4. DKIM: enable it at your mail provider and every service, create the records on selector._domainkey, choose 2048 bits.
  5. Send a test message to a Gmail mailbox, “Show original”, check spf=pass and dkim=pass with your domain.
  6. DMARC: create v=DMARC1; p=none; rua=mailto:… on _dmarc.
  7. Read reports for two to four weeks, add missing senders.
  8. Move to p=quarantine, then to p=reject. SPF to -all.
  9. Lock down non-sending domains with v=spf1 -all and p=reject.
  10. Once a year: rotate DKIM keys, tidy up the SPF list.

If you run your own mail server on a VPS, this belongs to the basic setup, just like firewall and updates. More on that in Linux server setup. And if you need HTTPS and certificates for the mail server: Create an SSL certificate.

FAQ: common questions about SPF, DKIM and DMARC

Do I need all three, or is SPF enough?

You need all three. SPF alone breaks on forwarding and doesn’t check the visible sender address. DKIM alone doesn’t say what should happen on failure. Only DMARC connects both to the From: your recipient sees. Google, Yahoo and Microsoft explicitly require all three from larger senders.

How long does it take for SPF, DKIM and DMARC to take effect?

As long as the record’s TTL and the receivers’ caches take. For a brand-new record that didn’t exist before, usually a few minutes. For a change to an existing record, up to the old TTL, typically 5 minutes to 1 hour, rarely longer.

Can I set up SPF, DKIM and DMARC without my own mail server?

Yes, that’s actually the normal case. All you need is access to your domain’s DNS. Your mail provider generates the DKIM keys; you just copy the record.

What does “SPF softfail” in the header mean?

The delivering server isn’t on your list, and your record ends in ~all. The message usually still gets delivered but marked as suspicious. If you see it on your own legitimate mail, a sender is missing from your SPF record.

What is a DKIM selector?

A freely chosen name in front of ._domainkey under which the public key lives. It appears in every signature as s=. With several selectors you can run several services, or an old and a new key, at the same time.

Which DMARC policy should I use?

Start with p=none plus rua= to collect reports. After two to four weeks move to p=quarantine, then p=reject. If you stay on none, you have a record but no protection.

Why does my mail land in spam despite SPF, DKIM and DMARC?

Because authentication is the ticket in, not a guarantee. Spam filters also weigh your IP and domain reputation, complaint rate, content, links, missing unsubscribe links on newsletters, and whether the IP has a matching reverse DNS (PTR) record. Once all three checks show “pass”, that’s where to keep looking.

Does DKIM still work after forwarding?

Usually yes, as long as the forwarding server doesn’t change the content. SPF, on the other hand, almost always breaks on forwarding. Mailing lists that append footers or change the subject destroy DKIM too. We measured it: changing one letter in the subject is enough.

How do I check whether my records are correct?

With dig +short TXT yourdomain.com, dig +short TXT _dmarc.yourdomain.com and dig +short TXT selector._domainkey.yourdomain.com. Additionally, send a test message to a Gmail mailbox and check “Show original”. Online checkers will also count your SPF lookups.

Is 1024-bit DKIM still secure?

Still accepted for the next few years, but no longer recommended. New keys should be 2048 bits. Our provider chose 2048 bits for an older domain and 1024 for newer ones, so it pays to check instead of assuming.

What is BIMI?

BIMI shows your logo next to the message in the inbox, but only if DMARC is on quarantine or reject. For most small businesses that’s a later step. Get SPF, DKIM and DMARC clean first, then think about BIMI.

Conclusion: setting it up is easy, following through is what counts

Setting up SPF, DKIM and DMARC takes half an hour and three TXT records. The hard part is something else: a complete list of senders, keeping an eye on the 10-lookup limit, and above all not getting stuck on p=none. Our own measurements kept us honest on exactly those points. getmind.io is still on ~all and p=none, two of our domains have no protection at all, and our provider signs fewer headers than we assumed. None of that would ever have produced an error message. You only notice if you look.

Our advice: check SPF and DKIM today, send a test message to Gmail, add DMARC with p=none and reports. And put a reminder in your calendar three weeks out to switch to quarantine.