Log in

HTML contact form that sends email

Plain HTML cannot send email on its own — it needs somewhere to POST to. That is the entire problem this page solves: set the action to an endpoint and the ordinary form you already know how to write becomes a working contact form.

Live preview: this is the HTML and CSS below, rendered as-is.

Replace YOUR_FORM_ID with a form of your own and this sends to your inbox.

Create your form
contact.html
<form action="https://submit.formpost.ai/YOUR_FORM_ID" method="POST">
  <h2>Contact us</h2>

  <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" rows="4" required></textarea>

  <!-- Land the visitor on your own page instead of ours -->
  <input type="hidden" name="redirect" value="https://example.com/thank-you">

  <button type="submit">Send message</button>
</form>
contact.css
body {
  margin: 0;
  padding: 32px 16px;
  background: #fbfbfc;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: #18181b;
}

form {
  display: flex;
  flex-direction: column;
  max-width: 420px;
  margin: 0 auto;
}

h2 {
  margin: 0 0 18px;
  font-size: 20px;
}

label {
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 600;
  color: #3f3f46;
}

input,
textarea {
  box-sizing: border-box;
  font: inherit;
  margin-bottom: 16px;
  padding: 10px 12px;
  color: #18181b;
  background: #fff;
  border: 1px solid #d4d4d8;
  border-radius: 8px;
}

input:focus,
textarea:focus {
  border-color: #2563eb;
  outline: 2px solid rgba(37, 99, 235, 0.2);
}

textarea {
  resize: vertical;
}

button {
  padding: 11px 16px;
  font: inherit;
  font-weight: 600;
  color: #fff;
  background: #2563eb;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
}

button:disabled {
  background: #93b4f5;
  cursor: default;
}

/* The status line, shared by all three JavaScript versions. Keyed on the role
   rather than a class, so it styles the element that is already announcing
   itself to a screen reader. */
[role="status"] {
  margin: 14px 0 0;
  font-size: 14px;
  text-align: center;
}

[role="status"]:empty {
  display: none;
}

[role="status"].ok {
  color: #16a34a;
}

[role="status"].bad {
  color: #dc2626;
}

Why HTML alone cannot send mail

HTML is markup. It can describe a form and it can tell the browser where to send it, but it has no way to open an SMTP connection — that has always required something on a server. The old answer was a PHP script; the modern one is to post to an endpoint that already does the job.

You may have seen action="mailto:you@example.com" suggested. It does not work in practice: it hands the submission to whatever desktop mail client the visitor has configured, which on most machines is none, and the ones that do open show the visitor a raw pile of form data to send manually.

The three attributes that matter

AttributeValueWhat happens without it
actionyour endpoint URLThe form posts back to the current page and nothing is sent
methodPOSTFields end up in the URL as a query string and are dropped
nameon every inputThe field is not submitted at all — this is the usual cause of a missing field

Landing on your own thank-you page

A plain form post is a navigation, so the browser has to arrive somewhere. Without configuration that is our confirmation page. The hidden redirect field overrides it per form, and you can set a default in the form settings instead so your markup never has to know:

<input type="hidden" name="redirect" value="https://example.com/thank-you">

This is the version that always works

  • It submits with JavaScript disabled, blocked by an extension, or simply not downloaded yet.
  • It works in an email client preview, a text browser, and every no-code page builder that lets you paste raw HTML.
  • There is no bundle, no hydration and nothing to go wrong between the click and the POST.
  • The trade-off is the page navigation. If you need the visitor to stay put, add a submit handler — the markup does not change.
Add a honeypot field before you launch. It is one hidden input, it costs nothing, and it stops the majority of automated submissions on its own.

Questions about this contact form

Can an HTML form send email without PHP?
Not by itself, but it does not need PHP either. Point the action at a form endpoint and the sending happens there — you keep writing plain HTML and never deploy any server code of your own.
Does action="mailto:" work for a contact form?
Almost never. It depends on the visitor having a desktop mail client configured, and even then it shows them raw form data to send by hand. Most people see nothing happen at all.
Why is one of my fields missing from the email?
It has no name attribute. Browsers only submit inputs that have one — an id is for labels and CSS, not for submission. This is the single most common reason a field silently disappears.
Can I host this on GitHub Pages or Netlify?
Yes. There is nothing to run server-side, so any static host works — GitHub Pages, Netlify, Vercel, S3, or a folder on shared hosting. That is the whole point of putting the sending behind an endpoint.

Related examples

Or go back to all 21 contact form examples.

Give this form an endpoint

Formpost takes the submission, emails it to you and keeps a searchable copy. Free for 250 messages a month, with unlimited forms and no card.