WordPress Problem Solving

WordPress Not Sending Emails? How to Fix It With SMTP

Why WordPress email goes missing and how to fix it for good: test what is really happening, send through SMTP or a provider API, add SPF, DKIM and DMARC, and correct the From address in forms and WooCommerce.

WordPress Not Sending Emails? How to Fix It With SMTP

Form notifications that never arrive, password resets that vanish, order confirmations in the spam folder. A report of WordPress not sending emails usually turns out to be WordPress sending them and the receiving mail server throwing them away. Out of the box, WordPress hands every message to the web server's local mail function with no authentication, from an address that may not exist. Mailbox providers have little reason to trust mail like that.

The lasting fix has three parts: send through an authenticated mail service by SMTP or API, publish SPF, DKIM and DMARC records for your domain, and use a From address on that domain. Before any of it, find out which kind of failure you have.

The usual reasons for WordPress not sending emails

Every message from core, plugins, forms and WooCommerce passes through one function, wp_mail(). It uses the PHPMailer library that ships with WordPress, and by default PHPMailer gives the message to PHP's mail() function, which passes it to whatever mail program the server runs. Several things go wrong on that path:

  • The host has disabled mail(), or caps the number of messages per hour.
  • The web server is not listed as an allowed sender for your domain, and the message carries no DKIM signature.
  • On shared hosting, the sending IP address is shared with other customers, and its reputation is theirs as much as yours.
  • The default sender is wordpress@ followed by your domain, a mailbox that normally does not exist.
  • Nothing records a failure. wp_mail() returns true as soon as the message is handed over, which says nothing about delivery.

Find out whether mail is unsent or undelivered

These are different problems with different fixes, and one test separates them. With WP-CLI over SSH:

wp eval 'var_dump( wp_mail( "you@example.com", "WordPress mail test", "Sent with wp_mail." ) );'

If it prints bool(false), sending failed on the server: mail() is disabled or the SMTP settings are wrong. If it prints bool(true) and nothing reaches the inbox or the spam folder, the message left the site and was dropped or filtered on the way, which is an authentication or reputation problem.

Without SSH, use the "Lost your password?" link on the login screen for your own account. Send tests to addresses at two different mailbox providers, because each one filters differently. When a test lands in spam, open the full headers (in Gmail, "Show original" in the message menu) and read the SPF, DKIM and DMARC results. A "fail" or "none" there is your answer.

To catch failures as they happen, log them. Put this in a small plugin, not in the theme:

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

Send through SMTP or a provider API

The cure for unauthenticated mail is to stop sending from the web server. There are three ways to do it.

OptionFitsWatch for
SMTP login to a mailbox you already have, from your host or your office emailLow volume: form notifications and password resetsHourly or daily sending limits, and a mailbox password stored on the site
A transactional email service over SMTPStores, course sites and membership sites that need volume and delivery reportsThe domain must be verified in DNS, and the host must allow outgoing connections on port 587
A transactional email service over its HTTPS APIHosts that block SMTP ports, and sites that send a lotNeeds a plugin or custom code written for that provider

Plugins such as WP Mail SMTP, FluentSMTP and Post SMTP add the settings screen and a test button, and some include an email log. For most sites a plugin is the sensible route. A developer who prefers code can configure PHPMailer directly. Define SMTP_HOST, SMTP_USER and SMTP_PASS in wp-config.php, which keeps the credentials out of the database, and add this to a small plugin:

add_action( 'phpmailer_init', function ( $phpmailer ) {
    $phpmailer->isSMTP();
    $phpmailer->Host       = SMTP_HOST;
    $phpmailer->Port       = 587;
    $phpmailer->SMTPSecure = 'tls';
    $phpmailer->SMTPAuth   = true;
    $phpmailer->Username   = SMTP_USER;
    $phpmailer->Password   = SMTP_PASS;
} );

Port 587 with STARTTLS is the standard for submitting mail, and port 465 uses TLS from the first byte ('ssl' in PHPMailer). Port 25 is meant for traffic between mail servers and is blocked by many hosts. Take a backup before adding code like this to a live site, and test on staging if you have one.

Publish SPF, DKIM and DMARC for your domain

Changing how mail is sent is half the job. The other half is three DNS records that let receivers confirm the mail is yours. Add them where the domain's DNS is managed, which may be the registrar, the host or a CDN.

  • SPF is a TXT record on the domain that lists the servers allowed to send for it. A domain may have only one SPF record. If one exists, add the new service's include: to it. A second record makes both invalid.
  • DKIM is a signature the mail service adds to every message. You publish the matching public key as a TXT or CNAME record under a name ending in _domainkey. The service gives you the exact record.
  • DMARC is a TXT record at _dmarc.example.com. It tells receivers what to do when a message fails both checks for the From domain, and where to send reports.

A sensible first DMARC record only observes:

v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com

Once the reports show that every legitimate sender passes, move the policy to quarantine and later reject. Remember the other systems that send as your domain: office email, the newsletter tool, the CRM, the invoicing system. Each needs to be covered. Google's email sender guidelines ask every sender for SPF or DKIM, and bulk senders for all three.

Use a From address that matches the domain

Set the From address to a real mailbox on the domain you just authenticated. A free webmail address as the sender fails the DMARC check when the mail goes out through any other server.

Contact forms deserve a separate look. Many are configured to send "from" the visitor's own address so that Reply works. Your server has no right to send for the visitor's domain, so receivers reject the message. Put your own address in From and the visitor's address in Reply-To. SMTP plugins have a setting that forces the From address for all mail. In code, two filters do it:

add_filter( 'wp_mail_from', function () {
    return 'website@example.com';
} );
add_filter( 'wp_mail_from_name', function () {
    return 'Example Company';
} );

Check each form's notification settings

With delivery fixed, check what each plugin is trying to send. Every form has its own notification settings: the recipient (often an old address or the site admin placeholder), the From and Reply-To fields, and any conditional rules. Submit each form once after changing mail settings. Know also whether the form plugin stores entries. Contact Form 7, for one, does not keep submitted messages unless you add its companion plugin Flamingo, so an undelivered email there is a lost inquiry. If leads matter, store them or send form entries to your CRM as well as by email. We set up notification routing as part of WordPress form development.

Check WooCommerce order emails

WooCommerce sends through wp_mail() too, so the SMTP setup covers it. Each notification is switched on and addressed under WooCommerce > Settings > Emails. An order that stays at "Pending payment" sends no confirmation. That is the payment gateway failing to report back, not a mail fault. Recent versions also record email attempts under WooCommerce > Status > Logs, and the vendor's email FAQ lists further checks. For a store, missing order emails are a support cost, and they are among the first things we test on a WooCommerce site we take over.

Keep it working, and know when to hand it over

Email breaks quietly, so give yourself a way to notice. Keep an email log and clear it on a schedule, since it holds personal data. Look at the bounce and complaint figures in the mail service's dashboard now and then. Send a test after every change to DNS, hosting or the mail plugin.

Most owners can do the plugin setup and the DNS records in an afternoon. Ask for help when several systems send as your domain and the SPF record has grown past what receivers will evaluate, when a custom plugin calls mail() directly and bypasses your settings, or when a store or course site sends enough volume to need queuing and monitoring. Mail delivery checks are part of our WordPress maintenance plans for that reason.

Frequently asked questions

Do I need a plugin, or can SMTP be configured in code?

Both work. The phpmailer_init hook is enough to route all mail through SMTP. A plugin adds a test button, a log and support for provider APIs, which is why most site owners are better served by one.

Why do emails reach one mailbox provider and not another?

Each provider applies its own filters and keeps its own reputation data for your domain and sending address. Check that SPF, DKIM and DMARC all pass in the headers of a delivered message, then look at the provider's postmaster tools for your domain.

Can I send WordPress email through a free webmail account?

For a small site it can work, if your SMTP plugin supports that provider's sign-in method. The From address has to be that mailbox, daily limits apply, and a business site looks more credible, and is easier to authenticate, with an address on its own domain.

How long do SPF and DKIM changes take to work?

Often minutes, and at most as long as the record's TTL, which can be several hours. Use the verify button in the mail service's dashboard, then send a fresh test and read the headers again.

Add WorldWin Coder to your preferred sources

Add worldwincoder.com as a preferred source on Google, or open this article in your AI assistant to use it as a source.

Swati Priyadrshni
· Founder & CEO at WorldWin Coder

I'm Swati Priyadarshani, Founder & CEO of LMS Advisor and Co-Founder of WorldWin Coder Pvt. Ltd. (est. 2019). Over the last 10+ years, I've helped enterprises build learning platforms that actually get used - not just deployed.

Keep reading

Have something to build, fix or move?

Tell us where you are. A developer reads every inquiry, and you get next steps and a free quote within one business day.