A WordPress contact form not sending email is one of the quietest failures a site can have. The visitor fills it out, sees a green thank you message, and walks away thinking they reached you. Nobody on your side ever sees it. No error, no bounce, nothing in the dashboard telling you that leads have been vanishing for weeks.
I have run into this on client sites, on store sites, and on my own. The fix is rarely the form plugin. It is almost always about how the email leaves the server and whether the receiving mailbox trusts it. Here is the process I follow every time.
Why is my WordPress contact form not sending email?
Out of the box, WordPress sends mail through a function called wp_mail, which hands the message to PHP mail on your host. That works on paper. In practice, the message goes out from a shared server with no authentication, often with a From address that does not match the server sending it. Gmail and Outlook look at that and decide it is probably spam, or they drop it without telling anyone.
The other common causes I see:
- The host has disabled PHP mail entirely, which some do to fight spam from hacked sites.
- The From address is set to the visitor’s email, so your server is pretending to be someone at gmail.com. Receiving servers reject that fast.
- The domain has no SPF record, or it has one that does not include the service actually sending the mail.
- A caching or security plugin is blocking the form’s submission request, so the email never gets triggered at all.
- The notification is going to an old address that nobody checks anymore.
That last one sounds silly. It is also the first thing I check, because it takes ten seconds.
Send through real SMTP instead of PHP mail
The single biggest improvement is routing form mail through an authenticated SMTP service. That can be the mailbox provider you already pay for, like Google Workspace or Microsoft 365, or a transactional email service built for sending from websites. An SMTP plugin swaps out the default wp_mail behavior so every message logs in to a real mail server before it goes out.
When I set this up, I follow a few rules:
- Use a dedicated sending address on the site’s own domain, something like a no-reply or forms address. Never the visitor’s address.
- Put the visitor’s email in the Reply-To field. You still hit reply and answer them directly, and the From line stays honest.
- Store the SMTP credentials in
wp-config.phpor the plugin’s constants if it supports them, instead of the database, so they survive exports and are less exposed. - Send a test from the SMTP plugin’s own test screen before touching the form.
If the test email lands in the inbox, the pipe works. If it does not, there is no point debugging the form yet.
Set up SPF, DKIM and DMARC on the domain
SMTP gets the message out. DNS records are what convince the receiving server that you are allowed to send it. All three live in your domain’s DNS, wherever that is managed.
- SPF is a TXT record listing which servers may send mail for your domain. If you use Google Workspace and a transactional service, both need to be in the same single SPF record. Two separate SPF records break it.
- DKIM adds a signature to each message. Your email provider gives you a key to publish as a DNS record, and then you switch signing on in their dashboard.
- DMARC tells receivers what to do when SPF or DKIM fails, and sends you reports. I start with a monitoring policy of
p=noneso nothing gets blocked while I read the reports, then tighten it later.
I check these with a free DNS lookup tool after publishing, because typos in TXT records are easy to make and hard to spot by eye. DNS changes can also take a while to show up, so I do not panic if the first test after an edit still fails.
Log every message the site sends
This is the step most people skip, and I think it matters more than anything else on this list. An email log plugin records every message WordPress tries to send: who it went to, the subject, and whether the mail server accepted it. When a client tells me they never got a lead, I can open the log and know in a minute whether the site sent it.
I also turn on form entry storage in the form plugin itself. If email fails completely, the submission still exists in the database. You lose speed, not the lead. On every store and company site I have managed, that backup has paid for itself at least once.
How do I test a contact form properly?
A test where you fill out the form once and see an email arrive is a start, but it does not cover much. Here is the checklist I run after any change to mail settings, hosting, or plugins:
- Submit the form from a phone on mobile data, not from your office network, so you see what a real visitor sees.
- Use a test address at a different provider than the one receiving the notification. Gmail sending to Gmail can hide problems.
- Check the inbox, then the spam folder, then the email log, in that order.
- Open the received message and view the original headers. Look for SPF pass, DKIM pass and DMARC pass.
- Reply to it and confirm the reply goes to the visitor, not to your own no-reply address.
- Repeat the test for every form on the site. Quote forms, contact forms and wholesale applications often have separate notification settings.
Then I put a reminder on the calendar to do a quick submission every month. Plugins update, passwords change, someone edits DNS for an unrelated reason. Forms break quietly, so the only way to catch it is to check on purpose.
What I would do first on a broken site
If you are staring at a form that is not delivering right now, do these in order: confirm the notification address is correct, install an SMTP plugin and send its test email, install an email log, and look up your SPF record. Most of the sites I have fixed were working again before I ever got to DKIM. Then set a monthly test submission on your calendar, because the form that worked last month is the one nobody is watching.