WordPress password reset email not sending? Check the log first
Published Updated View as Markdown
WordPress password reset email not sending? Check the log to see whether the site sent it, then fix the real cause: transport, spam, a plugin, a stale address.
“I clicked Lost your password and nothing came.” WordPress shows “Check your email for the confirmation link” whether or not the email got anywhere. When a WordPress password reset email is not sending, the problem is in one of five places, and the first job is finding out which one before touching any settings.
This guide starts with the one check that tells you where to look, then goes through the causes in order.
Check the log first
WordPress keeps no record of the emails it sends. An email log writes a row for every send, with what happened to it. If you don’t have one, Adminkeep is a free plugin whose Email Log feature works as a standalone free email log plugin. Switch it on under Settings → Adminkeep, in the Email group.
A log only records emails sent after it is on, so it cannot explain last week’s missing reset. It can explain the next one:
- Open a private browser window, go to
/wp-login.php?action=lostpassword, and enter your own username. - Open Email Log in the admin menu and look at the newest row.
What the row says splits the problem in two:
- Sent, and the email arrived. Sending works. A user who still gets nothing has a stale address, an inbox problem, or an expired link.
- Sent, but nothing in your inbox or spam folder. The site handed the email over. What went wrong is on the delivery side: the sender, the domain’s mail records, or the receiving server.
- Failed. Open the row and read the error at the top. It names the cause more precisely than anything else will.
- Unconfirmed. Another plugin took over sending or queued the email. Its own records are the place to check.
- No row at all. WordPress was never asked to send it, usually because a plugin stopped it first.
The guide to checking whether WordPress sent an email covers each status in more depth.
The site cannot send email at all
The usual cause of a Failed row, or of the login page saying “The email could not be sent. Your site may not be correctly configured to send emails”, is that the server has no way to send mail. By default wp_mail() hands the message to PHP’s mail() function, which hands it to a mail program on the server. Many hosts don’t install one, some block outbound mail on port 25, and some managed hosts disable mail() on purpose. Local and staging environments almost always fall here.
The fix is to give WordPress a real mail transport: an SMTP server, or a mail service such as Amazon SES, Brevo, Mailgun, Postmark or SendGrid. Adminkeep includes an SMTP feature with presets for those providers and a test email that shows the server’s own reply; the SMTP settings guide walks through it. Whichever route you take, the log should turn from Failed to Sent.
The email goes out but lands in spam, or nowhere
A Sent row with an empty inbox usually means the receiving server did not trust the message. Out of the box, WordPress sends from [email protected], an address that does not exist, on a domain that often has no SPF or DKIM record saying which servers may send for it. Gmail, Outlook and most business mail now reject or quarantine mail like that.
Two things fix this, and both are needed:
- Send from a real address on your domain, through a server allowed to send for that domain. That is what an SMTP or mail-service setup gives you, and why those services ask you to verify your domain first.
- Publish SPF and DKIM records for the sending service in your domain’s DNS, then a DMARC record. Your mail provider’s setup page lists the exact records.
Keep the From address on your own domain. A gmail.com or outlook.com From address sent from your web server fails those same checks harder.
A plugin or theme is intercepting it
Plugins can step into the reset flow at several points. A security plugin can block the request, a membership plugin can replace the email with its own, and any plugin can filter retrieve_password_message or wp_mail and change where the message goes. Some disable resets for certain roles through the allow_password_reset filter, in which case the login page shows an error and no email is attempted.
The log tells you which case you have. No row means the send was stopped before wp_mail(): look for a plugin that manages logins, membership or security. An unexpected recipient or sender means something filtered the email on its way out. Unconfirmed points at a plugin that queues or takes over sending.
To find it, deactivate the likely plugins one at a time, on a staging copy if you would rather not touch the live site, and request a reset after each.
The address on the account is wrong
If the log shows the reset Sent to an address the user does not recognise, the account’s email is stale. The lost-password form accepts a username as well as an email, so a user who types their username gets the reset sent to whatever address is on the profile, which may be one they can no longer read. WordPress does not show which address that was, on purpose.
Check the user under Users in the admin, fix the email, and ask them to try again.
The email arrived, but the link had expired
A password reset link is good for one day. After that, WordPress answers “Invalid key” and the user has to request a new one. The check happens in check_password_reset_key(), with the window set to DAY_IN_SECONDS and adjustable through the password_reset_expiration filter:
add_filter( 'password_reset_expiration', function () {
return 3 * DAY_IN_SECONDS;
} );
A link also stops working when the user requests a second reset. Only the newest key counts, so someone who clicks “Lost your password” twice and opens the first email is told the key is invalid. Tell them to use the most recent email, and if a link is refused the moment it arrives, send a fresh one and have them open it straight away.
Make the email easier to trust
Once the reset is arriving, how it looks matters too. WordPress sends it as plain text with a raw URL and no site name, which is what a phishing email looks like to a cautious user. Adminkeep’s Nice Default Emails feature sends WordPress’s own emails in a simple HTML layout headed by your site’s name, with the reset link clickable; the guide to sending WordPress default emails as HTML covers it.
In short
Check the log, then work down the list.
- Failed in the log: the site cannot send. Give it a mail transport.
- Sent but nowhere: fix the From address and the domain’s SPF and DKIM records.
- No row, or a strange recipient: a plugin or theme filter. Find it and switch it off.
- Sent to an address the user cannot read: fix the email on the account.
- Email arrived but “Invalid key”: the link was over a day old, or a newer one replaced it.
A log turns “the reset never came” from a guess into a row you can read, and the row usually says which of the five it is.
Questions people ask
How do I know whether WordPress sent the password reset email?
Switch on an email log, request a reset for your own account, and read the newest row. Sent means the site handed it over and the problem is on the delivery side. Failed shows the error. No row means WordPress never tried.
Why does the password reset email land in spam?
The From address is usually wordpress@yourdomain, and if that domain has no SPF or DKIM records, the receiving server has no way to trust the message. Sending through an authenticated server for your domain, and adding the records it needs, fixes it.
How long does a WordPress password reset link last?
One day. After that the link shows "Invalid key" and the user has to request a new one. Developers can change the window with the password_reset_expiration filter.
Do I need an SMTP plugin to fix password reset emails?
Only when the log shows the send failing or landing in spam because of the sender. If the log says Sent and the address on the account is right, look at the inbox and the domain's mail records before changing how the site sends.