Skip to main content
Login

WordPress Contact Form Not Sending Emails: What's Actually Wrong

Your WordPress form says the message sent. No email shows up. Here's the actual reason, the 10-minute test to confirm it, and what fixes it.

Someone fills out your contact form. The page confirms it: “Thanks, we’ll be in touch.” They close the tab and wait to hear from you.

You never call, because you never got the message. No email arrived, not that day, not ever. The lead just sits there in the quiet, then goes looking for the next business whose form actually works. Nothing on the screen ever told either of you it failed.

How WordPress actually sends this mail

Here’s the plumbing, in plain terms. When someone submits a WordPress form, the site calls a function named wp_mail, which by default hands the message to PHP’s built-in mail() function instead of a dedicated email service. PHP mail doesn’t log in anywhere, doesn’t prove it’s really you sending it, and doesn’t route through the kind of verified infrastructure Gmail or Outlook expect from a legitimate sender. It just asks your web server to push an email out the door and hopes for the best. That used to be good enough. It mostly isn’t anymore, because mail providers have raised their guard against exactly this kind of unauthenticated, low-effort delivery, and a plain mail() call rarely clears the bar.

The email pretends to come from you, and nobody buys it

Your contact form is usually set to send “from” an address like you@yoursite.com, or from something that doesn’t even exist, like wordpress@yoursite.com. The From field claims it’s you, but the server actually doing the sending was never authorized to send mail as your domain. Every major mail provider checks for that authorization now. When it’s missing, they don’t bounce the message back with a clear error you’d notice. They quietly drop it, or file it somewhere you’ll never open. Your site isn’t broken in any way you’d catch by looking at it. It’s making a claim it can’t back up, and providers have stopped taking that claim on faith.

Your host won’t send the mail, or won’t send much of it

Not every hosting plan lets a site send email freely. Shared hosting in particular often caps how many messages a domain can send per hour, or blocks PHP’s mail function outright, because some other customer on the same server once used it to send spam and the host locked the whole feature down. If your host is one of the strict ones, your form can look completely fine (the page confirms, the code runs without error) while the actual send gets swallowed before it ever leaves the building. You won’t see a failure message, because the failure happens on infrastructure you can’t see into.

Your domain can’t prove the mail is legitimate

Even when the mail does get sent, receiving providers check DNS records called SPF and DMARC to decide whether to trust it. Together they’re your domain’s way of stating which servers are allowed to send mail as you, and what a receiving server should do with a message that fails that check. On a WordPress site where nobody set these up on purpose, they’re often missing or misconfigured, and mail from your domain ends up looking exactly like the kind of message these systems exist to filter out. We wrote a full plain-English walkthrough of what these records do and how to check yours in why your website’s emails aren’t arriving. Worth five minutes if this is the failure mode you’re looking at.

It worked, until an update changed something

WordPress core, your theme, and every plugin on the site update on their own schedules, and any one of them can quietly change how mail gets sent. A form plugin update swaps its mail library. A security plugin starts blocking an outbound connection it used to allow. A caching plugin keeps serving the old confirmation page even after the backend send starts failing. None of it shows up as an error on your dashboard, because from WordPress’s point of view, the form submitted successfully. The layer underneath is what quietly stopped working, and an update is the most common reason that layer shifts without anyone touching it on purpose.

The 10-minute test

Before you fix anything, confirm what’s actually happening. This takes about ten minutes and tells you which failure mode above you’re dealing with.

  1. Submit a real test, using an email address that isn’t Gmail: a work address, an Outlook account, whatever you’ve got. Gmail’s spam filtering is aggressive enough on its own that a Gmail-only test can hide a problem a different provider would have caught.
  2. Check the spam or junk folder, not just the inbox, on the address you tested with. A message sitting in spam is a different problem from a message that never arrived at all, and it points you toward the SPF and DMARC section above rather than a host block.
  3. Look at the actual mail log, not the confirmation message. Most hosts have a mail log in cPanel or their control panel, or you can install a free plugin like WP Mail Logging that records every email WordPress attempts to send and whether it succeeded. This one step tells you whether WordPress even tried.
  4. Send a second test to a different provider. If it lands at Outlook but not Gmail, that’s a strong signal you’re looking at an authentication problem specific to how one provider evaluates your domain, not a blanket host block.
  5. Run your domain through Trust Check. It checks your SPF and DMARC records (not DKIM, which needs a different kind of lookup) and tells you in under a minute whether your domain is set up to prove its mail is legitimate. A flag there usually explains everything above it.

The honest fix options

Once you know which failure mode you’re dealing with, the fix is usually one of a few things. None of these is a trick; each is a genuine way to solve it.

Install an SMTP plugin. This is the standard developer answer, and it’s a fair one. An SMTP plugin reroutes your outgoing mail through a real email service instead of PHP’s mail() function, which fixes the authentication problem at the root because the mail is now actually coming from infrastructure providers already trust. It takes about twenty minutes if you’re comfortable creating an API key and pasting it into a settings screen. If you’re not, it’s a reasonable hour of work to hand to a developer.

Switch to a form service. Tools built specifically to handle form submissions, rather than a plugin bolted onto wp_mail, often route notifications through their own verified sending infrastructure, sidestepping the whole problem. You give up a little control over the form’s exact look and behavior. You gain a service whose entire job is making sure the message arrives.

Have someone run the site for you. If you’d rather not learn what SPF stands for, that’s a fair position, not a failure on your part. This is exactly the kind of maintenance that falls through the cracks on a self-managed WordPress site: nobody notices until a lead calls a competitor instead. If you’d rather stop being the one who checks a mail log every time an update breaks something, skip to the never-again option.

Why this keeps breaking

A WordPress site isn’t a thing you finish. It’s a stack of independently updating parts, core, theme, a dozen plugins, the host underneath all of it, and each one can shift the ground the others are standing on. A plugin update six months from now can break this same form again in a completely different way, and it won’t be your fault any more than it’s your fault now. That’s the tradeoff of running software nobody’s actively watching. The most extreme version we’ve seen wasn’t even about a form: 32 hidden spam links sat injected into a veteran-owned moving company’s WordPress code, invisible on the page, quietly dragging down their search rankings until an audit caught it. A broken contact form is the failure you notice, because leads stop calling. A lot of WordPress failures never get noticed at all.

If you never want to debug this again

If you’d rather not be the one running mail logs and reading DNS records every time this breaks, that’s what Surmado Sites handles as part of running the site: hosting and mail delivery, plus the maintenance that keeps a fix from unraveling at the next update. You ask for it once, in plain English, and it stays fixed.

FAQ

Why does the form say sent when nothing arrives?

The “message sent” confirmation is generated by WordPress the moment the form submits and wp_mail gets called. It doesn’t wait to hear back from a mail server about whether the message was actually delivered, because most contact form setups aren’t built to check for that. The confirmation means WordPress attempted the send. It doesn’t mean anyone received it.

Are submissions going to spam?

Sometimes, but not always. If your SPF or DMARC records are misconfigured, mail that does get sent often lands in spam because receiving providers can’t verify it’s really from your domain. If your host is blocking the send outright, or a plugin conflict stops it before it leaves your server, the mail never gets sent in the first place, so it isn’t sitting in spam either. Checking a mail log, or your Trust Check result, tells you which situation you’re actually in.

Why did it stop working after an update?

Because something in that update chain changed how or whether mail gets sent, and none of those changes show up as a visible error anywhere in WordPress. It’s rarely the plugin you’d guess first. That’s why checking the mail log right after any update is worth the two minutes it takes, before you start troubleshooting blind.

Do I need an SMTP plugin?

Not always, but often, yes. If your domain’s SPF and DMARC records check out and the actual problem is a host blocking or limiting PHP mail, an SMTP plugin that routes mail through a real email service is the most direct fix. If the DNS records are the problem, fix those first; a new sending method won’t help if the domain itself still can’t prove it’s legitimate. Either way, an SMTP plugin is a real, common solution, not a workaround, and also one more thing to configure and keep working, which is the part a form service or a managed site takes off your plate instead.

Never deal with this again

Hand Surmado the site. We rebuild it, run it, and keep everything you've built along the way.

How do you feel about your current site?

We rebuild it free and send you a preview. A human checks it before delivery. You pay nothing until you approve it and your domain moves. Most rebuilds are ready within 24 hours.

$99/mo. Hosting, maintenance, and updates included. We rebuild your site free. You see it before you pay anything.

Scout found 32 hidden spam links quietly rotting a veteran-owned mover's WordPress site. Read the case study