Skip to content
← All use cases
Use case · Form to email

Send an HTML form to your email, no backend

A browser cannot send email on its own, so a form needs something on a server to receive the POST and write the message. Formward is that server. Create a form in the dashboard, copy its ID into the action attribute, and every submission is checked for spam, stored, and emailed to you.

<form action="https://forms.formward.eu/f/YOUR_FORM_ID" method="POST">
  <input type="email" name="email" required>
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>

That is the whole integration. No JavaScript, no API key in the page, and it works the same in plain HTML, a static site generator or a framework component. Browser-side senders such as EmailJS work the other way round: the page carries the keys, sends the email itself and nothing is stored. The EmailJS comparison shows both versions of the code.

What happens when someone submits

  1. The browser POSTs the fields to forms.formward.eu. Before the submission is accepted, Formward checks the origin against the form's allowed origins (if you set any), applies a per-IP rate limit using a hashed IP, and looks at the honeypot field.
  2. The submission is saved to your dashboard, where you can read and search it later. Deleting the email does not delete the record.
  3. A notification goes to the form's address. Each extra recipient has to confirm their address before they receive anything, so a typo cannot send submissions to a stranger.
  4. The visitor lands on your thank-you page, or on Formward's default page if you have not set one. A fetch() request with Accept: application/json gets { "ok": true, "id": "..." } instead.

Control the email with hidden fields

Fields whose names start with an underscore are instructions for Formward rather than answers from the visitor.

<form action="https://forms.formward.eu/f/YOUR_FORM_ID" method="POST">
  <input type="hidden" name="_subject" value="New message from the website">
  <input type="hidden" name="_redirect" value="/thank-you">
  <input type="email" name="email" required>
  <textarea name="message" required></textarea>
  <!-- Honeypot: off-screen, must stay empty -->
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off"
         style="position:absolute;left:-9999px;opacity:0">
  <button type="submit">Send</button>
</form>
  • _subject sets the notification subject line. Without it you get "New submission to" plus the form name.
  • A field named email sets the Reply-To header on its own, so pressing Reply answers the visitor and the form above needs nothing extra. _replyto overrides it, for example when the email field has another name or the form has several; the special fields docs have the details.
  • _redirect accepts a relative path, or an absolute URL whose origin is on the form's allowed list. Anything else falls back to the redirect set in the dashboard.
  • _gotcha is the honeypot. A bot that fills it gets a normal-looking success response, and the submission is marked as spam and never emailed.

Submit with fetch() and stay on the page

If you would rather show a message in place than redirect, send the same form with fetch(). The Accept header is what switches the response from a redirect to JSON.

const form = document.querySelector("form");
form.addEventListener("submit", async (event) => {
  event.preventDefault();
  const res = await fetch(form.action, {
    method: "POST",
    headers: { Accept: "application/json" },
    body: new FormData(form),
  });
  const data = await res.json();
  if (res.ok) {
    form.reset();
    form.after("Thanks, your message was sent.");
  } else {
    alert(data.error || "Something went wrong. Please try again.");
  }
});

Errors come back as { "ok": false, "error": "..." } with a 4xx status: 429 when rate limited, 402 when the monthly limit is reached. The AJAX docs cover CORS and the full status table.

Limits worth knowing before you ship

  • Monthly submissions: 50 on Free, 200 on Personal, 2,000 on Professional and 20,000 on Business. Free and Personal stop at the limit; Professional and Business accept 20% more as overage first. Submissions caught by the honeypot do not count.
  • Several notification recipients, CSV export and search start on Personal.
  • The autoresponder and file attachments start on Professional. Attachments are not mailed; the notification lists them and links to the dashboard.
  • On Free, submissions are deleted after 30 days. Paid plans choose any period from 1 to 3,650 days, or keep them.

Full details are on the plans page.

If your inbox is Gmail or Outlook

A notification email contains the submission. If it goes to a mailbox hosted outside the EU, the content goes there too, and that transfer is yours to account for. Each form has a link-only setting for this case: the email then says only that a new submission arrived and links to the dashboard. Field values, the custom subject, attachment names and the Reply-To address are all left out.

Where the data lives

Formward stores submissions, file attachments and backups in Sweden, on servers run by Hostup AB. Notification email goes out through Mailjet from an EU data centre. Submitter IP addresses are replaced with a keyed HMAC-SHA-256 hash on receipt, so the raw address is never written to disk. On Professional and Business, AI features run on Mistral AI in France and can be switched off per form.

Data leaves the EU only where you send it: a notification inbox hosted outside the EU, a webhook URL, a Slack channel or a Google Sheet. Cloudflare Turnstile is a US service, and it is off unless you switch it on for a form. The details are in the sub-processor register, the data residency page and the published DPA. For the wider picture, see GDPR form backend.

Questions

Can a form send email with only HTML, using mailto:?
A mailto: action hands the message to the visitor's own mail app. Visitors without one set up get nothing, and you get no copy, no spam filtering and no record. A form endpoint receives the POST on a server instead, which is why it works for every visitor.
Is it free?
The Free plan includes 50 submissions a month and email notifications to your account address, with no card required. Extra recipients start on Personal (EUR 15 a month).
Can the visitor get a confirmation email?
Yes, on Professional and Business. The autoresponder replies to the address the visitor entered, with a per-form daily cap so the form cannot be used to send bulk mail.
Why did a notification land in my spam folder?
Form notifications carry text written by strangers, which spam filters weigh heavily. The blog post linked below explains how to tell a filtering false positive from a real authentication problem.

Get your first submission by email

Start free with 50 submissions a month. No card needed.

HTML form to email without a backend | Formward