Skip to content

Send and receive email in Next.js

Send from a route handler or server action with one fetch, no SDK, and receive email in another route handler through a signed webhook. Both work on Vercel, Node and Edge.

Updated

Send

app/api/contact/route.ts
// app/api/contact/route.ts
export async function POST(req: Request) {
  const { name, email, message } = await req.json();

  const res = await fetch("https://api.usemektup.com/v1/emails", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.MEKTUP_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      from: "website@yourapp.com",
      to: "hello@yourapp.com",
      replyTo: email,
      subject: `Message from ${name}`,
      text: message,
    }),
  });

  return Response.json(await res.json(), { status: res.status });
}

Add MEKTUP_API_KEY to your environment variables on Vercel or in .env.local. The same body works in a server action.

Receive

app/api/inbound/route.ts
// app/api/inbound/route.ts
import crypto from "node:crypto";

export async function POST(req: Request) {
  const raw = await req.text(); // the exact body Mektup signed
  const expected = crypto.createHmac("sha256", process.env.MEKTUP_WEBHOOK_SECRET!)
    .update(raw).digest("hex");
  const got = (req.headers.get("x-mektup-signature") ?? "").replace("sha256=", "");
  if (got.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))) {
    return new Response("bad signature", { status: 401 });
  }

  const { mailbox, message } = JSON.parse(raw);
  await saveTicket(mailbox, message); // your code
  return new Response(null, { status: 200 });
}

Set the webhook with PUT /v1/domains/:domain/mailboxes/:localPart/webhook and store the secret it returns as MEKTUP_WEBHOOK_SECRET. Answer within 8 seconds.

Questions

How do I send email from Next.js?

Call an email API from a route handler or a server action, with the key in an environment variable. With Mektup it is one fetch to https://api.usemektup.com/v1/emails; no SDK needed, and it works on the Node and Edge runtimes.

Can I use SMTP with Nodemailer instead?

Yes. Use mail.usemektup.com on port 465 with a mailbox address and password. The API is simpler on serverless platforms, where SMTP connections are slow to open.

How do I receive email in a Next.js app?

Set a Mektup mailbox webhook to a route handler, read the raw body with req.text(), verify the X-Mektup-Signature HMAC, then parse the JSON.

Start today, or talk to us?

Starter is $20 a month. Agencies get a quote for every client domain on one account.