When a user clicks "lost password", the email that goes out is the most mission-critical mail your WordPress site will ever send. A missed order confirmation is awkward; a missed password reset is a lost user, a support ticket, and a real loss of trust. And WordPress password resets have a reputation for going to Spam — partly for predictable reasons, partly for more subtle ones.
This article walks through the why, the how-to-test and the fix list.
A native wp-admin plugin is in private beta — run placement tests from your dashboard and alert on drops.
Why WordPress password resets hit Spam more than other mail
Four reasons, roughly in order of how often they are the cause:
- Default PHP
mail()send path. Without an SMTP plugin, WordPress hands the password reset email to PHP's built-in mail function, which in turn hands it to whatever local MTA the host runs — usually with no SPF/DKIM/DMARC alignment to your domain. Gmail, Outlook, Yahoo all treat this as highly suspicious, particularly for password-related mail. - From-address mismatch. Default WordPress sends as
wordpress@yourhost.example, not as your actual domain. That header-from almost never aligns with SPF or DKIM, breaking DMARC. - Content triggers. Password reset content is the textbook phishing template: "click here to reset your password", urgency, a link to a login flow. Reputation-neutral content can still get flagged if the sending domain is cold.
- Cold domain. If your site does not send much mail, the sending domain has a thin reputation. One password reset in Spam, one user marks it as Spam instead of "not spam", and the reputation gets worse.
Reproducing the problem — in 5 minutes
Do not guess. Test.
- Open our free Inbox Check tester and generate a seed list (20 mailboxes across Gmail, Outlook, Yahoo, Mail.ru, Yandex, GMX, ProtonMail and more). Keep the tab open.
- Go to your WordPress site's lost-password flow:
/wp-login.php?action=lostpassword. - Submit each seed email address. WordPress will attempt to look up a user for each and will fire
retrieve_password()if it finds a match — so you may want to create test users first, or trigger a different transactional flow (new user registration) that does send to arbitrary addresses. - Wait 30–60 seconds. Placement results appear on the tester page. You see exactly how many of the 20 landed in Inbox, Spam or Promotions, per provider.
- Check the authentication panel: SPF, DKIM, DMARC results. The raw headers are there too.
# If you see this in the headers, you have a problem
From: WordPress <wordpress@shop-host-prod-42.example>
Return-Path: wordpress@shop-host-prod-42.example
Authentication-Results: mx.google.com;
spf=softfail smtp.mailfrom=shop-host-prod-42.example;
dkim=none;
dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yoursite.comThat header is the sign of raw PHP mail() on shared hosting with no SMTP plugin. Gmail and Outlook bury this into Spam on first sight.
The 30-minute fix list
Step 1: Install an SMTP plugin
This is non-negotiable. Pick WP Mail SMTP, FluentSMTP or Post SMTP. Connect it to a transactional backend (Mailgun, SendGrid, SES, Postmark). Verify that the test email goes out via that backend, not via PHP mail().
Step 2: Fix the From address
Go to the plugin settings and override the default "From email". Set it to something like no-reply@yoursite.com — using your actual domain, not the host's. The "From name" should be your site name or company name.
Step 3: Publish SPF, DKIM, DMARC
Publish these three records on the sending domain. Values for SPF and DKIM come from your backend.
# SPF
yoursite.com TXT
v=spf1 include:mailgun.org ~all
# DKIM (published at the selector the backend tells you)
smtp._domainkey.yoursite.com TXT
v=DKIM1; k=rsa; p=MIGfMA0GCSq...
# DMARC — start at p=none, move to quarantine after 2 weeks clean
_dmarc.yoursite.com TXT
v=DMARC1; p=none; rua=mailto:dmarc@yoursite.com; adkim=s; aspf=sStep 4: Verify alignment in a test
Retrigger the password reset flow to your seed list. In the Inbox Check results, authentication should now show spf=pass, dkim=pass, dmarc=pass. If any of those three is still failing, fix before moving on.
Step 5: Warm the domain if it is cold
If your site is low-volume (a few emails a week), placement can still be shaky even after auth passes. Three weeks of low, natural sending to engaged recipients is what reputation needs. For a site that only sends password resets, that means seeding a newsletter or digest to build baseline reputation — not a cold outreach campaign.
Step 6: Audit the content
Default WordPress reset mail is plaintext, no heavy styling, no marketing wrapper. If your theme or a plugin has swapped the content for a big HTML template with promotional styling — unsolicited hero images, multi-column layouts, marketing copy — revert it. Password reset mail should look mechanical. Plain text with one clear link reaches Inbox better than any branded HTML.
Special cases
WooCommerce customer password reset
Woo generates its own reset flow for customers at checkout. It uses the same wp_mail() pipeline as the core flow, so everything above applies. Verify specifically by testing the "My Account → Lost your password" form on a Woo site — the templates are slightly different.
BuddyPress / membership sites
These plugins often send activation emails from a non-standard From header. Check the activation email's headers. If the From domain does not match your sending domain, either override it at the plugin level or publish SPF/DKIM for the alternate domain.
Custom reset flows (LearnDash, MemberPress)
Some learning and membership plugins implement their own reset/activation emails that bypass wp_mail(). Test them separately — do not assume fixing core WordPress fixes their flow.
Ongoing monitoring
Password reset deliverability is worth a weekly check at minimum. A DNS change, a plugin update, a shared-IP reputation hit at your backend can all break it silently. Users do not usually email support to say "I did not receive the reset" — they just leave. Scheduled placement tests catch the drop before the churn does.