Guides
Send email with Node
One import, one client, one awaited call — a script or serverless function is all it takes.
Facts verified 2026-07-17 — corrections: hello@emailfast.dev
Plain Node.js needs no framework to send email — a script, a queue consumer, or a serverless function calls @email-fast/nodejs directly. One import, one client, one awaited call. This page is the minimal recipe; the full Node quickstart adds message timelines and webhooks.
npm install @email-fast/nodejs// send.mjs — Node 18+
import { EmailFast } from "@email-fast/nodejs";
const ef = new EmailFast({ apiKey: process.env.EMAILFAST_API_KEY, baseUrl: "https://api.emailfast.dev" }); // ef_sandbox_… while testing
try {
const { id, status } = await ef.send({
to: "ada@example.com",
subject: "Nightly report",
html: "<p>{{rows}} rows processed.</p>",
data: { rows: 4210 },
idempotency_key: "report-2026-07-17", // re-running tonight's job can't double-send
});
console.log(`admitted ${id} (${status})`);
} catch (err) {
console.error("send rejected:", err.message);
process.exitCode = 1;
}EMAILFAST_API_KEY=ef_sandbox_... node send.mjsa 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
- Top-level
awaitneeds ESM: name the file.mjsor set"type": "module"inpackage.json. - Derive idempotency keys from your domain (
report-2026-07-17,invoice-8841), not from randomness — the key is exactly what makes a retried run harmless. - Catch and set
process.exitCodeinstead of letting an unhandled rejection kill the process — cron and CI read exit codes, not stack traces. - For cron jobs and CI, stay on a sandbox key as long as you like: sandbox keys (ef_sandbox_…) that run the real pipeline dry: real validation, real rendering, real events, a hosted capture inbox — and no email leaves.
Next
- Full Node.js quickstart — timelines, webhooks, batch
- The email API — scheduling and per-message events
- Sending from Express
- All docs