Skip to content
Approvalens

Guides · 9 min read

SPF, DKIM and DMARC Explained for Small Site Owners

Contact form or newsletter mail landing in spam? SPF, DKIM and DMARC in plain words, Gmail and Yahoo's sender rules, one SPF record, and a safe DMARC rollout.

By the Approvalens team

When the messages from your contact form or newsletter land in spam, the receiving server usually couldn't confirm that the mail really came from your domain. Three DNS records let it check. SPF lists the servers allowed to send mail for your domain. DKIM adds a signature that proves the message wasn't forged or changed. DMARC ties both to the address people see in the From line and tells receivers what to do when the checks fail. Gmail has required at least SPF or DKIM from every sender since February 2024, and all three from bulk senders. A small site should set up all three anyway; it's an hour of work once.

SPF, DKIM and DMARC in plain words

SPF is a TXT record on your domain that lists who may send mail for it. A receiving server looks at the IP that delivered the message, looks up the SPF record of the sending domain, and checks whether that IP is on the list.

example.com.  TXT  "v=spf1 include:_spf.google.com include:spf.host.example.com ~all"

DKIM is a signature. Your mail provider signs each outgoing message with a private key and you publish the matching public key in DNS, under a name like s1._domainkey.example.com. The receiver fetches the key and checks the signature. If someone changed the message on the way, or forged it from elsewhere, the signature doesn't match.

DMARC is the policy on top. Google's sender guidelines put it simply: "DMARC tells receiving servers what to do with your messages that don't pass SPF or DKIM." It also adds the rule that makes forging hard: "The authenticating domain must be the same domain that appears in the message From: header" (Email sender guidelines). That's called alignment. SPF or DKIM passing for some other domain doesn't count.

_dmarc.example.com.  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@example.com"
How a receiving mail server checks a message from hello@example.com: SPF looks up the TXT record of the envelope domain and checks that the sending IP 203.0.113.25 is listed; DKIM fetches the public key at s1._domainkey.example.com and verifies the signature with d=example.com; DMARC checks that at least one of them passed for the same domain as the From address and then applies the policy p=none, quarantine or reject; the result is inbox, spam folder or rejection
SPF and DKIM each answer "is this sender allowed?". DMARC asks whether either answer is about the domain in the From line.

What Gmail and Yahoo require since 2024

Google's Email sender guidelines say: "Starting February 1, 2024, all email senders who send email to Gmail accounts must meet the requirements in this section." For everyone, the first requirement is "Set up SPF or DKIM email authentication for your sending domains", along with valid forward and reverse DNS for the sending IP, TLS, and a spam rate below 0.3%.

Bulk senders need more: "Set up SPF and DKIM email authentication for your domain" and "Set up DMARC email authentication for your sending domain. Your DMARC enforcement policy can be set to none." Marketing mail also needs one-click unsubscribe. Google's sender FAQ defines a bulk sender as one "that sends close to 5,000 messages or more to personal Gmail accounts within a 24-hour period", and adds that "Starting November 2025, Gmail is ramping up its enforcement on non-compliant traffic", with "temporary and permanent rejections".

Yahoo's sender best practices match: "Implement SPF or DKIM at a minimum" for everyone, and for bulk senders both, plus "Publish a valid DMARC policy with at least p=none".

A small blog's newsletter isn't near 5,000 a day. Set up all three anyway. Google itself recommends "always set up SPF, DKIM, and DMARC for your domains", and unauthenticated messages "might be marked as spam or rejected with a 5.7.26 error".

Why your contact form mail lands in spam

In order of how often we see it:

The form sends "From" the visitor's address

A visitor types ayse@gmail.com into your form, and the plugin sends you the message as From: ayse@gmail.com. Your web server isn't allowed to send for gmail.com, so SPF and DKIM can't align with that From domain, and DMARC fails. Google lists "Don't impersonate Gmail From: headers" among the requirements for all senders.

Fix it in the form plugin's settings: From must be an address on your own domain (form@example.com), and the visitor's address goes into Reply-To. You still reply with one click.

Mail leaves through PHP mail() on shared hosting

WordPress sends mail with wp_mail(), and unless a plugin changes it, that uses PHP's mail() (the source literally says // Set to use PHP's mail().) from wordpress@ your domain (wp_mail reference). On shared hosting that means the message leaves from the web server's IP. Whether it passes depends on the host: is that IP in your SPF record, does the server sign DKIM for your domain, and what else is sent from that IP? Google's note on shared IPs: "The activity of any senders using a shared IP address affects the reputation of all senders for that shared IP address."

The fix that holds up: send through a real mailbox over SMTP. Install an SMTP plugin, point it at your mail provider (your host's mail server, Google Workspace, Zoho or similar) with a real mailbox's login, and set From to that mailbox. Then SPF and DKIM are your provider's job, and they're set up once for all your mail.

Two SPF records

Adding a second v=spf1 record when you sign up for a newsletter service is the classic mistake. RFC 7208 (the SPF standard): "A domain name MUST NOT have multiple records that would cause an authorization check to select more than one record", and if more than one is found the check "produces the "permerror" result" (RFC 7208). Both records then count as broken. Merge them into one:

# wrong: two records
"v=spf1 include:spf.host.example.com ~all"
"v=spf1 include:spf.newsletter.example.com ~all"

# right: one record, both senders
"v=spf1 include:spf.host.example.com include:spf.newsletter.example.com ~all"

(spf.newsletter.example.com stands for whatever your newsletter service tells you to include. Some services don't need an SPF include at all because they send with their own return address; their setup page says which.)

Too many DNS lookups in SPF

Each include:, a, mx, ptr, exists and redirect= costs a DNS lookup, includes inside includes count too, and RFC 7208 section 4.6.4 caps it: "SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation". Over 10, the result is again "permerror". ip4: and ip6: don't count. Remove includes for services you stopped using, and drop a and mx if those servers don't send mail.

No DKIM at all

SPF alone breaks when mail is forwarded (the forwarding server isn't in your record). DKIM survives forwarding. Turn it on at every service that sends for you, and check the key length: Google says personal Gmail accounts require "a DKIM key of 1024 bits or longer" and recommends 2048 bits.

Turning DKIM on at the usual places

  • cPanel: Email » Email Deliverability. It shows each domain's SPF and DKIM status and a Repair button that writes suggested records (cPanel docs). The docs note that Repair "is unavailable if the system does not control the domain's DNS records". If your DNS is at Cloudflare or your registrar, copy the suggested DKIM and SPF values from Manage and add them there by hand.
  • Plesk: Websites & Domains > your domain > Mail tab > Mail Settings, tick "Use DKIM spam protection system to sign outgoing email messages" (Plesk docs). With external DNS, Plesk shows the records to copy.
  • Google Workspace, Zoho, newsletter services: each has a "domain authentication" or "authenticate domain" page that gives you one or two DNS records (TXT or CNAME). Add them exactly, wait for the service to show "verified".

Rolling out DMARC without losing mail

Google's recommended DMARC rollout starts with: "Set up DKIM and SPF at least 48 hours before setting up DMARC." Then:

  1. p=none with reports for at least a week. Google: "Messages are delivered normally. There is no risk of messages being rejected or marked as spam." The rua= address receives daily XML reports showing every server that sent mail as your domain and whether it passed.
  2. Fix what the reports show. Usually a forgotten sender: the shop's order e-mails, the host's server notifications, an old newsletter tool.
  3. Move to p=quarantine. Failing mail then goes to spam rather than the inbox. Google's page suggests ramping up with pct= (for example pct=5). The current DMARC standard, RFC 9989 from May 2026, removed pct because "the "pct" tag was usually not accurately applied" by receivers. For a small site with two or three senders we'd skip the percentage step: once a couple of weeks of reports show everything passing, switch to p=quarantine for all mail.
  4. p=reject is optional for a blog. It stops spoofing completely, but a sender you forgot is then silently dropped.
Example DNS records for example.com: one SPF TXT record with two includes and ~all, a DKIM TXT record at s1._domainkey with a public key, and a DMARC TXT record at _dmarc with p=none and a rua report address; below, two common mistakes marked in red: a second v=spf1 record, which makes SPF a permerror, and a From address on gmail.com in a contact form, which fails DMARC alignment
Three records, one each. A second SPF record doesn't add a sender, it breaks SPF.

Check it

From a terminal:

dig +short TXT example.com | grep spf1
dig +short TXT s1._domainkey.example.com
dig +short TXT _dmarc.example.com

Replace s1 with your provider's selector (you'll find it in the DKIM setup page, or in the s= part of a message's DKIM-Signature header).

Then send a test from your contact form to a Gmail address, open it, and use More (three dots) > Show original. The top of that page lists SPF, DKIM and DMARC with PASS or FAIL. If DMARC fails while SPF passes, look at the domains: the SPF pass is probably for your host's domain, not yours.

Where this connects to your site

A contact address that actually gets your replies into inboxes is part of a believable contact page; the About and contact pages guide covers what reviewers and readers look for there. If you collect e-mail addresses for a newsletter, your privacy policy should say so.

Check your records for free

The free SPF and DMARC checker reads your domain's SPF and DMARC records, counts the SPF lookups and flags a second SPF record or a missing DMARC policy.

FAQ

Do I need DMARC if I only send a few e-mails a week?

Google requires it only from bulk senders, so you can get by without it. We'd still publish p=none with a report address: it costs nothing, the reports show anyone sending mail as your domain, and Google recommends it for every domain.

What's the difference between ~all and -all?

~all is a soft fail: mail from unlisted servers is suspicious but not rejected on SPF alone. -all is a hard fail. With DMARC in place, ~all is the usual choice, because DMARC's policy decides what happens.

Can I have one SPF record for the domain and another for a subdomain?

Yes. The one-record rule is per name. example.com and news.example.com can each have their own SPF record.

My domain doesn't send any e-mail. Should I still set these up?

Yes, to stop others from using it. Publish v=spf1 -all and v=DMARC1; p=reject; on domains that never send mail.

My host's DNS and Cloudflare both have records. Which one counts?

Only the DNS provider your domain's nameservers point to. If the nameservers are Cloudflare's, records you add in the hosting panel do nothing; add them in Cloudflare.

Spotted something out of date or wrong? Tell us and we'll correct it.

Read this guide in Turkish →

Check it on your own site. Free, no sign-up.

Free tools for this

Free scan

Check your own site

The free scan reads the first 50 pages and shows your score and every problem it finds.

First 50 pages free · no sign-up · no card

All guides