Users not receiving password reset emails in WordPress

I’m currently facing an issue with my WordPress website. Customers on my website are not receiving the password reset link when they request a password reset. Are there any common issues or known conflicts that could lead to customers not receiving password reset emails in WordPress?

r/Wordpress

WordPress password reset email fails for five distinct reasons: two are general deliverability problems that affect all WordPress mail, three are specific to the reset flow. The diagnostic below sorts between them in about five minutes and is the right first move.

Step 1: confirm whether wp_mail() is running at all

Install Check & Log Email or Log Emails, trigger a password reset from the login screen for a test account, and look at the log. If the site uses WooCommerce, trigger the reset from both the standard WordPress login page (/wp-login.php?action=lostpassword) and the WooCommerce My Account page and compare the log output; the two forms trigger different code paths. For a broader test of WordPress’s sending capability, see Check that WordPress can send emails.

The result puts you in one of three buckets:

Log status What it means Where to look
No log entry wp_mail() was never called; a security plugin likely throttled the request Cause 3
Log entry, status failure Mailer rejected the message; credential or config error Cause 1
Log entry, status success, no email delivered Mail left WordPress; From-address alignment issue or WooCommerce override Cause 2, Cause 5

wp_mail() returns true on handoff to the mailer, not on delivery. Without a logging plugin, a successful handoff and a delivery failure look identical. Installing one resolves this ambiguity before any other diagnostic.

Cause 1: the site cannot send mail {#cause-1-the-site-cannot-send-mail}

If Step 1 showed a log entry with a failure status, the mailer is configured but rejecting messages. If there was no log entry and a security plugin is not installed, the problem is likely that wp_mail() cannot reach an SMTP server at all.

PHP’s built-in mail() function is disabled or blocked at the server level on most modern hosts. WordPress’s default sending path calls PHP’s mail() via PHPMailer and produces wp_mail_failed errors or silently drops mail when mail() is disabled.

The fix is an SMTP plugin paired with a transactional provider. The plugin replaces PHP’s mailer with an authenticated SMTP or API connection; the provider supplies the relay infrastructure and the deliverability reputation.

WP Mail SMTP, FluentSMTP, and Post SMTP cover the plugin side. For provider-side options, Postmark and SMTP2GO are well-regarded for transactional mail at WordPress volumes. Mailgun and Resend make sense for sites already using those ecosystems.

Full setup walkthrough: How to Set Up Email on WordPress. If the log shows an SMTP connect() failed or 535 Authentication failed error with an SMTP plugin already installed, the problem is a credential or host/port mismatch, not a code problem. Check the plugin’s connection settings against the provider’s documentation.

Cause 2: the From address is unaligned with your DNS {#cause-2-the-from-address-is-unaligned}

A common cause on sites that have SMTP configured and can demonstrably send other types of email. Password reset email lands in spam or is quietly discarded while WooCommerce orders, plugin notifications, and contact form replies arrive normally.

The reason is the default From address. WordPress’s wp_mail() function constructs its default From: in wp-includes/pluggable.php using network_home_url(): it strips the scheme and a leading www., then prefixes wordpress@. On a site whose home URL is https://www.example.com, the default From comes out as [email protected]. On a site whose home URL is https://store.example.com, it comes out as [email protected].

That subdomain address is where the alignment problem appears. SPF, DKIM, and DMARC published for example.com cover subdomains under DMARC relaxed alignment, but the strictness of how that is applied differs between mailbox providers. Microsoft 365 and several large ISPs score messages with bare-hostname or unexpected-subdomain From addresses more aggressively than the RFC minimum, and the reset email goes to junk regardless of whether the technical SPF and DKIM pass.

The fix is to set an explicit From address in the SMTP plugin, on the organisational domain ([email protected], [email protected]) where SPF and DKIM are published and where the SMTP provider’s DKIM signing domain aligns. The “From Email” override in WP Mail SMTP, FluentSMTP, and Post SMTP all apply this override after every other filter, including the core wp_mail_from default. Enable “Force From Email” in WP Mail SMTP and FluentSMTP so that WooCommerce and other plugins that set their own From at the message level cannot override the setting.

For setting the From override, see Change WordPress’s default email sender details. For publishing the DNS records, see DNS for WordPress email: SPF, DKIM, DMARC.

Cause 3: a security plugin is suppressing the reset {#cause-3-a-security-plugin-is-suppressing-the-reset}

Login-protection plugins throttle password reset requests by IP and by username as part of brute-force protection. When the throttle trips, the reset form usually returns a generic success message (“Check your email for a password reset link”) without sending anything. Nothing is logged on the WordPress side because wp_mail() was never called.

The diagnostic clue from Step 1 is no log entry despite the user completing the reset form. Four plugins account for the large majority of cases:

Wordfence Security. Under All Options > Brute Force Protection, the “Limit password reset attempts” and “Forgot password lockout” settings cap how many reset requests can come from one IP or target one username within a configured window. The default is permissive; installations hardened by a security-focused admin often are not. Check both the attempt count and the window length.

Limit Login Attempts Reloaded. Under Settings > Limit Login Attempts, a separate “Password reset email limit” throttles resets per IP and per username per hour. When the limit is reached, the plugin suppresses the email without an error visible to the user. This is distinct from the login lockout: an IP can be unlocked from the login lockout and still have its reset requests suppressed.

WP Cerber Security. Under Main Settings > Hardening, a “Disable password reset” toggle exists and drops every reset request silently when checked. Cerber also has per-IP and per-username attempt limits under its “Limit attempts” section. Check both.

Solid Security (formerly iThemes Security). Under Security > Settings > Local Brute Force, the “Max Login Attempts Per Host” and “Max Login Attempts Per User” settings apply to password reset requests as well as login attempts. After the threshold is reached, subsequent reset requests from the same IP or for the same account are suppressed.

To fix: temporarily increase the limits, wait for the lockout window to expire, and retest. For a user who is definitely locked out, temporarily whitelisting their IP in the plugin will let the reset through immediately. After confirming the cause, raise the thresholds enough that a user retrying three times in an hour is not locked out.

Cause 4: the reset link has expired {#cause-4-the-reset-link-expired}

Reports that read “the link doesn’t work” or “I clicked the link and got an error” rather than “I didn’t receive the email” often resolve to key expiry. check_password_reset_key() in wp-includes/user.php rejects keys older than DAY_IN_SECONDS (86,400 seconds, 24 hours). The user gets “Your password reset link has expired. Please request a new link.” This is not a delivery failure; the email arrived and the user received it.

The link also expires the moment a new reset is requested for the same account, because generating a new key invalidates all prior keys for that user. A user who clicks the link from their first reset attempt after having triggered two more will find the link invalid.

For most sites the right answer is to tell the user to request a fresh link and click it promptly. For sites with a specific operational reason why 24 hours is too short (users in environments where email is reviewed by an assistant and acted on 48-72 hours later, for example), the password_reset_expiration filter extends the window:

// In a mu-plugin file, not in functions.php
add_filter( 'password_reset_expiration', function() {
    return 48 * HOUR_IN_SECONDS; // 48 hours
} );

Use this sparingly. Longer-lived reset tokens expand the window for account takeover if an attacker can intercept or access the email.

Cause 5: WooCommerce sends a separate reset flow {#cause-5-woocommerce-sends-a-separate-reset-flow}

WooCommerce adds its own “Lost your password?” flow alongside WordPress core’s. The two flows send different emails from different code paths with different From address settings, and they can fail independently.

The WooCommerce customer password reset email is handled by the WC_Email_Customer_Reset_Password class (defined in woocommerce/includes/emails/class-wc-email-customer-reset-password.php), which extends WC_Email and uses the template at woocommerce/templates/emails/customer-reset-password.php. The From address for all WooCommerce emails, including this one, is set globally at WooCommerce > Settings > Emails > “From address”: the field above the notifications table, distinct from both the WordPress General Settings email address and the SMTP plugin’s From override.

A WooCommerce site can have a working SMTP plugin, correct SPF/DKIM/DMARC for the organisational domain, and a correctly configured From address in the SMTP plugin, and still drop the customer password reset email if WooCommerce’s global “From address” field points at an unverified address.

Check WooCommerce > Settings > Emails for two things:

  1. “Customer Reset Password” is enabled. Click the “Customer Reset Password” row in the notifications table and confirm the “Enable this email notification” toggle is on. It is occasionally disabled during email template configuration work and not re-enabled.
  2. The global “From address” field (above the notifications table) contains an address on the authenticated domain. If WooCommerce’s From address is empty, it falls through to WordPress’s default. If it is set to a non-empty address on a domain the sending pipeline cannot authenticate, the email will fail alignment checks.

The WooCommerce “Lost your password?” form appears on the My Account page (shortcode [woocommerce_my_account]). If the site’s login page is the standard WordPress wp-login.php, that page’s reset flow goes through core’s retrieve_password() and is entirely unaffected by WooCommerce’s settings. If the login and password reset flow has been moved to a WooCommerce-managed page, both must be checked.

If you only fix one thing

On a site that already has a working SMTP plugin and has published SPF, DKIM, and DMARC for its sending domain, the single change that resolves the largest fraction of password reset email failures is setting an explicit From address in the SMTP plugin’s “From Email” field: something on the organisational domain rather than the default wordpress@<sitename>, with the SMTP plugin’s “Force From Email” option enabled so no plugin overrides it. This addresses Cause 2 and removes the most common cause of authenticated mail that still underperforms at major mailbox providers. The check and log step takes five minutes and rules out the other causes before the From fix is applied.