Back to the blog
Engineering Published 16.09.2026 6 min read

When the contact form says “Thank you” but no mail arrives

A contact form can break without anyone seeing an error: the visitor gets a friendly confirmation, you get nothing. Why it happens, and how to notice in time.

Imagine a small physiotherapy practice. Its website has a contact form, and the form works – or at least it looks like it does. Visitors fill it in, click “Send” and see a friendly “Thank you, we will get back to you soon”. What nobody sees: the messages stopped reaching the practice's inbox some time ago. There is no error, no bounce in anyone's inbox, no red light anywhere. The form fails silently.

Why nobody notices

A form's “Thank you” page usually means only one thing: the website handed the message on. Whether a mail server accepts it, files it as spam or rejects it along the way happens later, out of the form's sight. PHP's mail() function, for example, reports success as soon as the local system accepts the message for delivery – not when it reaches anyone. So the visitor gets a confirmation and moves on. The owner, meanwhile, sees an empty inbox and assumes it is just a quiet month. Fewer enquiries are rarely alarming on their own: holidays, the weather, the economy – there is always an explanation that sounds more plausible than “the form is broken”.

A hypothetical timeline
  1. Day 0
    A routine plugin update runs overnight. The site looks exactly as before.
  2. Day 1
    The last message arrives. Nobody knows it is the last one.
  3. Days 2–13
    Visitors keep submitting the form and keep seeing “Thank you”. Nothing reaches the inbox.
  4. Day 14
    Someone calls and asks, slightly annoyed, why nobody ever answered their enquiry.
  5. Day 15
    The cause is found within an hour. The messages from those two weeks are gone – unless the form also kept a copy.
Not a real case – but a very typical pattern.

The usual causes

  • The SMTP password or the mail provider changed. The form keeps logging in with the old credentials and the mail server refuses – silently, as far as the visitor can tell.
  • PHP mail() without authentication. The web server sends mail directly, without logging in to a proper mail server. Many receiving servers treat such mail as suspicious: it lands in spam or is rejected outright.
  • SPF, DKIM and DMARC don't line up. Many forms put the visitor's address in the From field. The message then claims to come from, say, a gmail.com address but is sent by your web server – exactly what DMARC is designed to stop.
  • A plugin update or theme change breaks the form or its CAPTCHA. A changed template drops a field, a script no longer loads, or the CAPTCHA widget appears without its script – and every submission fails validation.
  • The receiving mailbox is full. The mail server refuses new messages, and the bounce goes to an address nobody reads.
  • The cookie banner blocks the form script. If the consent tool classifies the CAPTCHA or the form script as “marketing”, visitors who decline cookies may get a form that cannot be submitted, or whose submissions are rejected because a token is missing.
  • An expired TLS certificate or domain. Visitors see a browser warning and leave, or the mail server can no longer be reached securely. If the domain of the receiving mailbox expires, mail to it simply stops.
  • A caching layer serves stale pages. A full-page cache can deliver a form with an expired security token (a nonce or CSRF token). The server rejects the submission, and depending on the setup the visitor sees no clear error.

The From address trap

The third cause deserves a closer look, because many form setups have it built in by default. DMARC checks whether the domain in the visible From address matches a domain that SPF or DKIM vouch for. If the form sends a message “from” the visitor's address, your server is not authorised to send for that domain, so the check fails. Depending on the DMARC policy of the visitor's domain and on your own mail provider, the message lands in spam or is rejected. The fix is simple: send from an address on your own domain and put the visitor's address in Reply-To. Clicking “Reply” still reaches the visitor.

Two ways to send the same form message
Fragile
  • From: the visitor's address
  • No Reply-To
  • PHP mail() straight from the web server
  • No SPF, DKIM or DMARC for the sending domain
  • The message exists only as an e-mail
Robust
  • From: an address on your own domain, e.g. form@yourdomain
  • Reply-To: the visitor's address
  • SMTP with authentication or a sending service
  • SPF, DKIM and DMARC set up and aligned
  • A copy is also stored in the database
The right column is hardly more work – it is mostly configuration.

What to do

  1. 1Send a test message through your own form regularly – at least monthly, and always after updates, theme changes or changes to the mail settings. Mark it clearly as a test so nobody answers it.
  2. 2Know your normal rhythm. If the form usually brings a few messages a week, two weeks of silence is a reason to check, not a quiet month.
  3. 3Send via SMTP with authentication – through your mail provider or a dedicated sending service – instead of relying on PHP mail().
  4. 4Use your own domain in From and the visitor's address in Reply-To. Then set up SPF, DKIM and DMARC for that domain so the messages pass the checks.
  5. 5Keep a copy of every submission in the database. Many form plugins offer this, sometimes as an add-on. If mail fails, the enquiries are still there.
  6. 6Check the form after every plugin update – including the CAPTCHA, and also with cookies declined.

Checks like these are easy to forget, which is why it is worth automating them. With an account and a verified domain, formexposed can send a clearly marked test submission and check whether it actually arrives (the delivery check, opt-in only). It also detects silence – a form that normally gets messages suddenly getting none – and checks SPF, DKIM and DMARC of the notification mails as well as TLS certificate and domain expiry. You are alerted only when something changes.

If you just want a first look: a free check on formexposed.com needs no account and submits nothing. Among other things, it shows whether a CAPTCHA is present but broken – a widget without its script, a public test key, errors in the browser – one of the quieter ways a form stops working. Whether messages really arrive can only be confirmed by a real test message, so send one today.