Skip to content

How to Debug wp_mail in WordPress (Step-by-Step Guide)

Email delivery is one of the most common pain points in WordPress. Whether it’s contact form messages not arriving, WooCommerce receipts disappearing, or password resets going missing, the culprit often lies in how WordPress sends email with the wp_mail() function.

In this guide, you’ll learn how to debug wp_mail in WordPress using built-in hooks, error logging, and PHPMailer diagnostics—so you can pinpoint issues fast and ensure your site’s emails actually arrive.

If your WordPress site isn’t sending emails, the fastest way to debug wp_mail() is to enable logging and hook into WordPress’ built-in email actions.

Start by turning on WP_DEBUG_LOG so all errors are written to wp-content/debug.log.

Then, capture failures with the wp_mail_failed hook and log successful sends with wp_mail_succeeded.

For deeper insights, enable PHPMailer’s debug output using the phpmailer_init hook to see SMTP connection details.

Finally, send a controlled test message to confirm settings.

This combination of logging, hooks, and PHPMailer diagnostics gives you a clear picture of why emails succeed or fail—and makes debugging WordPress email problems much easier.

Key Takeaways

  • Use WP_DEBUG_LOG to capture detailed logs in debug.log.
  • Always hook wp_mail_failed and wp_mail_succeeded to track both problems and successes.
  • Leverage phpmailer_init to see SMTP-level details when diagnosing connection/authentication issues.
  • Run controlled test emails to quickly confirm whether your fixes work.
  • Most email issues boil down to server restrictions, authentication errors, or DNS/SPF/DKIM configuration.

Enable WordPress Debug Logging

Before you can capture mail errors, turn on WordPress’ debug log. Add this to your wp-config.php:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
// Optional: set a custom log path outside webroot
// define( 'WP_DEBUG_LOG', dirname(__DIR__) . '/logs/wp-debug.log' );

This creates (or writes to) a debug.log file in your wp-content/ folder. Errors and custom logs will go here.


Catch Failed wp_mail Calls

Since WordPress 4.4, a dedicated hook exists for logging mail failures:

add_action( 'wp_mail_failed', function( $wp_error ) {
    error_log( 'wp_mail_failed: ' . print_r( $wp_error->get_error_messages(), true ) );
    error_log( 'wp_mail_failed data: ' . print_r( $wp_error->get_error_data(), true ) );
});

This will dump the failure reason and data into debug.log. Great for spotting missing “From” headers, blocked ports, or malformed addresses.


Log Successful wp_mail Calls Too

Don’t just log failures. Sometimes you’ll want to confirm what did send:

add_action( 'wp_mail_succeeded', function( $mail_data ) {
    error_log( 'wp_mail_succeeded: ' . print_r( $mail_data, true ) );
});

This hook logs recipients, headers, and subject lines—helpful when only some messages go through.


Enable PHPMailer Debug Output

Under the hood, wp_mail uses PHPMailer. You can enable its built-in debug output with the phpmailer_init hook:

add_action( 'phpmailer_init', function( $phpmailer ) {
    $phpmailer->SMTPDebug = 2; // 1 = errors & messages, 2 = client/server msgs, 3–4 = verbose
    $phpmailer->Debugoutput = function( $str, $level ) {
        error_log( "PHPMailer[$level]: $str" );
    };
});

This is invaluable when you’re troubleshooting SMTP connections or authentication.


Test wp_mail Quickly

Instead of guessing, fire off a test message. You can use a quick snippet:

add_action( 'init', function() {
    if ( isset( $_GET['testmail'] ) ) {
        wp_mail( get_option( 'admin_email' ), 'Test WP Mail', 'This is a test message.' );
        wp_die( 'Test mail sent. Check your inbox and debug.log.' );
    }
});

or in WP_CLI:

wp eval "var_dump(wp_mail(get_option('admin_email'), 'Test Mail', 'Body'));"

Common Causes of wp_mail Issues

Even with logging, many problems trace back to these root causes:

  • Server blocks: Hosting provider blocks port 25/587.
  • Authentication: Wrong SMTP credentials or missing API key if using an external mailer.
  • Spam filters: No SPF/DKIM/DMARC records → emails marked as spam.
  • Headers: Missing or invalid “From” address.

Use logs to confirm the exact failure, then fix configuration or DNS accordingly.


Keep Privacy in Mind

While logging, avoid dumping entire message bodies or PII into debug.log on a production site. Instead, log metadata (subject, recipient count) and detailed errors.

Debug wp_mail Checklist

  • ✅ Enable WP_DEBUG_LOG in wp-config.php.
  • ✅ Hook into wp_mail_failed to capture errors.
  • ✅ Hook into wp_mail_succeeded to log successful sends.
  • ✅ Use phpmailer_init for SMTP-level debug output.
  • ✅ Send a controlled test email (snippet or WP-CLI).
  • ✅ Review server settings: open ports, valid SMTP credentials.
  • ✅ Verify DNS records: SPF, DKIM, and DMARC.
  • ✅ Check that your “From” header is valid.
  • ✅ Avoid logging sensitive data (only log metadata and errors).

Final Thoughts

Debugging wp_mail doesn’t have to be a guessing game. With WordPress hooks and PHPMailer’s debug tools, you can trace exactly what’s happening when your site tries to send email.

Set up these logging hooks once, and you’ll always have the insight you need to troubleshoot email issues like a pro.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.