The short answer: a form is a door that anyone, and any robot, can try. To keep it spam-free, add a trap field (a honeypot) and, if needed, a captcha. To keep it safe, validate everything on the server, never trust what arrived, and do not let a text field go into the e-mail or the database as it is. The two kinds of care go together.
Against spam: from the quietest layer to the most visible
| Defence |
How it works |
Annoyance to the visitor |
| Honeypot |
A field hidden with CSS. A person does not see it or fill it in; a robot fills in everything. If it comes back filled, you discard it. |
None. |
| Minimum time |
A form sent one second after it opened was sent by a robot. |
None. |
| Rate limit |
Few messages a minute per address. It slows down whoever insists. |
Hardly any. |
| Captcha |
Asks the visitor to prove they are a person. Some versions do not even ask for clicks (reCAPTCHA, hCaptcha, Cloudflare Turnstile). |
Medium. Some visitors give up. |
| Moderation |
Nothing is published without approval. It applies to comments and reviews. |
A delay in publishing. |
Start with the first two: they cost little and stop most simple robots. Add the captcha only if the spam carries on. In WordPress, most form plugins have these options as tick boxes; for comments, see stopping spam comments in WordPress, and for a shop, fake orders and spam sign-ups.
For safety: what the code has to do
| 1 |
Validate on the server. Validation in the browser (the field that says “invalid e-mail”) is only a courtesy: a robot never goes through it. On the server, confirm the e-mail is an e-mail, the length is reasonable and the required fields exist.
|
|
| 2 |
Never let the visitor’s text touch the database as it is. Use prepared statements, where the instruction and the data travel separately. It is the defence against “SQL injection”, where a field filled in with an instruction becomes part of your query.
|
|
| 3 |
Neutralise the text before showing it on a page, by converting special HTML characters. It is the defence against scripts inserted by whoever filled in the form (XSS). In PHP, the htmlspecialchars function does this.
|
|
| 4 |
Watch the e-mail header. If the sender address and subject come from the form, anyone who puts a line break there can add recipients and use your server to send spam. Strip line breaks from those fields, and prefer sending with authentication, as in sending e-mail with PHPMailer.
|
|
| 5 |
If you accept files, accept only the types you need, limit the size, rename them and never store them in folders where code can run. A “resume.pdf” that is really a PHP program is an old class of attack.
|
|
|
Do not put the destination e-mail in the form as a hidden field. Anyone who sees it can use your form to send messages to anyone. The destination stays on the server.
|
|
Receiving hundreds of fake messages, or was the form used to send spam? Tell us the domain.
Open a support ticket
|
RECOMMENDED PRODUCT Professional e-mail on your domain Mailboxes in your company name, no adverts, with spam filtering. from $6.60/mo (3-year plan, with coupon) See plans |