Yes. The builder runs entirely in your browser and uploads nothing. The generated code hard-codes the destination server-side, strips header-injection characters, validates every field, never deserializes input, and MIME-checks all uploads.
Generate a hardened PHP contact form that emails you through your own SMTP server — CSRF token, honeypot, time-trap, rate limiting and strict input sanitization built in. The classic FormMail scripts of the 2000s were open relays; this one locks the destination address server-side and never trusts the browser. No account, no server: the form design and generated code are produced entirely in your browser.
Add fields, pick a theme, watch the live preview update as you type.
Enter your SMTP details and destination address; optionally enable reCAPTCHA v3 and attachments.
One click generates the hardened formmail.php — copy it or download the file.
Drop it beside your page, require it, echo fm_form() — done. Test once before going live.
The generated form uses PHPMailer over authenticated SMTP — this step-by-step guide covers the download, include path and SMTP configuration.
Open the KB Guide →Nginx reverse-proxy builder, DNS zone builder, Kubernetes manifests, Linux toolkit — all 100% client-side, all free.
Browse All Tools →| Attack | How the generated code stops it |
|---|---|
| Open relay / recipient spoofing | The classic FormMail flaw: old scripts took the destination address from a form field, so anyone could relay spam through them. Here the recipient lives only in the server-side config block — addAddress($cfg['recipient']) — and is never accepted from the request. |
| Email header injection | Every field passes through fm_clean(), which strips CR, LF and their percent-encoded forms plus all HTML tags; email and URL fields are additionally validated with filter_var(). Embedded newlines are impossible by construction. |
| Cross-site request forgery | A per-session token is embedded in the form and compared with hash_equals() (timing-safe) on every POST. |
| Bots & scripted spam | Three always-on layers: a hidden honeypot field, a time-trap (submissions faster than 3 seconds or older than an hour are rejected), and a 5-per-hour session rate limit. Optionally Google reCAPTCHA v3 with a 0.5 score threshold. |
| Malicious uploads | Attachments are limited to JPG, PNG and PDF by real MIME type (finfo, not file extension), capped at 2 MB each, stored under random names in the system temp directory, and deleted immediately after sending — on success or failure. |
| Stored XSS | All output is escaped with htmlspecialchars(); input is tag-stripped. Nothing a visitor types is ever rendered as HTML. |
| Unsafe deserialization | None of the classic vulnerabilities apply: the code never calls unserialize(), eval() or system() on user input — it only reads strings and files. |
| Information leaks | Visitors see generic messages ("Please try again later"); real errors (SMTP failures, exceptions) go to your server's error_log only. |
Authenticated SMTP passes SPF, DKIM and DMARC checks, so Gmail and Outlook deliver your messages. Native mail() without authentication is routinely rejected or spam-foldered — and on shared hosts it often never leaves the server.
One file is one thing to upload, back up and permission. chmod 640 formmail.php keeps the SMTP credentials readable only by your web server user. The form renderer and the mail handler share a session-based CSRF token, so they belong together anyway.
Yes. The builder runs entirely in your browser and uploads nothing. The generated code hard-codes the destination server-side, strips header-injection characters, validates every field, never deserializes input, and MIME-checks all uploads.
Authenticated SMTP passes SPF, DKIM and DMARC, so Gmail and Outlook deliver your messages. Native mail() is routinely rejected or spam-foldered.
A hidden honeypot field, a minimum three-second fill time, a five-per-hour session rate limit — and optionally Google reCAPTCHA v3 with a 0.5 score threshold.
Only into the config block of formmail.php on your own server — never into the HTML shown to visitors. Use an app password and keep the file at permission 640.