Send email from React: call your backend, which calls the Inboxili API

Updated

There is no React package for Inboxili, and there should not be one: an API key in browser code is public. React talks to your own server, and your server uses the Node, Python or PHP SDK.

React runs in the visitor's browser, so anything in its code or environment is public. The Inboxili API key can send email as your domain, which means it must live only on a server you control.

The architecture

How a transactional email is sent with InboxiliYour application calls the Inboxili API. Inboxili sends the email to the recipient, and delivery events return to your application by webhook.Your applicationOTP, reset, receiptInboxili APItemplates, sender checks, logsRecipient inboxyour verified domainPOST /sendemailwebhooks: delivered, bounced, complained
Sending is one request. Outcomes come back as signed webhook events.

Read the diagram with one change in mind: "Your application" is your server, and the browser's React code talks to it instead.

  1. React submits a form to your endpoint, such as POST /api/contact.
  2. Your server validates the input, applies rate limits, and calls the Inboxili SDK.
  3. Your endpoint returns a simple success or error to React.

The React side

import { useState, type FormEvent } from "react";

type Status = "idle" | "sending" | "sent" | "error";

export function ContactForm() {
  const [status, setStatus] = useState<Status>("idle");
  const [error, setError] = useState<string | null>(null);

  async function onSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const form = e.currentTarget;
    const data = Object.fromEntries(new FormData(form));
    setStatus("sending");
    setError(null);

    try {
      const res = await fetch("/api/contact", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(data),
      });
      if (!res.ok) throw new Error((await res.json().catch(() => ({}))).error ?? "Something went wrong.");
      setStatus("sent");
      form.reset();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Something went wrong.");
      setStatus("error");
    }
  }

  if (status === "sent") return <p role="status">Thanks, we have your message.</p>;

  return (
    <form onSubmit={onSubmit}>
      <label>Name <input name="name" required maxLength={100} /></label>
      <label>Email <input name="email" type="email" required /></label>
      <label>Message <textarea name="message" required minLength={5} maxLength={5000} /></label>
      {/* Honeypot: hidden from people, filled by bots */}
      <input name="website" tabIndex={-1} autoComplete="off" style={{ position: "absolute", left: "-9999px" }} aria-hidden="true" />
      <button disabled={status === "sending"}>{status === "sending" ? "Sending…" : "Send"}</button>
      {status === "error" && <p role="alert">{error}</p>}
    </form>
  );
}

The server side

Pick the backend you already have:

For a complete, abuse-resistant handler, see the contact form workflow. It covers the honeypot field above, escaping, fixed recipients and rate limits.

Common mistakes

| Mistake | Why it hurts | Instead | |---|---|---| | REACT_APP_INBOXILI_KEY or VITE_INBOXILI_KEY | Bundled into public JavaScript | Keep the key in a server environment variable | | Letting the form choose the recipient | Turns your domain into a spam relay | Fix the recipient in server code | | No loading state | Users click Send repeatedly and send duplicates | Disable the button while sending, as above | | Showing raw server errors | Leaks configuration | Return a generic message, log the detail | | Calling the API from a proxy that forwards the key from the browser | The key still reaches the browser | Attach the key only on the server |

Frequently asked questions

Can I put the Inboxili API key in a React environment variable?
No. Anything bundled into a React app is visible to every visitor. A leaked key can send email as your domain until you revoke it.
Do I need a server just to send one email?
Yes, a small one: an Express route, a Next.js route handler, or a serverless function. It also gives you somewhere to validate input and limit abuse.

Official SDKs

Build with Inboxili

Create a workspace, verify a domain, and make your first API call.

Related