Create Accountor Login
WordPress

WordPress Email Not Sending: Find the Break in Order

· 7 min read

Hand holding a pen over a notebook checklist with a sticky note
Photo by Jakub Zerdzicki on Pexels

Why WordPress Mail Fails Without an Error

WordPress email usually stops because the server sends it with no authentication, from an address that does not match the server, and the receiving mailbox silently drops it. WordPress itself reports success in nearly every one of these cases. This is for site owners and developers whose password resets, form notifications, or order receipts have gone missing, and who want a way to find the break instead of trying plugins at random.

A True Return Value Is Only a Handoff

Every email WordPress sends passes through one function, wp_mail(). The WordPress developer reference is direct about what its return value means: a true result does not mean the user received the email, only that the method used was able to process the request without errors.

So the site shows "message sent," the log in your form plugin says "sent," and the customer sees nothing. The failure happened after WordPress was finished, on the server or at the receiving mailbox, and neither reports back to your dashboard. A failure inside PHP itself triggers the wp_mail_failed action, which is the one place WordPress does raise a flag, but it covers only a small slice of what can go wrong.

Why Host Mail Gets Dropped

By default wp_mail() hands the message to PHP's mail machinery on the web server, and on many shared hosts that means a local sendmail process. Messages leave from the host's IP address with no DKIM signature for your domain and often no SPF entry that covers that host. Some hosts block outbound mail entirely to protect their IP reputation, and others throttle it to a few messages per hour.

Gmail's own error reference describes the result. A rejection reads like 550 5.7.26 This email has been blocked because the sender is unauthenticated, and Gmail states that it requires senders to authenticate with SPF or DKIM (Gmail SMTP error reference, checked October 2026). If your contact form mail never reaches a Gmail address, that rejection text is the first thing to hunt for.

The from Address Problem

WordPress sends as wordpress@yourdomain.com unless you change it. That address rarely exists, which is harmless until a receiving server checks whether it can verify the domain. If the sending server is not authorized in your SPF record and nothing signs the message with your domain, the message is unauthenticated for exactly that domain. Our guide to DMARC alignment explains why a pass on the wrong domain still fails.

The trap that catches contact forms most often is a form plugin that sets From to the visitor's own address, jane@gmail.com, so replying is easy. Your server is not authorized to send as gmail.com and nothing signs the message with that domain, so it fails authentication for the very address people see, and many receivers reject or filter it. The standard fix is to send from an address on your own domain and put the visitor's address in Reply-To.

Overhead view of a woman at a desk with a laptop, phone, and notebooks
Photo by energepic.com on Pexels

Plugins That Skip Wp_mail Altogether

Some plugins open their own connection to a mail service and never call wp_mail(). Anything you configure at the WordPress level has no effect on those messages, and they fail for reasons that look identical from the outside. This is the case that wastes the most time. You tune SMTP settings for an hour, and the missing messages were never going through the function you were tuning.

Form builders, membership tools, and some help desk plugins are the usual suspects, and the cure is to check each plugin's own mail settings for a toggle that routes through WordPress. The fastest test is a send log. If the message you expected is absent from a log that records every wp_mail() call, something bypassed it.

Why It Often Starts After a Move or a Change

Email that worked for years and then stops usually follows a change. A site moved to a new host starts sending from a different server, and the SPF record that listed the old host no longer covers it. A new SMTP plugin replaces a working one with a typo in the password. A DNS edit for something unrelated drops a DKIM record. A form plugin update changes how the From header is built.

Ask what changed in the week before the first complaint. The answer is often in your own change history, and it points at the layer to check first, which saves most of the steps below. Sites with no record of what changed are the hardest to diagnose, so write the answer down when you find it.

Finding the Break in Order

Work from the cheapest check to the most involved. Each step rules out one layer, and most sites are fixed by the third or fourth.

Send a Test and Keep a Record

Before changing anything, get evidence. A logging plugin, or the log built into a mail plugin, records recipient, subject, time, and what the mail layer said back. Send a test to a Gmail address and another to a different provider, so you see whether the problem is universal or specific to one receiver.

If your site has none, add a small hook that writes failures to the PHP error log. The wp_mail_failed action receives a WP_Error with the recipients, subject, and the exception message from the mail library, which names problems like a refused connection or a rejected sender.

Read the Bounce Message

Check the spam folder first, since it takes ten seconds. Then look for a bounce. A message rejected by the receiving server sends a non-delivery report to the From or envelope address, which on a default WordPress install is an address nobody reads. Pointing the From address at a mailbox you watch lets the reason arrive.

The three-part code in the bounce tells you where to go next. A 5.7.x code points at authentication or policy. A 5.1.x code points at a bad recipient address. A 4.x.x code means temporary deferral, usually throttling, and the sender will retry.

Set a Sender Address on Your Own Domain

A sender address is also a promise about where replies go. Pick one that a person actually reads, because customers do answer automated receipts. Choose one real address on your domain and apply it site-wide, such as notifications@yourdomain.com, with the visitor's address in Reply-To for form mail. Setting this in a theme functions file works until the theme updates and the snippet disappears, so put it in a plugin setting you will not forget.

It also makes the next step possible, because authentication is configured per sending domain and has to match the From address you chose.

Authenticate the Domain

The domain needs an SPF record that includes whatever actually sends the mail, a DKIM key for that sender, and a DMARC record. The SPF syntax guide and the DKIM setup guide cover the records themselves, and why emails go to spam covers what happens when delivery works but placement does not.

Records live in DNS, so changes to them are DNS work. Check the exact hostnames carefully, because a panel that appends your domain automatically turns a full hostname into a doubled one that nothing will look up.

Ask the Host Two Direct Questions

If the test sends never reach any receiver and no bounce comes back, the host is the next suspect. Ask support whether PHP mail is allowed on your plan and what the hourly sending limit is, and whether outbound SMTP ports are blocked. Some hosts close port 25 and others restrict the submission ports, which breaks every SMTP plugin pointed at an outside provider even when the credentials are perfect.

The answers also tell you which fix will hold. A plugin that talks to a mail service over HTTPS, port 443, does not depend on any mail port being open, because the host has to leave web traffic alone for the site to function.

Stop Sending from the Web Server

The durable fix is to send through a service built for it. Two broad options exist. A general SMTP plugin connects WordPress to a mail provider with a host, port, and credentials. An API-based plugin skips SMTP and makes an HTTPS request.

Our free Email Delivery for Cloudflare plugin takes the second approach. It replaces wp_mail() and sends through Cloudflare Email Service using your Account ID and an API token, with a send log in your own database and a test send tab. Setup needs your domain on Cloudflare DNS, a Workers Paid plan, and the domain onboarded for Email Sending. Cloudflare's documentation, updated June 2026 and checked October 2026, lists 3,000 outbound emails included per month and then $0.35 per 1,000, and still labels Email Sending as beta. The plugin is free, the sending is Cloudflare's. Read the plugin documentation for the setup order, and if you would rather compare it with other plugins, the comparison pages lay them out.

Man working at an office desk with a computer in daylight
Photo by Andrea Piacquadio on Pexels

Getting It Handled for You

If you would rather not run this yourself, the Transactional Email service is built for mail that your website generates, such as receipts, password resets, and form notifications. Email Authentication publishes and watches the SPF, DKIM, and DMARC records, and Managed WordPress Hosting is the place to look when the root cause turns out to be the host instead of the domain.

Keep Reading

WordPress WordPress Maintenance Mode: What It Actually Protects, and What It Does NotMaintenance mode is a holding page and nothing more. Why sites get stuck in it, how to clear the .maintenance file, and what it does not protect you from.Read the article WordPress WordPress Missed Schedule: Why WP-Cron Skipped Your PostMissed schedule means WP-Cron never ran the job that publishes your post. Why it happens, how to check the queue, and the cron fix that holds.Read the article WordPress WordPress White Screen of Death: Find the Fatal ErrorA blank WordPress page is a PHP fatal error with the message hidden. How to turn on the debug log, read it, and get the site back in the right order.Read the article WordPress WordPress Security Checklist: What to Fix Once and RecheckA WordPress security checklist split into settings to fix once and checks to repeat: updates, logins, file permissions, backups, scans, and a quarterly review.Read the article WordPress WordPress MCP: How to Connect an AI Assistant SafelyHow WordPress MCP works, from the Abilities API to the official adapter, and how to connect an AI assistant using OAuth, profiles, and a staging copy first.Read the article Zoho Zoho Deluge: What It Is, Where It Runs, and How It Fails QuietlyDeluge is the scripting language built into Zoho. Where it runs, the places it hides across your apps, and how it fails without anyone noticing.Read the article Email SPF Record Syntax: How the Record Is Built and Why It BreaksAn SPF record lists the servers allowed to send mail using your domain. What each mechanism means, how the record is read, and where it usually breaks.Read the article Operations DNS Record Types: Which Ones Actually Break ThingsA working guide to the DNS records you actually meet, what each one does, and the specific way each one fails when something stops resolving.Read the article Agency Outsourcing Web Development: What Actually Goes WrongThe four ways agencies buy development, the arithmetic behind each one, and the failure modes, including when the honest answer is to turn the work down.Read the article

Ask Us Anything

We’d love to hear from you!