How to ship transactional email in Next.js
2026-09-07 · 3 min
Transactional email in Next.js is the mail your product must send: a contact-form copy to your inbox, a password reset, an order receipt. It is not a newsletter. Mixing the two in the same SMTP identity is how Gmail starts treating your resets as promotions.
What is a transactional email in a Next.js app?
A transactional email is a message triggered by a user action or a system event, addressed to one recipient, with no marketing list. In the App Router that almost always means a Route Handler (app/api/.../route.ts) that validates the payload, talks to an email API, and returns 202 or an error the UI can show. Keep the provider API key on the server. A publishable key in a client bundle is an abuse magnet.
MailingCore is a European email API for this job: JS SDK or REST, versioned templates, EU data residency. The Free plan is 100 emails per month and 5 templates. You can still call it from a Next.js server route; do not paste a live mc_live_ key into a Client Component.
Minimal architecture
- A server route that sanitizes fields, checks a honeypot, and rate-limits by IP.
- Credentials in environment variables (
MAILINGCORE_API_KEY, neverNEXT_PUBLIC_for live keys). - A published template slug for each message type (
contact-form,password-reset). - An idempotency key on retries so a double-click does not send twice.
- Logs in the dashboard — not
console.logof the full recipient list.
Contact form pattern
Validate on the server even if the form already checked HTML required. Reject empty honeypots that bots fill. Then send with a template so marketing can edit copy without a deploy:
POST /api/contactreceives name, email, message.- The route calls
MailingCore.sendTemplate({ slug: "contact-inbox", to: process.env.CONTACT_INBOX, data }). - Optionally send a second template to the visitor as confirmation.
If you need the visitor to receive a copy, treat that as a second transactional send, not a BCC of the internal ticket. BCC is how you leak other people's addresses into a thread.
Password resets and receipts
Use a dedicated From domain with SPF, DKIM and DMARC aligned. Disable open/click tracking on security mail: a tracking pixel and rewritten links look like bulk to mailbox providers. MailingCore documents trackingDisabled per send for that reason.
Store tokens hashed. Expire them. Never log the full reset URL.
GDPR for EU Next.js teams
If your users are in the EU, the email provider is a processor. A sending region in Ireland does not by itself mean logs and templates live in the Union. Prefer a vendor that states EU storage for account data — or accept SCCs and document them. MailingCore stores data in Europe; Resend's EU region is a sending location with account data still in the US according to their public policy. Verify current vendor docs before you tell a DPO otherwise.
What to do next
Ship the contact route first. Add domain authentication before production traffic. Then add templates for auth and billing. See the quickstart and the MailingCore vs Resend page if data residency is the reason you are choosing a provider.