WordPress email lands in spam when the receiving server cannot confirm that your domain allowed it to be sent. That check uses three DNS records on the domain in your From address: SPF, DKIM and DMARC. Send from an address on your own domain, through a mail service that signs for that domain, publish the three records it asks for, and then test with a real inbox rather than trusting a "sent" message in a log.
Spam, or never sent at all?#
Check this first, because the fixes are different. Send a test from the site to an address of your own at Gmail and one at Outlook.com, then look in the inbox and the spam folder of both.
If it is in spam, the message left your site and the receiving server did not trust it: this guide is for you. If it is nowhere at all, or a log says it failed, the problem is sending rather than trust. Fix that first, by sending through a mail service, and come back here.
Why WordPress mail looks suspicious#
By default WordPress hands email to PHP's mail function on the web server. Three things then count against it:
- The server sending it is a web server, often shared, and your domain has not said it may send for you.
- Nothing signs the message for your domain, so the receiving server cannot tell it apart from a forgery.
- The From address may not be a real mailbox. When nothing sets one, WordPress sends from
wordpress@followed by your site's domain.
Gmail's sender guidelines ask every sender to set up SPF or DKIM, and anyone sending more than 5,000 messages a day to Gmail accounts to set up SPF, DKIM and DMARC. Microsoft has announced the same three for domains sending more than 5,000 messages a day to Outlook.com (Microsoft's post). Below that volume Gmail asks only for SPF or DKIM, but the same records still decide whether a small shop's mail looks genuine.
Send from an address on your own domain#
Everything below is checked against the domain of the From address, so pick one you control, such as shop@yourdomain.com, and make sure your mail service lets you send as it.
- WooCommerce emails use WooCommerce → Settings → Emails → Email sender options, in the "From" address box.
- WordPress's own emails (password resets, new account notices) use
wordpress@yourdomainunless something changes it. This snippet replaces only that made-up address and leaves alone any plugin that sets its own:
add_filter( 'wp_mail_from', function ( $from ) {
return str_starts_with( $from, 'wordpress@' ) ? 'shop@yourdomain.com' : $from;
} );Never send from a gmail.com, outlook.com or yahoo.com address through anything other than that provider's own servers. Gmail's guidelines say plainly not to impersonate Gmail From addresses, and those domains publish DMARC records you cannot change.
SPF, DKIM and DMARC in plain words#
All three live in your domain's DNS, added wherever you manage the domain (your registrar, your host, or Cloudflare). They are TXT records, except that some services publish DKIM as a CNAME pointing at their own key. Your mail service tells you exactly what to add.
SPF: who may send for your domain#
A single TXT record on your domain, starting v=spf1, listing the servers allowed to send your mail. Most mail services give you an include: to add. Google's own example, for a domain that sends only through Google Workspace, is:
v=spf1 include:_spf.google.com ~allOne detail matters: services such as SendGrid and Amazon SES send, by default, with a return address on their own domain, and SPF is checked against that return address. For them, SPF on your domain matters less and DKIM matters more.
DKIM: a signature only your service can make#
Your mail service signs each message, and publishes the matching public key on your domain at a name like selector._domainkey.yourdomain.com. Google Workspace's DKIM set-up page uses google._domainkey as its example. Usually you switch signing on in the service's dashboard and add the record it gives you.
DMARC: what to do when the other two fail#
A TXT record at _dmarc.yourdomain.com. A message passes DMARC when SPF or DKIM passes for a domain aligned with the one in the From address: the same domain, or under the same main domain. Gmail's guidelines put it the same way. The record also tells receiving servers what to do with a message that fails: p=none asks only for reports, p=quarantine asks for spam, p=reject asks for refusal. A safe start:
v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.comThe current standard is RFC 9989, published in May 2026. It is also clear that a DMARC pass on its own does not guarantee delivery to the inbox.
The mistakes that undo them#
These are worth checking first. Each of the first three makes the whole SPF record an error to a receiving server; the fourth leaves DMARC out altogether:
- Two SPF records. A domain must have one record starting
v=spf1. Adding a second one for a new service, instead of adding itsinclude:to the first, breaks both. RFC 7208, the SPF standard, treats more than one as an error. - Too many lookups. Each
include,a,mx,ptr,existsandredirectcosts a DNS lookup, and the ones inside each include count too. Past 10, the standard says the check must return an error. A domain with includes for several services can pass the limit without anyone adding anything wrong. - An include that leads nowhere. A typo, or a service you have since left, gives an
include:with no SPF record behind it, and the standard treats that as an error as well. - No DMARC record at all. Start with
p=noneand only move toquarantineonce reports show all your real mail passing.
Look up your own records#
You do not need any special software. On a Mac or Linux terminal:
dig +short TXT yourdomain.com
dig +short TXT _dmarc.yourdomain.com
dig +short TXT google._domainkey.yourdomain.comOn Windows, nslookup -type=TXT yourdomain.com does the same. Or use Google's Dig tool in a browser: choose TXT and type the name.
How to read the answers:
- The first command should return exactly one line starting
v=spf1. Two such lines is mistake 1 above. Other TXT lines (site verification codes and the like) are normal. - Count the includes, then look up each one the same way and count theirs.
- The second should return one line starting
v=DMARC1. Nothing back means no DMARC record. - For DKIM, use the selector your service gives you in place of
google. Nothing back means signing was never switched on, or the record has a different name.
DNS answers are cached, so a record you added a few minutes ago may not show yet.
Contact forms: the visitor's address goes in Reply-To#
A contact form that sends the message "from" the visitor's own address is a common cause of form messages going to spam or vanishing. Your server is not allowed to send for the visitor's domain, so SPF and DKIM cannot pass for it. You can see what some of those domains ask for: dig +short TXT _dmarc.yahoo.com returned p=reject in October 2026, which asks every receiving server to refuse such a message.
Set the form to send from your own address and put the visitor's address in the Reply-To field. Pressing Reply still answers the visitor. Look for both fields in your form plugin's notification settings.
Test the inbox, not the plugin#
"Sent" in a log means the message was handed over and accepted for sending. Whether the receiving server trusted it only shows in the received message.
- Send a test to a Gmail address you can open.
- Open it, then next to Reply choose More and Show original (Google's instructions).
- Look for the
Authentication-Resultslines. You wantspf=pass,dkim=passanddmarc=pass, and the DKIM line should name your domain rather than only the mail service's.
Repeat with Outlook.com if your customers use it. If all three pass and the message is still filed as spam, the records are no longer the cause: Gmail's sender guidelines list what it weighs next, such as how often recipients report your messages as spam and, for marketing email, a working one-click unsubscribe.
Doing the checks with Email Delivery#
Email Delivery sends your site's email through a mail service and keeps a log of every message. Its From Domain panel, under Email Delivery → Dashboard and again under the result of Send a test, looks up the SPF and DMARC records of your From domain, and DKIM for services that always use the same record name (google for Google Workspace unless you chose another, selector1 and selector2 for Microsoft 365, and the names SendGrid, Mailjet and Fastmail use). For other services it says Not checked rather than guessing.
Each row shows what was looked up, what came back and the one thing to do: the include Google or Microsoft 365 asks for, two SPF records to merge, an SPF record past the 10-lookup limit, an include that leads nowhere or back to itself, a part receiving servers cannot read, or no DMARC record. It runs once a day, after each test, when you save a new From address or mail service, and when you press Check again. The lookups go to your own server's DNS resolver and no outside service. When SPF or DMARC is missing or wrong, Worth doing next on the Dashboard says so. The domain you send from in the docs lists every check.
What it does not do: it changes nothing about how mail is sent and does not edit your DNS (you add the records where your domain is managed), and a row that says Found is not a promise that every message reaches the inbox. It does not read the message itself. It checks the From address set in its own settings, so a plugin sending from an address of its own is not checked. The From, name and reply-to settings can make every plugin send from your address.
Checklist#
- Every email from the site uses a From address on your own domain.
dig +short TXT yourdomain.comreturns onev=spf1line, with your mail service's include, and no more than 10 lookups in total.- DKIM signing is switched on in your mail service, and its record answers.
_dmarc.yourdomain.comreturns av=DMARC1record,p=noneto start.- Contact forms send from your address with the visitor in Reply-To.
- A test to Gmail shows
spf=pass,dkim=passanddmarc=passunder Show original, and lands in the inbox.
The plugin for this
Email Delivery
Send your site's email through a real mail service, and see what happened to every message.
From $19 a year · every feature · 30-day refund
![The Send a test screen of Email Delivery in WordPress admin. A red box reads It did not go. SMTP Error: Could not authenticate. Below, a panel headed What the mail server said, noting it is safe to paste into a support request, shows the full conversation with smtp.sendgrid.net, the sign-in lines replaced by [credentials hidden], ending in 535 Authentication failed: The provided authorization grant is invalid, expired, or revoked.](https://www.traslatability.com/wp-content/themes/traslatability/assets/screens/email-delivery-by-traslatability/crops/01-test-transcript-m.webp?ver=1792726162)
In the documentation
- The domain you send from: SPF, DKIM and DMARC Documentation
- From, name and reply-to Documentation
- Being told when it breaks Documentation
- Why do my WordPress emails go to spam? Knowledge base
- A customer says their email never came, but the log says Sent Knowledge base
- How do I know whether my site has this problem? Knowledge base