WordPress send email not working: the likely causes, in order
Five reasons WordPress stops sending mail, ranked by how often they are the culprit, plus the one test that tells you whether the message ever left your server at all.
On this page
- Step zero: send one test to an inbox you control
- Cause 1: your host blocks PHP mail entirely
- Cause 2: it arrives, but nothing authenticates it
- Cause 3: the From address is a domain you do not send for
- Cause 4: another plugin has taken over wp_mail()
- Cause 5: the mail is queued and the queue never runs
- Keep it fixed, because the failure is silent
If WordPress send email not working is your problem, the cause is nearly always one of five
things, and they are not equally likely. In rough order: your host blocks PHP mail, the mail
leaves but is not authenticated and gets filtered, the From address belongs to a domain you do
not really send for, another plugin has taken over wp_mail(), or the message is sitting in a
queue that never runs. Before you change anything, work out which half of the problem you
have: mail that never left the server, or mail that left and was thrown away at the far end.
Those need opposite fixes, and guessing wrong costs a day.
Step zero: send one test to an inbox you control
These investigations drag on because people test by mailing themselves. Your own mailbox is the worst possible witness: it trusts your domain, and it hides things in spam.
Use a disposable inbox instead. Open InboxDome, copy the address, and send one message from the site with WP-CLI:
wp eval 'var_dump( wp_mail( "k7f2p9@mail.inboxdome.com", "WP test", "hello" ) );'
Three outcomes, three problems:
bool(false): WordPress never handed the mail to a mailer. Go to cause 4.bool(true)and nothing arrives within a minute: it left WordPress and died after that. Cause 1.- It arrives: sending works in general, so the fault is with one specific email, not with WordPress. Cause 4 again, or a switched off notification.
No WP-CLI on the box? The InboxDome Email Tester plugin does the same job from Tools > Email Tester, and also reports how long the mail took and what the SPF, DKIM and DMARC checks said. It needs a free API key and is not on WordPress.org, so you upload it yourself. The inbox is throwaway either way: receive only, and deleted 24 hours after it is created. If you have not used one, here is how a test address works.
Cause 1: your host blocks PHP mail entirely
This is the single most common reason WordPress send email not working turns up on shared
hosting. With no SMTP configured, wp_mail() hands the message to PHPMailer, which hands it to
PHP’s mail(), which hands it to a local sendmail binary. Plenty of hosts have disabled that
path, rate limited it, or route it through an IP with no reputation.
Every layer reports success, so nothing in the admin looks wrong.
The fix is to stop sending locally. Install an SMTP plugin (WP Mail SMTP, Post SMTP and FluentSMTP are the usual choices), point it at a transactional provider such as Postmark, Mailgun, SendGrid or Amazon SES, then run the same one line test again.
Cause 2: it arrives, but nothing authenticates it
If the test mail lands in spam rather than not at all, the problem has moved: it is authentication. Google’s sender guidelines require SPF or DKIM from every sender, and SPF, DKIM and DMARC together from anyone sending more than 5,000 messages a day to Gmail accounts. A WordPress site sending straight from an unaligned host IP satisfies none of that.
Your provider’s dashboard gives you the DNS records to publish. Add them at your registrar, let DNS settle, then re-send and read the results instead of assuming. The breakdown of SPF, DKIM and DMARC covers what each record asserts, which matters when only one of the three is failing.
Cause 3: the From address is a domain you do not send for
WordPress defaults to wordpress@yourdomain.com, and plugins happily override it. Two ways
that breaks delivery. First, the From domain has to line up with the domain your provider
signs, or DMARC alignment fails even though SPF and DKIM passed. Second, and worse, some
contact form plugins set From to the visitor’s own address, often a Gmail or Outlook one.
Those domains publish strict DMARC policies, so a receiver rejects the message outright.
Set From to an address on a domain you control and that your provider is authorised for, and
put the visitor’s address in Reply-To. Configure that in the SMTP plugin, not in a snippet
pasted into functions.php.
Cause 4: another plugin has taken over wp_mail()
wp_mail() is a pluggable function, so any plugin or mu-plugin loaded early enough can
replace it wholesale. Staging, maintenance and “disable all emails” plugins do this
deliberately, and one left active after a migration quietly swallows everything. WooCommerce
adds its own trap: a per-email on and off switch under WooCommerce > Settings > Emails, so one
notification can be dead while the rest are fine.
To see the real reason rather than a bare false, log the error. Put this in an mu-plugin:
add_action( 'wp_mail_failed', function ( $error ) {
error_log( 'wp_mail failed: ' . $error->get_error_message() );
} );
That hook fires after a PHPMailer exception is caught and hands you a WP_Error carrying the
original message, which usually names the problem outright. WP_DEBUG_LOG has to be on for
anything to be written. Then bisect: deactivate plugins in halves, re-running the WP-CLI test
each time.
Cause 5: the mail is queued and the queue never runs
Some plugins hand mail to a background job instead of sending it during the request. WordPress
runs those jobs on wp-cron, fired by visitor traffic rather than a real scheduler. If
someone set DISABLE_WP_CRON to true in wp-config.php and never added a system cron entry,
or the site gets very few visits, nothing fires. The signature is mail arriving
hours late, or only once you load the admin.
Check with wp cron event list and look for events long past due, then add a real cron entry
that hits wp-cron.php every few minutes.
Keep it fixed, because the failure is silent
Nothing bounces and nothing alerts you when this breaks again, only customers who never got a receipt. Once it works, automate one check: create an inbox through the Email Testing API, trigger a real password reset or order mail against it, and assert that it arrives with the right text and that SPF, DKIM and DMARC pass. The free tier covers 100 inbox tests a month with no card, enough to run it on every deploy.
One honest limit: InboxDome is the wrong tool if you need to keep the mail. Inboxes are temporary on purpose, 24 hours by default and seven days at the most, and receive only. For proving that WordPress send email not working is finally fixed, that is exactly what you want. For an archive of what your store sent last quarter, use your provider’s logs.
Disclosure: InboxDome publishes this blog and makes the products it mentions. We describe what they do rather than promise results.
Key takeaways
- Split the problem first, because mail that never left the server needs the opposite fix to mail that left and got filtered.
- Send one test message to a disposable inbox you control, since mailing yourself hides the failure in your own spam folder.
- On shared hosting the usual cause is blocked PHP mail, and the fix is an SMTP plugin pointed at a transactional provider.
- If mail arrives but goes to spam, the problem is authentication, so check SPF, DKIM and DMARC against the From domain.
- The failure is silent by design, so put one automated delivery check in place once it works again.
Sources
- WordPress Developer Reference: wp_mail() — What wp_mail() actually returns, and that it is a pluggable function.
- WordPress Developer Reference: the wp_mail_failed hook — Fires after a PHPMailer exception, passing a WP_Error with the real message.
- Google: Email sender guidelines — Every sender needs SPF or DKIM, and bulk senders need SPF, DKIM and DMARC.
- PHP Manual: the mail() function — The local sendmail path WordPress falls back to when no SMTP is configured.
Links last checked September 1, 2026.
Frequently asked questions
Why is WordPress send email not working when the admin says the message was sent?
Because WordPress only reports that it handed the message to a mailer. If wp_mail() returns true, PHPMailer accepted it, and nothing after that point is visible to WordPress. The host may have dropped it, or the receiving server may have filtered it. That is why you have to test with an inbox you can actually read.
Do I need an SMTP plugin on every WordPress site?
Practically, yes. WordPress falls back to PHP mail, which sends from your web server with no authentication and no reputation behind it. An SMTP plugin pointed at a transactional provider gives you a signed, authenticated path and a log you can look at when something goes missing.
How do I see the real error behind a failed wp_mail() call?
Hook wp_mail_failed. It fires after a PHPMailer exception is caught and passes a WP_Error object carrying the original PHPMailer message, which is far more specific than the false that wp_mail() returns. Log it, reproduce the failure, then read the log.
Can I use a temporary inbox to test WordPress mail?
Yes, and it is the fastest way to prove delivery. Open InboxDome, copy the address, send a test to it, and watch the message land. The inbox is receive only and deletes itself after 24 hours, so use it for testing rather than as a mailbox you need to keep.