All resources
Forms to email

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

MethodWorks on a static hostCredentials safeLands in the inboxEffort
action="mailto:"Yes, but nothing is sentn/aNot applicableNone
PHP mail()No, needs a PHP serverYesUsually spamLow
JavaScript email service (EmailJS and similar)YesNo, the key is in the pageVariesLow
Serverless function plus SMTP or an email APIYesYesYes, if you configure DNSMedium
Form endpoint (form backend)YesYesYesOne 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:

html
<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.

html
<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.

js
// 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.

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.

The deeper reason:

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.

What a form backend does here:

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

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