Email for your Next.js app — receive inbound email as a signature-verified App Router route handler, reply from your own handler, send over a verified domain.
The official MailKite package for Next.js.
Docs · Library guide · mailkite.dev
createMailKiteRouteHandler(handler) builds the POST export for an App Router route. When mail
arrives at any address on your verified domain, MailKite POSTs a signed email.received event to
that route; the package verifies the x-mailkite-signature header (HMAC-SHA256, no network call)
and hands the parsed event to your handler function. It also exports sendEmail() and the webhook
reply helpers so an auto-reply bot is a two-file affair.
Next.js has no plugin/module system like Astro or Nuxt, so there's no auto-discovered handler file or injected route — you create the route file yourself and pass your handler in explicitly. That's the whole integration surface.
npm install next-mailkite// lib/mailkite-handler.ts
import { sendEmail, replyOk } from 'next-mailkite';
import type { MailKiteInboundHandler } from 'next-mailkite';
const handler: MailKiteInboundHandler = async (event) => {
const m = event.message;
if (event.type !== 'email.received' || !m) return replyOk();
await sendEmail({
from: 'bot@myapp.ai', // an address on your verified domain
to: m.from,
subject: `Re: ${m.subject ?? 'your email'}`,
inReplyTo: m.messageId,
text: 'Thanks — got your message. A human will follow up soon.',
});
return replyOk();
};
export default handler;// app/api/mailkite/inbound/route.ts
import { createMailKiteRouteHandler } from 'next-mailkite';
import handler from '@/lib/mailkite-handler';
export const { POST } = createMailKiteRouteHandler(handler);Point your MailKite domain webhook at https://your-app.com/api/mailkite/inbound
(dashboard → domain → Webhooks, or mk.setWebhook(...) from the mailkite SDK).
No handler yet? Call createMailKiteRouteHandler() with no arguments (or null) — deliveries are
still verified, logged, and acknowledged; nothing is dropped silently.
Your handler can return:
| Return value | Response sent to MailKite |
|---|---|
undefined / void |
replyOk() — acknowledge |
a string — use replyOk(), replySpam(), replyDrop(), replyBlockSender() |
sent verbatim (control-mode replies act on the message) |
| a plain object | JSON-serialized |
a Response |
returned as-is |
| a thrown error | 500 — MailKite retries the delivery |
sendEmail() is a thin wrapper over the mailkite SDK's
send() that reads MAILKITE_API_KEY from the environment. Use it anywhere server-only —
server actions, route handlers — never from a "use client" component:
// app/actions.ts
'use server';
import { sendEmail } from 'next-mailkite';
export async function sendInvoice(to: string) {
return sendEmail({
from: 'hello@myapp.ai',
to,
subject: 'Your invoice #1042',
html: '<p>Thanks! Receipt attached.</p>',
});
}Need the full SDK surface (domains, templates, routes, broadcasts…)? Use mailkite directly —
it's already a dependency.
| Variable | Used by | Required | Where to get it |
|---|---|---|---|
MAILKITE_WEBHOOK_SECRET |
the route handler (signature verification) | for receiving | dashboard → Webhooks |
MAILKITE_API_KEY |
sendEmail() |
for sending | dashboard → API keys |
MailKite.verifyWebhook() uses node:crypto, so the inbound route must run on the Node.js
runtime — the App Router default. If you set export const runtime = 'edge' on the route file,
signature verification will fail to load; leave the runtime unset (or explicitly
export const runtime = 'nodejs').
| Export | What |
|---|---|
createMailKiteRouteHandler(handler?, options?) |
Builds { POST } for app/api/mailkite/inbound/route.ts. options.webhookSecret overrides MAILKITE_WEBHOOK_SECRET. |
handleInbound(request, handler, options?) |
The underlying verify → parse → dispatch logic, directly testable without a Next.js runtime. |
sendEmail(message, options?) |
Send over a verified domain. options.apiKey/options.baseUrl override the environment. |
replyOk() / replySpam() / replyDrop() / replyBlockSender() |
Control-mode webhook replies. |
MailKiteInboundEvent, MailKiteInboundMessage, MailKiteInboundHandler, MailKiteHandlerResult |
Types for handler authors. |
MIT © MailKite