Guides

How to send HTML form submissions to email

Browsers can't send email. Here are the three real options for getting form submissions by email, and the one that needs no server code.

Updated · 7 min read

You have an HTML form and you want an email every time someone submits it. The catch: a browser can't send email. It can only send the form's fields to a URL. Whatever sits at that URL has to turn the request into an email.

There are three ways to do that. Here is each one with working code and what it costs you in practice.

Option 1: mailto (HTML only, not recommended)

Setting the form's action to a mailto: link is the only approach that needs nothing but HTML:

mailto form
<form action="mailto:you@example.com" method="POST" enctype="text/plain">
  <input name="email" type="email" required>
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>

It looks like it works on your own machine, but nothing is sent. The browser opens the visitor's email app with the fields pasted into a draft, and the visitor still has to press Send. On phones and shared computers without a configured email app, nothing happens at all. You also never see the messages that were abandoned at that step.

Option 2: A server script

If your host runs PHP, a short script can receive the form and call mail(). Set the form's action to /contact.php:

contact.php
<?php
// contact.php: the bare minimum. Real code also needs spam checks and rate limiting.
$name = strip_tags($_POST["name"] ?? "");
$email = filter_var($_POST["email"] ?? "", FILTER_VALIDATE_EMAIL);
$message = strip_tags($_POST["message"] ?? "");

if (!$email || $message === "") {
  http_response_code(422);
  exit("Please fill in a valid email and a message.");
}

mail(
  "you@example.com",
  "New message from your website",
  "From: $name <$email>\n\n$message",
  "Reply-To: $email"
);

header("Location: /thanks.html");

This is fine for a quick fix, but it leaves work on your plate:

  • Deliverability. Mail sent from shared hosting often lands in spam or is dropped unless SPF and DKIM are set up for the sending domain.
  • Spam. Bots will find the form. You have to add honeypots, rate limits, or a CAPTCHA yourself.
  • No record. If an email is lost, so is the message. There is no list of past submissions to search or export.
  • No server on static hosts. GitHub Pages, Netlify, Vercel, and Cloudflare Pages don't run PHP, so you'd need a serverless function and an email API instead.

Option 3: A form backend (no server code)

A form backend is a hosted URL built to receive form posts. It stores every submission, filters spam, and emails you when one arrives. Your form stays plain HTML and works on any host. This guide uses Heapform, the form backend we build.

1. Create a form and add your email

Sign up for free, create a form in the dashboard, then open its settings and add the addresses that should be notified. Each plan allows a set number of recipients per form: 1 on Hobby, 2 on Starter, 5 on Pro, 10 on Business.

2. Point your form at the endpoint

Copy the form's endpoint URL from the dashboard and use it as the action. Every field with a name attribute is saved with the submission.

contact.html
<form action="https://forms.heapform.com/f/YOUR_FORM_SLUG" method="POST">
  <label for="name">Name</label>
  <input id="name" name="name" type="text" autocomplete="name">

  <label for="email">Email</label>
  <input id="email" name="email" type="email" autocomplete="email" required>

  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>

  <!-- Honeypot: hidden from people, filled in by bots -->
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display:none">

  <button type="submit">Send</button>
</form>

3. Send a test submission

Fill in the form on your live site. The submission appears in the dashboard right away and the notification email follows within seconds, from Heapform <updates@notifications.heapform.com>. If it isn't in your inbox, check your spam folder once and mark it as not spam.

The email tells you which form received a submission and links straight to it. The fields themselves are shown in the dashboard, where you can also search them and export them as CSV or JSON.

You can also test the endpoint from a terminal:

Terminal
curl -X POST "https://forms.heapform.com/f/YOUR_FORM_SLUG" \
  -H "Content-Type: application/json" \
  -d '{"name":"Jane","email":"jane@example.com","message":"Testing the email notification"}'

4. Optional: submit with JavaScript

To show your own success message without leaving the page, send the same fields with fetch:

contact.js
const form = document.querySelector("form");

form.addEventListener("submit", async (event) => {
  event.preventDefault();

  const response = await fetch(form.action, {
    method: "POST",
    headers: { "Content-Type": "application/json", Accept: "application/json" },
    body: JSON.stringify(Object.fromEntries(new FormData(form))),
  });
  const result = await response.json();

  if (result.success) {
    form.reset();
    alert("Thanks! We'll get back to you soon.");
  }
});

For a version with loading state and validation errors, see how to create a contact form in HTML. Using React or Next.js? The Next.js contact form guide covers that.

Which option should you use?

  • mailto only if you are fine losing a share of messages, for example on an internal page where everyone has Outlook set up.
  • A server script if you already run a server, are comfortable with email deliverability, and need the data in your own database.
  • A form backend for static sites and anyone who wants an email alert for every submission, plus a searchable, spam-filtered record of them, without maintaining code.

Comparing form backends? Our honest comparison lists free tiers and prices for Heapform, Formspree, Web3Forms, Getform, and others.

Frequently asked questions

Make your form work in minutes

Create a form endpoint, paste it into your form, and get an email for every submission.

Start for free