Email Fast Get a sandbox key
Guides

Send email with React

A contact form that sends from the component, with a key that's safe to ship — or a small backend route when you have one.

Facts verified 2026-07-17 — corrections: hello@emailfast.dev

A React component can send email without any backend at all. Email Fast ships a browser SDK with EmailJS-compatible endpoints — the recipient always comes from the server-stored template, never from the request, so a public key in your frontend can't be abused to spam arbitrary addresses. Initialize it with your public key, point it at a server-stored template, wire it to a form. If you already run a backend, skip the browser SDK and send from there instead — that variant is below.

npm install @email-fast/browser
// ContactForm.jsx
import { useState } from "react";
import emailfast from "@email-fast/browser";

emailfast.init({ publicKey: "ef_pub_..." }); // public by design — safe to ship

export function ContactForm() {
  const [state, setState] = useState("idle");

  async function onSubmit(e) {
    e.preventDefault();
    setState("sending");
    try {
      await emailfast.sendForm("default", "contact_form", e.target);
      setState("sent");
    } catch {
      setState("error");
    }
  }

  return (
    <form onSubmit={onSubmit}>
      <input name="name" required />
      <input name="email" type="email" required />
      <textarea name="message" required />
      <button disabled={state === "sending"}>Send</button>
      {state === "sent" && <p>Thanks — we got it.</p>}
      {state === "error" && <p>That didn't go through. Try again.</p>}
    </form>
  );
}

"contact_form" is a template slug: the template — including who receives the mail — lives in your dashboard, not in the component.

Or: send through your own backend

If your React app already talks to a server, keep the secret key there and expose one route:

// server.js — Express; the secret key never reaches the browser
import express from "express";
import { EmailFast } from "@email-fast/nodejs";

const app = express().use(express.json());
const ef = new EmailFast({ apiKey: process.env.EMAILFAST_API_KEY, baseUrl: "https://api.emailfast.dev" }); // ef_sandbox_… while testing

app.post("/api/contact", async (req, res) => {
  try {
    const { id } = await ef.send({
      to: "team@yourdomain.dev",
      subject: "New contact message",
      html: "<p>{{message}}</p>",
      data: { message: req.body.message },
      idempotency_key: req.body.formId, // generated once per render — a double-submit replays
    });
    res.status(202).json({ id });
  } catch {
    res.status(502).json({ error: "send failed" });
  }
});

Gotchas

Next

See it for yourself

Sandbox keys run the real pipeline dry — real validation, real events, a hosted inbox, no email sent. Early access is onboarding now.