Launch Special: Use code LAUNCH20 for $20 off — Just $59 $79
Logo
Back

Send React Email with Postmark in Next.js (2026 Guide)

Step-by-step guide to sending React Email templates with Postmark in Next.js. Covers install, env setup, App Router & Pages Router examples, error handling, and tips.

Guides
Soufiane E.
Soufiane E.
8 min read
Send React Email with Postmark in Next.js (2026 Guide)

Postmark is a transactional email service focused on fast, reliable delivery. It has a straightforward API and excellent deliverability for password resets, receipts, and notifications. This guide shows you exactly how to integrate React Email with Postmark in a Next.js project — covering environment setup, rendering templates to HTML, sending with both App Router and Pages Router, and handling common errors.


Prerequisites

Before starting, you need:

  • A Postmark account with API credentials
  • A Next.js project (App Router or Pages Router — both covered below)
  • Node.js 18+

Step 1: Install Dependencies

npm install postmark @react-email/render

@react-email/render converts your React Email component to an HTML string, which you then pass to Postmark's API. Unlike Resend (which accepts React elements directly), most providers require rendered HTML.


Step 2: Configure Environment Variables

Add the following to your .env.local file:

POSTMARK_SERVER_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  • POSTMARK_SERVER_TOKENFound in your Postmark server settings under "API Tokens"

When deploying, add these variables in your hosting provider's environment settings (Vercel dashboard, Railway, Fly.io, etc.). Variables in .env.local do not deploy automatically.


Step 3: Create a React Email Template

Create an emails/ directory and add your first template. All providers use the same React Email template format — the difference is only in how you send it.

// emails/welcome-email.tsx
import * as React from 'react';
import {
Body, Button, Container, Head,
Heading, Html, Preview, Section, Text,
} from '@react-email/components';
interface WelcomeEmailProps {
username: string;
dashboardUrl: string;
}
export function WelcomeEmail({ username, dashboardUrl }: WelcomeEmailProps) {
return (
<Html>
<Head />
<Preview>Your account is ready — let's get started</Preview>
<Body style={{ fontFamily: 'sans-serif', backgroundColor: '#f4f4f5' }}>
<Container style={{ margin: '0 auto', padding: '40px 20px', maxWidth: '560px' }}>
<Heading>Welcome, {username}!</Heading>
<Text>Your account is set up and ready to use.</Text>
<Section>
<Button
href={dashboardUrl}
style={{ backgroundColor: '#000', color: '#fff', padding: '12px 24px', borderRadius: '6px' }}
>
Go to Dashboard
</Button>
</Section>
</Container>
</Body>
</Html>
);
}
WelcomeEmail.PreviewProps = {
username: 'Alex',
dashboardUrl: 'https://example.com/dashboard',
} as WelcomeEmailProps;
export default WelcomeEmail;

Preview locally

Before sending real emails, use the React Email dev server to preview your templates:

npx react-email dev --dir emails

Open http://localhost:3000 to see your templates rendered exactly as they will appear in email clients.



Step 4: Initialize the Postmark Client

Create the client once at module level so it's reused across requests:

import { ServerClient } from 'postmark';
const client = new ServerClient(process.env.POSTMARK_SERVER_TOKEN!);

Step 5: Create the API Route

App Router (app/api/send/route.ts)

import { render } from '@react-email/render';
import { ServerClient } from 'postmark';
import { WelcomeEmail } from '../../../emails/welcome-email';
const client = new ServerClient(process.env.POSTMARK_SERVER_TOKEN!);
export async function POST(request: Request) {
const { username, email } = await request.json();
const html = await render(
<WelcomeEmail username={username} dashboardUrl="https://yourdomain.com/dashboard" />
);
const result = await client.sendEmail({
From: 'hello@yourdomain.com',
To: email,
Subject: `Welcome, ${username}!`,
HtmlBody: html,
MessageStream: 'outbound',
});
return Response.json({ messageId: result.MessageID });
}

Pages Router (pages/api/send.ts)

import type { NextApiRequest, NextApiResponse } from 'next';
import { render } from '@react-email/render';
import { ServerClient } from 'postmark';
import { WelcomeEmail } from '../../emails/welcome-email';
const client = new ServerClient(process.env.POSTMARK_SERVER_TOKEN!);
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'POST') return res.status(405).end();
const { username, email } = req.body;
const html = await render(
<WelcomeEmail username={username} dashboardUrl="https://yourdomain.com/dashboard" />
);
const result = await client.sendEmail({
From: 'hello@yourdomain.com',
To: email,
Subject: `Welcome, ${username}!`,
HtmlBody: html,
MessageStream: 'outbound',
});
return res.status(200).json({ messageId: result.MessageID });
}

Postmark-Specific Tips

  • You must specify `MessageStream: "outbound"` for transactional emails. Postmark separates transactional and broadcast streams.
  • Your `From` address must be a verified sender signature in the Postmark dashboard.
  • Postmark has a sandbox mode — use the test API token (`POSTMARK_API_TEST`) during development to process emails without delivering them.
  • Postmark supports `TextBody` alongside `HtmlBody`. Use `render(component, { plainText: true })` from `@react-email/render` to generate the plain-text version.

Common Errors and Fixes

ErrorCauseFix
Invalid API tokenWrong token or using account token instead of server tokenUse the Server API Token from your specific Postmark server, not the account-level token
Sender signature not foundThe From address is not a verified sender in PostmarkAdd and verify your From address under Sender Signatures in the Postmark dashboard
Message stream not foundMissing or wrong MessageStream valueSet MessageStream to "outbound" for transactional emails

Organizing Multiple Email Templates

A SaaS app typically needs 8–12 email templates. Keep them organized in a dedicated directory:

emails/
├── welcome-email.tsx
├── otp-email.tsx
├── magic-link.tsx
├── password-reset.tsx
├── payment-receipt.tsx
├── trial-started.tsx
├── trial-ending.tsx
└── security-alert.tsx

Each template uses the same @react-email/components primitives and is rendered to HTML with @react-email/render before being passed to Postmark.

If you don't want to write and cross-client test all these templates from scratch, the React Email Templates bundle includes 12 production-ready templates for the most common SaaS email flows — tested on Gmail, Outlook, Apple Mail, and mobile clients in both light and dark mode.


Related Guides