WordPress SPF and DKIM setup

WordPress has no mail server of its own. Out of the box, wp_mail hands each message to PHP's mail function on your web host, from wordpress@ your domain, with no DKIM signature and a Return-Path the host chose. Here is why that fails DMARC, how to route the mail through a provider that signs as you, and the From-address trap that a forced From walks straight into.

What you are setting up

Every email a WordPress site sends (password resets, new-user notices, comment moderation, WooCommerce receipts, contact-form submissions) goes through one function, wp_mail(). Unless a plugin changes it, that function builds the From address as wordpress@ plus your site's host name with any www. stripped, then calls PHPMailer in isMail() mode, which means PHP's mail() and whatever sendmail binary your web host wired behind it. Two things follow. The message leaves from the web server, so SPF is evaluated against a Return-Path that server chose, normally an address on the host's own domain, not yours. And nothing signs it with your domain, because a shared web server has no DKIM key for yourdomain.com unless the host set one up. Yet the From address is on your domain, so your DMARC policy applies: under p=none the mail lands in spam more often than it should, and under p=quarantine or p=reject the password reset never arrives. The fix is not a record. It is to stop sending from the web server and route wp_mail() through a provider that authenticates as you, then publish that provider's records.

Publish SPF and DKIM

Install a mailer plugin. WP Mail SMTP is the most widely used, and Post SMTP and FluentSMTP follow the same pattern: they hook phpmailer_init and hand the message to a provider instead of mail(). In WP Mail SMTP, run the Setup Wizard or open WP Mail SMTP > Settings and choose a mailer. The free plugin offers SendLayer, SMTP.com, Brevo, Elastic Email, Google Workspace / Gmail, Mailgun, Mailjet, MailerSend, Postmark, Resend, SendGrid, SMTP2GO, SparkPost, and Other SMTP; Amazon SES, Microsoft 365 / Outlook, and Zoho Mail need the Pro license. Whichever you pick, the DNS records you publish are that provider's, not WordPress's. Authenticate your domain in the provider's console and follow our guide for it: Amazon SES, SendGrid, Mailgun, Postmark, Brevo, Google Workspace, Microsoft 365, Zoho, or SMTP2GO. For a transactional provider the shape is always some version of this, with the selector and target taken from your own provider console:

Type:  TXT     (SPF, at the apex or on the provider's return-path subdomain)
Host:  @
Value: v=spf1 include:<the provider's SPF include> ~all

Type:  CNAME or TXT   (DKIM)
Host:  <selector>._domainkey
Value: (the key or delegation target the provider shows you)

Then, back in the plugin, set From Email to a real mailbox on the domain you just authenticated. WP Mail SMTP's own wording is that in many cases this must be an address at your domain, and for the API mailers it must be on the domain the provider verified. Replace the wordpress@ default with an address that exists, so bounces and replies have somewhere to go, and turn on Force From Email so a form plugin cannot quietly send as a customer's address. Send a message from the plugin's Email Test tool before you call it done.

If you must stay on PHP mail() (some managed hosts block outbound SMTP), the records have to come from the host, because the host's server is the sender. Ask for three things: the SPF mechanism that covers its outbound servers (an include: the host publishes, or the server's ip4:), a DKIM key the server will sign your domain with (the host generates it and tells you the selector; cPanel hosts do this from the Email Deliverability screen for domains they serve), and a Return-Path on your domain instead of the server's. If the host cannot do all three, nothing you publish will make that mail pass, and the plugin route is the only one left.

Add DMARC

Standard _dmarc TXT record at your domain. Start in monitor-only mode:

Type:  TXT
Host:  _dmarc
Value: v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com

WordPress is the reason to sit at p=none for a few weeks before tightening. The site you routed is rarely the only one: a staging copy, a second install on the same host, or a plugin that calls its own SMTP library instead of wp_mail() will keep sending from the web server, and the reports are the only place you will see it. Build the record with our DMARC builder and progress past p=none once the host's server has stopped appearing as a source.

The WordPress gotcha

Force From Email fixes the From and breaks the alignment. Every mailer plugin has a switch that stamps one From address on every message site-wide, and WP Mail SMTP strongly recommends turning it on. It is the right setting once the mailer is real. It is the wrong setting on its own, because the From is the domain DMARC judges and the switch does nothing to who signs. Two common shapes: the mailer is still Default (none), which the plugin's own docs describe as essentially the same as not using the plugin, so the forced you@yourdomain.com now rides on the web host's server with no DKIM, aligned with nothing, failing more decisively than the wordpress@ default did. Or the mailer is a personal Gmail or Outlook account on a different domain, so the message is signed for that mailbox provider's domain while the From says yours. In both cases the header analyzer shows a From on your domain, a signature (or none) for someone else's, and dmarc=fail. The From domain and the authenticated domain have to be the same domain, and only the provider you routed through can make that true.

The apex SPF record is not enough by itself. Adding the web host's servers to your SPF record is the most common WordPress “fix” and it usually changes nothing, because the Return-Path on PHP-mailed messages is the host's address, so your record is never the one consulted. It also spends one of your ten SPF lookups on a sender you are about to retire. Publish the provider's records, route the plugin, and let the host's server disappear from your reports.

Confirm it worked

  • Send a test from the plugin and read the headers. Trigger a real notification (a password reset is the honest test) as well as the plugin's Email Test. Confirm the DKIM signature shows d=yourdomain.com, the Return-Path is on your domain or on the provider's return-path subdomain for you, and the result is dmarc=pass. Our header analyzer reads it back plainly.
  • Check every sender on the site. Send a contact-form submission and a store receipt too. If one of them still arrives from the web server, a plugin is bypassing wp_mail() or has its own SMTP settings that need the same provider.
  • Watch the reports. The provider you chose should appear as an aligned, passing source. A row from your web host's IP range sending as your domain with no DKIM is WordPress mail that did not take the route: a staging site, a second install, or a mailer that fell back to PHP mail after a failed login. trustyourinbox labels the provider by name and flags the host's server as an unknown sender.
Let trustyourinbox publish WordPress for you

Connect your DNS once and we publish the WordPress records above in a single click, with a five-minute window to undo. Then we keep watching this sender in your DMARC reports and tell you the moment WordPress mail starts failing, so a typo in a record never quietly costs you the inbox.

Keep reading

Last verified 2026-09-06 against the official WordPress developer documentation.

Was this page helpful?

Stop guessing. Start monitoring.

Free for one domain. Set up in five minutes. We parse the reports; you read plain-English summaries.