A PHP email form posts to a .php script that calls mail() to send the message, but that approach often lands in spam, is easy to get wrong securely, and doesn't run on static hosts. To build a contact form without PHP, set the form's action to a hosted form endpoint such as https://formsubmit.app/f/YOUR_FORM_ID. The form backend receives the submission, filters spam and emails it to you from a properly authenticated sending domain. If you already have a PHP form, you can switch by changing one attribute and keeping all your field names.
This guide shows a typical PHP email form honestly, explains where it breaks, and then walks through the no-PHP alternative and a migration.
How a typical PHP email form works
Most "email form HTML PHP" tutorials have two files: an HTML form and a script that sends it.
<form action="send.php" method="POST">
<label for="name">Name</label>
<input id="name" type="text" name="name" required>
<label for="email">Email</label>
<input id="email" type="email" name="email" required>
<label for="message">Message</label>
<textarea id="message" name="message" required></textarea>
<button type="submit">Send</button>
</form><?php
// A typical copy-paste handler. Shown for illustration, not as a recommendation.
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
http_response_code(405);
exit;
}
$name = trim($_POST["name"] ?? "");
$email = trim($_POST["email"] ?? "");
$message = trim($_POST["message"] ?? "");
if ($name === "" || !filter_var($email, FILTER_VALIDATE_EMAIL) || $message === "") {
http_response_code(400);
exit("Please fill in all fields.");
}
$to = "you@example.com";
$subject = "New message from your website";
$body = "Name: $name\nEmail: $email\n\n$message";
$headers = "From: website@example.com\r\nReply-To: $email";
if (mail($to, $subject, $body, $headers)) {
header("Location: /thanks.html", true, 303);
} else {
http_response_code(500);
echo "Sorry, your message could not be sent.";
}This is a reasonably careful version. It checks the method, validates the email before using it in a header, and sends from your own address rather than the visitor's. Plenty of scripts in the wild skip all three. Even so, it has problems that the code can't fix.
The problems with PHP mail()
Deliverability: emails land in spam or vanish
mail() hands the message to the server's local mail program, which sends it from your host's shared server. Unless your domain's SPF record allows that server, and the message is signed with DKIM for your domain, Gmail and Outlook have little reason to trust it. Many scripts make it worse by setting From: to the visitor's address, which looks exactly like spoofing and can fail DMARC checks outright.
The result is the classic "my contact form doesn't send email" problem. The script reports success, but the message is filtered, delayed or silently dropped. Fixing it means editing DNS records, configuring SMTP through a library such as PHPMailer, and often paying for a transactional email provider. Contact form emails going to spam covers this in depth.
Header injection
The fourth argument to mail() is raw email headers. If any user input reaches it without validation, an attacker can submit a value containing line breaks and add their own Bcc: header, turning your form into a spam relay for other people's mail. Validating with filter_var as above helps, but it's easy to forget when you add a field later.
Spam submissions
A bare PHP script has no spam protection. Bots find it within days. Adding a honeypot, rate limiting, duplicate detection, content scoring and a captcha is all code you have to write, test and keep current.
Hosts that disable or limit mail()
Many hosts disable mail(), rate-limit it, or require you to use their SMTP server with authentication. And static hosts such as GitHub Pages, Netlify, Vercel and Cloudflare Pages don't run PHP at all, so send.php is downloaded or returns a 404 instead of executing.
Maintenance and no record
You own the PHP version upgrades, the security patches and the debugging. There's also no record of submissions. If an email is lost, the message is gone, because nothing stored it.
A contact form without PHP
A form backend replaces send.php. The browser posts the form straight to it, and it handles validation, spam filtering, storage and email. With FormSubmit:
Create a form
Sign up with Google or email and click New form. You get an endpoint like https://formsubmit.app/f/k3m9p2qabx.
Use it as your form's action
<form action="https://formsubmit.app/f/YOUR_FORM_ID" method="POST">
<div>
<label for="fs-name">Name</label>
<input id="fs-name" type="text" name="name" placeholder="Jane Doe" required>
</div>
<div>
<label for="fs-email">Email</label>
<input id="fs-email" type="email" name="email" placeholder="jane@example.com" required>
</div>
<div>
<label for="fs-message">Message</label>
<textarea id="fs-message" name="message" rows="5" placeholder="How can we help?" required></textarea>
</div>
<!-- Honeypot: leave this hidden field empty to catch bots -->
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display:none">
<!-- Optional: where to send people after submitting -->
<!-- <input type="hidden" name="_redirect" value="https://yoursite.com/thanks"> -->
<button type="submit">Send</button>
</form>Test it
Submit the form. You're redirected to a thank-you page, the submission appears in your dashboard, and the notification email arrives with Reply-To set to the visitor.
Compared with the PHP version:
PHP mail() script | FormSubmit | |
|---|---|---|
| Server code to write | Yes | None |
| Works on static hosts | No | Yes |
| Sent from | Your host's shared server | FormSubmit's own sending address, with the visitor in Reply-To |
| Spam protection | Whatever you build | Honeypot, timing check, content scoring, rate limits, optional captcha |
| Header injection risk | Yours to prevent | No headers built from your HTML |
| Stored copy of each submission | No | Yes, in your dashboard |
| File uploads | Extra code and storage | enctype="multipart/form-data" and a file input |
| Cost | Hosting | Free for 1 form and 50 submissions a month |
Migrate an existing PHP email form
You don't need to rebuild your form. Most PHP email forms can switch in a few minutes.
Keep your field names
FormSubmit stores whatever field names your form sends, so name, email, phone and message all keep working. Names become readable labels in the email, so company_size appears as "Company size". If your email field has an unusual name, rename it email (or add a _replyto field) so replies go to the visitor.
Change the action
<!-- Before -->
<form action="send.php" method="POST">
<!-- After -->
<form action="https://formsubmit.app/f/YOUR_FORM_ID" method="POST">Keep method="POST". If the form has a file input, keep enctype="multipart/form-data" too.
Move your PHP settings into hidden fields or the dashboard
| In your PHP script | With FormSubmit |
|---|---|
$to = "you@example.com" | Your account email by default. Add more under Notifications → Recipients. |
$subject = "..." | A hidden _subject field, or a subject template such as New message from {{name}} in email settings |
Reply-To: $email | Automatic, from a field named email or _replyto |
header("Location: /thanks.html") | A hidden _redirect field with the full URL, or a redirect URL in form settings |
| Required-field checks | Keep the required attributes in your HTML |
<input type="hidden" name="_subject" value="New message from your website">
<input type="hidden" name="_redirect" value="https://example.com/thanks.html">
<input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display:none">See control fields and redirects for the details.
Test, then remove the PHP file
Send a test submission, check your inbox and dashboard, and then delete send.php from your server. Leaving an old mail script online invites abuse.
If you'd like to stay on the page and show an inline thank-you message instead of redirecting, see submit a form with JavaScript.
When PHP still makes sense
If you already run a PHP application, such as a custom CMS, with authenticated SMTP and proper SPF and DKIM, and you need to write submissions into your own database, keeping the handler in PHP is reasonable. Use a maintained library like PHPMailer with SMTP rather than bare mail(). For WordPress, see WordPress contact form without a plugin.
For most brochure sites, portfolios and landing pages, though, a PHP email form is a lot of moving parts for a job a form backend does in one line.
Next steps
- Get a ready-made contact form for website projects, or build your own fields in the form generator.
- Learn how sending an HTML form to email works end to end, including subject lines and attachments.
- Understand what the browser does on submit in HTML form action explained.
- Harden the form with the spam protection settings and a domain allowlist.