Skip to content
ThemesIonic — home
Troubleshooting

WordPress Not Sending Emails: How to Diagnose and Fix It

WordPress sends mail through PHP by default, and most hosts and inboxes reject it. Find out whether the message left the server, then move the site to authenticated SMTP.

1 min read intermediate

Quick fix: WordPress hands mail to PHP's mail() function, which most hosts either disable or send from an unauthenticated address that Gmail and Outlook discard. Install an SMTP configuration, authenticate with a real mailbox or sending service, and set a From address on your own domain.

Before changing anything, find out which of the three stages is failing: WordPress never calls the mail function, the server never delivers the message, or the recipient's provider silently discards it.

Stage 1: confirm WordPress is actually sending

Send a test from a source you control. Most SMTP plugins ship a test tool, but a plain trigger works too:

  • request a password reset for your own account;
  • add a new user with your address;
  • submit the site's contact form.

If nothing at all happens — no error, no delay — check whether a plugin is short-circuiting mail. Some maintenance, staging and security plugins disable outgoing email deliberately so a staging copy cannot email real customers.

Turn on WordPress debug mode and watch wp-content/debug.log while you trigger a send. A PHP fatal inside a mail hook stops the message before it reaches the transport.

Stage 2: read what the transport says

wp_mail() returns false when PHP refuses the message. Capture that instead of guessing, using a small must-use plugin in wp-content/mu-plugins/mail-debug.php:

<?php
add_action('wp_mail_failed', function (WP_Error $error) {
    error_log('wp_mail failed: '.$error->get_error_message());
});

Now trigger a send and read the log again. Typical messages and what they mean:

Logged message Cause
Could not instantiate mail function PHP mail() is disabled on the host
SMTP connect() failed Wrong host, port blocked, or firewall
SMTP Error: Could not authenticate Wrong username, password or app password
Invalid address: (From) From address is empty or malformed
No entry at all Nothing called wp_mail(); the problem is in the form or plugin

That last row matters. If no entry appears when you submit a form, the form never handed the message to WordPress, and the fix belongs in the form plugin instead.

Stage 3: replace PHP mail with authenticated SMTP

PHP mail() sends from the web server with no authentication and usually a From address like wordpress@yourdomain.com that does not exist as a mailbox. Receiving providers treat that as a spoofing attempt.

Pick one sending route:

  • A mailbox on your domain through your host or Google Workspace/Microsoft 365 — fine for low volume such as admin notices and form notifications.
  • A transactional email service — better deliverability, logs of every message, and it survives a host migration. Use it once the site sends order emails or password resets that customers depend on.

Configure it with an SMTP plugin or in code:

<?php
add_action('phpmailer_init', function ($phpmailer) {
    $phpmailer->isSMTP();
    $phpmailer->Host       = 'smtp.example.com';
    $phpmailer->SMTPAuth   = true;
    $phpmailer->Port       = 587;
    $phpmailer->SMTPSecure = 'tls';
    $phpmailer->Username   = 'notifications@yourdomain.com';
    $phpmailer->Password   = defined('SMTP_PASS') ? SMTP_PASS : '';
    $phpmailer->setFrom('notifications@yourdomain.com', 'Your Site');
});

Keep the password out of the file itself. Define it in wp-config.php and reference the constant, so the credential is not sitting in a theme or plugin file that could be exposed.

Fix the From address and authentication records

Deliverability depends on three DNS records on the sending domain:

  1. SPF — lists the servers allowed to send for the domain. Add your sending service to the existing record; never publish two SPF records.
  2. DKIM — signs each message. Your provider gives you the key to publish.
  3. DMARC — tells receivers what to do when SPF and DKIM fail, and where to send reports.

Then make WordPress use an address that matches those records:

<?php
add_filter('wp_mail_from', fn () => 'notifications@yourdomain.com');
add_filter('wp_mail_from_name', fn () => 'Your Site');

A message from noreply@yourdomain.com with valid SPF and DKIM lands. The same message from wordpress@server123.hosting.net usually does not.

Common cases that look like a WordPress bug

Only some recipients get mail. Almost always a reputation problem at one provider. Check the sending service's log for that address — a bounce or complaint may have suppressed it.

Mail works for admin notices but not the store. WooCommerce templates can be disabled individually under WooCommerce → Settings → Emails. Confirm the specific notification is enabled before debugging the transport.

Mail stopped after a migration. The new host may block port 25 or 587, or the DNS still points SPF at the old provider. Re-check both after moving hosts.

Mail is slow, not missing. Sending happens during the page request. A slow SMTP handshake shows up as a slow checkout or slow user registration; a service with an API transport avoids that.

Verify the fix

Send one test to an address at a different provider than your own, then check:

  • it arrives in the inbox rather than spam;
  • the message headers show spf=pass and dkim=pass;
  • the From address is the one you configured;
  • replies reach a monitored mailbox.

Keep the mail-failure logger in place. The next time delivery breaks, the reason will already be in the log instead of requiring this whole pass again.

Frequently asked

WordPress only reports whether PHP accepted the message for delivery. If the host's mail transport drops it, or the receiving server rejects it for failing SPF or DKIM, WordPress never learns about it.
You need authenticated SMTP or an email API. A plugin is the usual way to configure it, but the same result can be achieved in code with a phpmailer_init hook if you prefer fewer plugins.
No. The From address must belong to a domain you can add SPF and DKIM records to, otherwise receiving servers will treat the message as spoofed.

Related guides