Skip to content

Documentation

Send email from Next.js.

A route handler in the App Router that sends a welcome email safely.

Before you start

You need a verified sending domain (see Domains) and an API key (under API keys in the dashboard; it is shown once). Keep the key in an environment variable on your server, never in code that runs in a browser or an app.

Install

Add the client library. It uses fetch, so it runs in route handlers, server actions and edge runtimes.

Terminal
npm install mailtruss

The route handler

A route handler in the App Router. It escapes user input, reports Mailtruss errors instead of throwing, and uses an idempotency key so a retried request never sends twice.

app/api/welcome/route.ts
import { MailClient, MailError } from "mailtruss";
​
const mail = new MailClient({ apiKey: process.env.MAILTRUSS_API_KEY! });
const escapeHtml = (s: string) => s.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
​
export async function POST(req: Request) {
const { email, name } = await req.json();
try {
const { id } = await mail.emails.send(
{
from: "Acme <hello@yourdomain.com>",
to: email,
subject: "Welcome to Acme",
html: `<p>Hi ${escapeHtml(name)}, thanks for signing up.</p>`,
},
{ idempotencyKey: `welcome:${email}` }, // a retry of this request sends nothing twice
);
return Response.json({ id });
} catch (e) {
if (e instanceof MailError) {
const status = e.statusCode === 429 ? 503 : 502;
return Response.json({ error: e.code, message: e.message }, { status });
}
throw e;
}
}

Try it without sending real mail

Send to delivered@mailtruss.test first. It works before any domain is verified and reaches no real mailbox, so you can check your code and see the recorded timeline. Then try bounced@mailtruss.test to see what a bounce looks like. All the test addresses are listed under Sending.

See what happened

Open the message under Emails in the dashboard: it shows the recorded timeline, what each event proves, and a diagnosis if something went wrong. Or fetch it with GET /api/v1/emails/:id/events. To be told as it happens, add a webhook.

If it fails

API requests answer with an error name and message. The common ones:

  • 403 invalid_api_key or 401 missing_api_key: the key is wrong, revoked or not sent. Send it as Authorization: Bearer ms_live_….
  • 403 domain_not_verified: the from address is on a domain that is not verified. Publish the DNS records and re-check.
  • 422 validation_error: fix the field the message names. Nothing was sent and no quota was used.
  • 429 rate_limit_exceeded: back off for the Retry-After header. See rate limits.

Problems that happen after a message is accepted (bounces, complaints) are explained under delivery errors.

Other guides

Last updated

Something wrong or unclear on this page?

Report an issue