Guides

Send email from Next.js: API route or SMTP relay

There are two straightforward ways to send email from a Next.js app server-side: call the REST API directly from a Route Handler, or use the SMTP relay through a library like Nodemailer from a Server Action. Both run through the identical send pipeline server-side, so pick whichever fits your existing code — this repo's own marketing site uses the REST API pattern for its waitlist emails.

  1. 1.Set the API key as an environment variable

    Create an API key with `sending_access` (or `full_access`) and store it server-side only — never in a client component or `NEXT_PUBLIC_` variable.

    IRISEND_API_KEY=ir_xxxxxxxxxxxxxxxxxxxx
  2. 2.Option A — a Route Handler calling the REST API

    A plain `fetch` to `POST /emails` from a Route Handler. No SDK required, though `@irisend/sdk` wraps the same call with a typed `{ data, error }` return.

    app/api/send/route.tsTypeScript
    export async function POST(request: Request) {
      const { to, subject, html } = await request.json();
    
      const res = await fetch("https://api.irisend.com/emails", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.IRISEND_API_KEY}`,
          "Content-Type": "application/json",
          "Idempotency-Key": crypto.randomUUID(),
        },
        body: JSON.stringify({ from: "[email protected]", to, subject, html }),
      });
    
      if (!res.ok) return Response.json(await res.json(), { status: res.status });
      return Response.json(await res.json());
    }
  3. 3.Option B — a Server Action over SMTP

    The SMTP relay runs the exact same `sendEmailSchema` validation and send pipeline as the REST API — domain verification, suppressions, quotas and rate limits behave identically regardless of transport.

    app/actions/send-receipt.tsTypeScript
    "use server";
    import nodemailer from "nodemailer";
    
    const transport = nodemailer.createTransport({
      host: "smtp.irisend.com",
      port: 587, // or 465 for implicit TLS
      secure: false, // true only for port 465
      auth: { user: "irisend", pass: process.env.IRISEND_API_KEY },
    });
    
    export async function sendReceipt(to: string) {
      await transport.sendMail({
        from: "[email protected]",
        to,
        subject: "Your receipt",
        html: "<p>Thanks for your order.</p>",
        headers: { "Idempotency-Key": `receipt-${to}` },
      });
    }

Related

Next

Read the full API reference, the Resend migration guide, or see pricing.