How to send email in Next.js
The simplest way to send email in Next.js is to call an email SDK from a route handler, so your key stays on the server. With Neuctra Mailer that is one npm install, four environment variables and one mailer.send() call, sending through your own Gmail, Outlook, Zoho or SES account.
Step 1: install the SDK and add your keys
Run npm install @neuctra/mailer. Create a service in Neuctra Mailer, connect your SMTP account, and create a server key under Settings. Then copy the values from the Overview tab into .env.local.
# .env.local (server only)
MAILER_URL=https://your-server-url
MAILER_SERVICE_ID=your-service-id
MAILER_SERVICE_NAME=your-service-name
MAILER_API_KEY=nm_sk_your-server-keyStep 2: send email from a route handler
Route handlers run on the server, so the server key never reaches the browser. Your pages call this route with fetch.
// app/api/order-confirmation/route.js
import { NeuctraMailer } from "@neuctra/mailer";
// No NEXT_PUBLIC_ prefix, so the server key never reaches the browser.
const mailer = new NeuctraMailer({
serverUrl: process.env.MAILER_URL,
serviceId: process.env.MAILER_SERVICE_ID,
serviceName: process.env.MAILER_SERVICE_NAME,
apiKey: process.env.MAILER_API_KEY, // the server key, nm_sk_...
});
export async function POST(request) {
const { email, orderId } = await request.json();
const { messageId } = await mailer.send({
to: email,
subject: `Order #${orderId} confirmed`,
html: `<p>Thanks! Order #${orderId} is on its way.</p>`,
});
return Response.json({ messageId });
}Or send from a client component
For a contact form that only emails you, you can skip the route and call the SDK from a client component with the public key (NEXT_PUBLIC_ variables). Limit it under Settings: add your site to Allowed websites and your address to Allowed recipients. This also works on a static export, with no server at all.
import { NeuctraMailer } from "@neuctra/mailer";
const mailer = new NeuctraMailer({
serverUrl: process.env.NEXT_PUBLIC_MAILER_URL,
serviceId: process.env.NEXT_PUBLIC_MAILER_SERVICE_ID,
serviceName: process.env.NEXT_PUBLIC_MAILER_SERVICE_NAME,
apiKey: process.env.NEXT_PUBLIC_MAILER_API_KEY,
});
await mailer.send({
to: "[email protected]",
replyTo: form.email,
subject: `New message from ${form.name}`,
text: form.message,
});Test locally without sending real email
- Use the test key (nm_test_...) in .env.development: it works from localhost
- Requests are checked and logged, but nothing is delivered except to your test addresses
- mailer.verify() checks the SMTP login without sending
- Send to [email protected] to see how your app handles a failure
Node.js, Express and other frameworks
The same SDK works in any Node.js 18+ server, such as Express, Fastify, Remix or a background job, and in React, Vue or plain browser JavaScript. Anything else can POST to the REST API.
Frequently asked questions
- Can I use Nodemailer in Next.js instead?
- Yes, in route handlers on the Node.js runtime. You then manage SMTP connections, retries and error messages yourself, and it can't run in the browser or on a static export. Neuctra Mailer handles those parts and works in both places.
- Does this work with the Next.js App Router and Pages Router?
- Yes. Use a route handler (app/api/.../route.js) in the App Router or an API route (pages/api) in the Pages Router. The SDK call is the same.
- Where do I put the API key in Next.js?
- Put the server key in a variable without the NEXT_PUBLIC_ prefix and use it only in route handlers or server code. Only the public key, limited to your websites, should ever use NEXT_PUBLIC_.
- Can Next.js send a welcome email when someone signs up?
- Yes. Call mailer.subscribe() with your newsletter's id, and turn on the newsletter's welcome email in the dashboard. It goes out right away.
Send your first email today
Create a service, add your SMTP login and send a test. It takes about two minutes.