Guide
How to send email with Express
Send email from an Express route with fetch - no SDK needed.
In short
Create a Sendpository account, verify your domain, put your API key inSENDPOSITORY_API_KEY, and send with the code below - one HTTPS request per email, from server-side code only.1. Verify your sending domain
Add your domain in the dashboard and publish the three DNS records it shows - SPF and a bounce record on an sp. subdomain, and a DKIM key on your apex. Your existing records are never edited. Verification usually lands in a few minutes, and you can set up the code below while you wait.
2. Create a key
Create an API key with the sending permission. It is shown once, so put it straight into your secrets. Load SENDPOSITORY_API_KEY from the environment (dotenv or your host's settings).
3. Send an email
import express from "express";
const app = express();
app.use(express.json());
app.post("/signup", async (req, res) => {
const r = await fetch("https://api.sendpository.com/v1/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SENDPOSITORY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "Your App <hello@mail.yourdomain.com>",
to: [req.body.email],
subject: "Confirm your email",
html: "<p>Click the link to confirm.</p>",
}),
});
const data = await r.json();
if (!r.ok) return res.status(502).json({ error: data.error.message });
res.json({ id: data.id });
});
app.listen(3000);A success returns { "id": "..." } - the message’s id for looking it up later. A failure returns { "error": { "type", "message" } } with a 4xx or 5xx status.
Where the send belongs
In the route handler, but after `res.json()` has gone out, or in a worker the route hands off to. An `await` before the response turns every email into added latency on a request the user is watching.
Put the send behind a small module rather than calling fetch inline in the route - it keeps the key in one place and gives you something to stub in tests.
Testing it
- Rate-limit any public route that sends. A contact form is the first thing a spammer finds, and your quota is the thing they spend.
- `express.json()` must come before the route, or the body is undefined and the error you get back will be about your own payload rather than the API.
Things to know
- Every error has the shape { error: { type, message } } - log type, show message.
- Send after your database write succeeds, so a failed signup never sends a welcome email.
Questions
Where in the route should the send go?
After `res.json()`, or in a worker the route hands off to. Awaiting the send before responding adds the full API round trip to a request the user is watching, and Express gives you no way to stream the response first.
How do I send email with Express?
Verify your sending domain, create an API key, put it in an environment variable, and POST the message as JSON to https://api.sendpository.com/v1/emails from server-side Express code. The example on this page runs as written once the domain is verified.
Can I send email with Express without SMTP?
Yes. This is plain HTTPS, so Express needs no mail library and no SMTP port - which matters on hosts that block outbound 25 and 587. Failures come back as a status code on the call instead of as a bounce message hours later.
More guides
Send email with Node.js
Send email from any Node.js app with the typed SDK or plain fetch.
Send email with Next.js
Send transactional email from a Next.js App Router server action or route handler.
Send your first email in minutes
6,000 emails a month (up to 200 a day), free forever. No card needed.