How to Send an HTML Form to Your Email (Without PHP or SMTP)
How to send an HTML form to your email without PHP or SMTP: why mailto: fails, the one-line form backend method, the JavaScript fetch() version, and how to stay out of spam.
The ShipMyForm team
· Published Jul 12, 2026 · 6 min read
An HTML form cannot send email on its own. It can only POST its fields to a
URL, so the job is to put something at that URL that turns the submission into
an email. The fastest way that works on any static host is a form endpoint:
one action attribute, no PHP, no SMTP, no JavaScript. This guide covers that
method, the JavaScript fetch() version, the serverless-plus-SMTP version for
people who want to own the sending, and why mailto: and PHP mail() keep
failing.
Full disclosure: ShipMyForm is our product and it is the form endpoint in the examples. Every other option below is described on its merits.
Every way to send an HTML form to email, compared
| Method | Works on a static host | Credentials safe | Lands in the inbox | Effort |
|---|---|---|---|---|
action="mailto:" | Yes, but nothing is sent | n/a | Not applicable | None |
PHP mail() | No, needs a PHP server | Yes | Usually spam | Low |
| JavaScript email service (EmailJS and similar) | Yes | No, the key is in the page | Varies | Low |
| Serverless function plus SMTP or an email API | Yes | Yes | Yes, if you configure DNS | Medium |
| Form endpoint (form backend) | Yes | Yes | Yes | One attribute |
Send HTML form data to an email address without PHP
This is the whole thing. Point action at a form endpoint and give each input
a name. The endpoint receives the POST, stores it, and emails you:
<form action="https://shipmyform.com/f/YOUR_FORM_ID" method="POST">
<label>Your email <input type="email" name="email" required /></label>
<label>Message <textarea name="message" required></textarea></label>
<button type="submit">Send</button>
</form>No fetch() wrapper, no keys in the page, no server. Because it is a standard
form post it behaves identically whether the page is Astro, Hugo, Next.js,
plain HTML, or something an AI builder produced. Add a hidden field named
_subject to set the email subject, and _redirect to choose the thank-you
page. If you want the markup generated for your own fields, the free
contact form generator writes it, honeypot
included.
Send HTML form data to email using JavaScript
Keep the same endpoint and post to it with fetch() when you want an inline
"thanks" instead of a page change. The JavaScript is the browser half only;
the email is still sent server-side, so there are no credentials to leak.
<form id="contact" action="https://shipmyform.com/f/YOUR_FORM_ID" method="POST">
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>
<script>
const form = document.getElementById("contact");
form.addEventListener("submit", async (e) => {
e.preventDefault();
const res = await fetch(form.action, {
method: "POST",
body: new FormData(form),
headers: { Accept: "application/json" },
});
form.outerHTML = res.ok
? "<p>Thanks, we'll be in touch.</p>"
: "<p>Something went wrong. Please email us directly.</p>";
});
</script>The full pattern, with loading states and per-field validation errors from the JSON response, is in submit a form with fetch().
HTML form to email with SMTP, if you want to own the sending
You cannot speak SMTP from a browser, and you should not try: the credentials would be in the page. What you can do is put a small serverless function between the form and your mail provider. The form posts to the function, the function sends through a transactional email API with a verified sending domain.
// api/contact.js (Vercel or Netlify function)
export default async function handler(req, res) {
const { email, message } = req.body;
await fetch("https://api.your-email-provider.com/send", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.EMAIL_API_KEY}` },
body: JSON.stringify({
from: "[email protected]",
reply_to: email,
to: "[email protected]",
subject: "New contact form message",
text: message,
}),
});
res.status(200).json({ ok: true });
}This is a correct answer if you already run email infrastructure. You also own the DNS records, bounce handling, spam filtering, rate limiting and retries. The Vercel contact form guide walks through what that costs in practice.
Why the popular shortcuts fail
mailto: does not send anything. It asks the visitor's browser to open
their mail client with a draft they then have to send themselves. On a phone,
a locked-down work machine, or a browser with no mail client configured,
nothing happens. The data arrives as a URL-encoded blob, and you have published
your address for every scraper. Fine as a plain "email us" link. Useless as a
form.
PHP mail() assumes a server you do not have. Netlify, Vercel, GitHub
Pages and Cloudflare Pages cannot run it. Even on a PHP host, bare mail()
sends without authentication and lands in spam.
Email services called from JavaScript put your key in the page. Anyone can open dev tools, copy it, and send as you until you notice the bill or the blocklist. Acceptable for an internal tool behind a login. Risky for anything a stranger can load.
Sending email is an authenticated conversation with a mail server, and that conversation has to happen on a machine running code. A static site is files on a CDN. Every working method above is a way of borrowing such a machine. More on the mechanics in sending form email without SMTP.
The part tutorials skip: making the email actually arrive
Getting the email sent is half the job. Getting it into the inbox rather than spam is the half nobody writes about, and three things decide it.
Send from a domain you control, not the visitor
The instinct is to make the notification come "from" the person who filled in
the form. Do not. Mail providers check that the sender is allowed to send for
that domain, through SPF and DKIM, and you cannot authenticate for someone
else's address. Send from your own domain and put the visitor's address in
Reply-To. The mail authenticates, and hitting reply still reaches them.
Publish SPF, DKIM and DMARC for the sending domain
Three DNS records that say "this server may send for my domain". Without them even a well-formed email is treated with suspicion. A transactional provider, or a form backend that uses one, gives you the exact records. Ten minutes, once.
Give it a real subject and reply path
A submission with a blank or generic subject is easy to miss and easy for
filters to distrust. A clear subject plus a working Reply-To makes the
notification a real email you can act on.
If your form mail is already going to spam, the fix is usually the first of these three. Why form emails land in spam walks through the diagnosis.
ShipMyForm sends notifications from a verified domain, sets Reply-To to the submitter automatically, and keeps a stored copy of every submission, so a message that slips past your inbox is never lost.
Do not forget the spam bots
The moment a form can email you, it can email you garbage; bots find public forms within days. You do not need a CAPTCHA for most of it: a hidden honeypot field plus server-side rate limiting blocks the bulk quietly. See how to stop form spam without reCAPTCHA.
Which should you use?
- A personal page, low stakes. A
mailto:link, not a form, is honestly fine. - An internal tool behind a login. A JavaScript email service will do.
- You already run email infrastructure. A serverless function and your provider.
- A real contact form on a public site. Post to a form endpoint. It stays static, keeps credentials safe, gets deliverability right, and is one attribute.
Email was never HTML's job. Hand it to something built for it, keep your form
a plain <form>, and the message shows up where you expected it.
Next steps
- Want the code ready to paste? HTML contact form templates that email you
- Keep the visitor on the page: submit a form with fetch()
- Landing in the spam folder? Why form emails get filtered
- Build one now: add a contact form to an Astro site
- Understand what is doing the work: what is a form backend?
- Start free: email notifications on every plan, 250 submissions a month, no card required.
Frequently asked questions
- Can an HTML form send an email by itself?
- No. An HTML form can only POST its fields to a URL. Sending email needs an authenticated connection to a mail server, which has to run on a machine that executes code. A static site has no such machine, so something at that URL has to turn the submission into an email for you.
- How do I send HTML form data to an email address without PHP?
- Point the form's action at a hosted form endpoint instead of a PHP script. The endpoint receives the POST and sends the email server-side, so the page stays plain HTML and works on any static host. With ShipMyForm that is one attribute: action="https://shipmyform.com/f/YOUR_FORM_ID".
- Can I send an HTML form to email using JavaScript?
- Yes, but JavaScript should post to a backend endpoint, not send the email itself. Intercept submit, send the fields with fetch() to the endpoint, and show an inline thanks. Never put SMTP or email API credentials in browser code; anyone can read them.
- Why doesn't action="mailto:" work for a contact form?
- Because it does not send anything. It asks the visitor's browser to open their own mail client with a draft, which they then have to send. On phones, locked-down machines and browsers with no mail client, nothing happens at all, and your address is exposed to scrapers.
- Why do my form emails go to spam?
- Usually because the notification is sent as the visitor, from a domain you do not control, which fails SPF and DMARC. Send from your own domain, or through a service that does, and put the visitor's address in Reply-To.
- Do I need SMTP to send form emails?
- Only if you run the sending yourself, on a server or serverless function, with a transactional email provider's credentials. A form backend removes the need entirely: it sends the email for you and never exposes credentials to the browser.
Related guides
Send Email From an HTML Form — No SMTP, No PHP
What SMTP actually is, why your HTML form can't speak it (and shouldn't), and the modern setup that emails you submissions with zero mail servers.
Why Your Contact Form Emails Land in Spam (and How to Fix It)
Most form notifications land in spam for one reason: the From address is the person who filled the form. Here's why that fails authentication, and what to send instead.
How to Submit a Form with JavaScript fetch() (and Send It to Your Email)
The vanilla-JS pattern for submitting a form without a page reload — intercept submit, fetch() the data, and render success and per-field errors from the JSON response.