Your order emails stopped arriving, and it's probably not your website
Missing order confirmations and contact form notifications are among the most common problems we get called about, and among the least likely to be caused by the website. Here is where they actually go.
Somebody places an order. The order appears in the admin. The customer never gets a confirmation, and neither do you. Nothing about the website has changed, and the last time anybody looked, it worked.
This is one of the most common calls we get, and it's almost never a bug in WooCommerce, WordPress or your contact form. The website and your email share a domain name and very little else: different infrastructure, different records, different failure modes, and usually different suppliers.
The first question: did it leave the building?
There are two completely different failures here, with different fixes, and confusing them wastes days.
- The message never left your server. PHP mail failed, a plugin errored, a queue stalled, or the host blocked the send. The mail log will show nothing, or an error.
- The message left and was refused or filed as spam. The mail log shows it going out. What happens after that's decided by the receiving system, and it's a reputation and authentication problem.
The server's mail log answers this in about a minute, and everything you do next depends on the answer. If your host won't give you access to it, that's worth knowing about your host.
Why sending from your web server has stopped being reliable
For years, websites sent email using PHP's built-in mail function directly from the web server. That approach has quietly stopped working well, for reasons that have nothing to do with your site.
Receiving systems now expect email to be authenticated. Mail from a web server typically isn't, or is authenticated for a domain that doesn't match the address it claims to be from. Add a shared IP address whose reputation depends on the behavior of every other site on the machine, and a large share of perfectly legitimate order confirmations end up quarantined or silently dropped.
The three records that decide whether you're trusted
These are DNS records for your domain. They tell receiving mail servers who is allowed to send on your behalf and what to do if something doesn't match.
| Record | What it does | What goes wrong |
|---|---|---|
| SPF | Lists which servers are permitted to send email using your domain. | Missing entirely, or missing the service you actually send through. Also commonly broken by having two SPF records, which is invalid, or by exceeding the ten-lookup limit after adding several services. |
| DKIM | Signs each message cryptographically so the receiver can confirm it wasn't altered and did come from an authorized sender. | Never set up, or set up for one sending service and not the others. Frequently forgotten when a business changes email providers. |
| DMARC | Tells receivers what to do when SPF and DKIM don't line up, and can send you reports about who is sending as your domain. | Set to a strict reject policy before SPF and DKIM were correct, which very efficiently blocks your own legitimate email. |
SPF, DKIM and DMARC explained
The order matters. Get SPF and DKIM correct and verified first, then introduce DMARC in monitoring mode, then tighten it. Publishing a strict DMARC policy on a domain whose authentication is incomplete is a reliable way to stop your own invoices reaching customers.
Host limits nobody mentions
Shared hosting almost always caps outbound mail per hour or per day. The cap is usually in the terms rather than in the control panel, and nothing on your dashboard tells you when you reach it. Messages over the limit are typically held and retried rather than sent, and may eventually bounce with a message naming the limit. Both states are visible in the mail log and the mail queue, which is another reason access to them matters.
A store that sends a confirmation, an admin notification, a shipping update and a review request per order reaches a modest hourly cap faster than expected on a busy day, which is exactly the day it matters.
Things that look like this and aren't
- The address is a distribution list or an alias that silently drops mail from outside, which is common in organizations with strict mail policies.
- The order status is wrong. In WooCommerce, some emails only fire for certain status transitions. If payment didn't complete, the confirmation isn't supposed to send.
- A plugin is intercepting mail. Logging and SMTP plugins can queue or swallow messages, particularly if a queue has stalled or an API key has expired.
- The customer typed their address wrong. Worth ruling out before investigating anything, and easily checked against the order record.
How to work through it
- Check the mail log. Did the message leave the server at all?
- Check whether the address is receiving mail from anywhere else.
- Check SPF, DKIM and DMARC for the sending domain, and confirm they cover the service actually doing the sending.
- Check for host sending limits, and for queued messages sitting unsent.
- Move transactional email to an authenticated sending service if it's not already there.
- Send test messages to several providers, not just to your own address. Delivery varies significantly between them and testing to one is misleading.
Then put something in place that watches
The reason this problem gets expensive is that it's silent. Nothing tells you email has stopped, so you find out from a customer, or from a month of orders that never got confirmed.
Whatever you end up doing, add something that notices. A monitored send, a delivery report, an alert when sending fails. It's a small piece of work and it converts a problem you discover in six weeks into one you discover in an hour.