Stop Contact Form Spam Without Killing Real Inquiries
How I reduce contact-form spam on client sites: honeypots, time checks, and rate limits—before a captcha that scares mobile users away.
On this page
A contact form that fills the inbox with casino links gets ignored. A form that demands a puzzle on every phone gets abandoned. The useful middle is quiet spam control.
Start with the inbox, not a new plugin
Confirm real mail still arrives: send a test from a phone on mobile data to the client’s actual address. If SMTP is broken, “anti-spam” is a distraction—you are already losing legitimate leads.
Use an authenticated SMTP sender. Shared-host PHP mail() is both unreliable and easier to spoof.
Controls that do not punish people
- Honeypot — a field hidden from users that bots still fill. Reject the submission when it is non-empty.
- Minimum time — reject posts that arrive in under two seconds. Humans do not complete a name, email, and message that fast.
- Rate limit — a few posts per IP per hour. Enough for a retry, not enough for a script.
- Allow-list the fields — ignore unexpected inputs. Do not email raw HTML from the message body.
These four remove a large share of dumb bots without a captcha.
When a captcha is justified
Turn on a visible challenge only after the quiet controls fail, and prefer one that stays invisible for most visitors. Put it on the form that is actually abused (often /contact/), not on every newsletter box in the footer.
Tell the client what changed. A sudden drop in form email can be “spam stopped” or “SMTP died.” They cannot tell from silence.
WordPress notes
- one forms plugin, not three;
- disable the default
wp-comments-postflood if the site has no blog comments; - do not store every spam attempt forever in
wp_posts—it bloats backups; - log rejected reasons on staging while you tune thresholds, then keep production logs short.