Send email with Express
A POST route, one shared client, and the error handling Express 4 won't do for you.
Facts verified 2026-07-17 — corrections: hello@emailfast.dev
In Express, email lives in a route handler: parse the body, call ef.send, return the id. Create one EmailFast client at module scope and share it across requests — it is stateless and cheap. The only Express-specific work is error propagation, because Express 4 does nothing with a rejected async handler.
npm install @email-fast/nodejs// server.mjs
import express from "express";
import { EmailFast } from "@email-fast/nodejs";
const app = express();
app.use(express.json());
const ef = new EmailFast({ apiKey: process.env.EMAILFAST_API_KEY, baseUrl: "https://api.emailfast.dev" }); // ef_sandbox_… while testing
app.post("/signup", async (req, res, next) => {
const { email, name } = req.body;
try {
const { id } = await ef.send({
to: email,
subject: "Confirm your account",
html: "<p>Hi {{name}}, confirm your address here.</p>",
data: { name },
idempotency_key: `confirm-${email}`, // a double-POST can't double-send
});
res.status(202).json({ id });
} catch (err) {
next(err); // Express 4 won't catch async throws for you
}
});
app.use((err, req, res, next) => {
console.error(err);
res.status(502).json({ error: "email send failed" });
});
app.listen(3000);a 202 from the API means the send is committed to a durable, partitioned outbox before we answer — a crash can't lose it, and a retry with the same idempotency key can't double-send.
Gotchas
- Express 4 silently drops rejected promises from async handlers — wrap in
try/catchand callnext(err). Express 5 propagates them, but the explicit catch works in both. - Without
app.use(express.json()),req.bodyisundefinedand every send fails on a missing recipient. - Don't loop sends inside a request:
/v1/emails/batchtakes up to 500 messages in one call, with per-recipient idempotency. - Key the idempotency on domain data (
confirm-${email}), so client retries and refresh-resubmits collapse into one send.
Next
- Full Node.js quickstart — timelines, webhooks, batch
- The email API — batch, scheduling, suppressions
- Sending from Fastify
- All docs