Prompt
How do I send emails from a Next.js app?
Latest observation
Sep 23, 2026
OpenAI APIWeb search: off
You generally don’t send email directly from the browser in a Next.js app. Instead, you send the request to a server-side API route / server action, and that server code talks to an email provider or SMTP server.
Common ways to send email from Next.js
1) Use an email service API
Good options:
- Resend
- SendGrid
- Postmark
- Mailgun
This is the easiest and most reliable approach.
2) Use SMTP with Nodemailer
Works if you already have an SMTP server, but can be trickier in serverless environments.
Recommended approach: API route + email provider
1. Install a provider SDK
Example with Resend:
npm install resend
2. Create an API route
If you’re using the App Router, create:
app/api/send-email/route.ts
import { NextResponse } from "next/server";
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY!);
export async function POST(req: Request) {
try {
const { name, email, message } = await req.json();
const result = await resend.emails.send({
from: "Your App <onboarding@resend.dev>",
to: "you@example.com",
subject: `New message from ${name}`,
html: `
<p><strong>Name:</strong> ${name}</p>
<p><strong>Email:</strong> ${email}</p>
<p><strong>Message:</strong> ${message}</p>
`,
});
return NextResponse.json({ success: true, result });
} catch (error) {
console.error(error);
return NextResponse.json(
{ success: false, error: "Failed to send email" },
{ status: 500 }
);
}
}
3. Add your API key to .env.local
RESEND_API_KEY=your_api_key_here
4. Call it from your form
Example client component:
"use client";
import { useState } from "react";
export default function ContactForm() {
const [loading, setLoading] = useState(false);
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setLoading(true);
const formData = new FormData(e.currentTarget);
const data = Object.fromEntries(formData.entries());
const res = await fetch("/api/send-email", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
setLoading(false);
if (res.ok) {
alert("Email sent!");
} else {
alert("Failed to send email");
}
}
return (
<form onSubmit={handleSubmit}>
<input name="name" placeholder="Name" required />
<input name="email" type="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" required />
<button disabled={loading} type="submit">
{loading ? "Sending..." : "Send"}
</button>
</form>
);
}
If you prefer SMTP: Nodemailer
Install
npm install nodemailer
API route example
app/api/send-email/route.ts
import { NextResponse } from "next/server";
import nodemailer from "nodemailer";
export async function POST(req: Request) {
try {
const { name, email, message } = await req.json();
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
secure: false,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
await transporter.sendMail({
from: process.env.SMTP_FROM,
to: process.env.SMTP_TO,
subject: `Message from ${name}`,
text: `From: ${name} <${email}>\n\n${message}`,
});
return NextResponse.json({ success: true });
} catch (error) {
console.error(error);
return NextResponse.json(
{ success: false, error: "Failed to send email" },
{ status: 500 }
);
}
}
Important notes
- Never expose API keys in client-side code
- Use server-side code only for sending emails
- Add spam protection if this is a public form:
- rate limiting
- CAPTCHA
- input validation
- Check whether your deployment platform supports SMTP or serverless functions properly
Best practice recommendation
If you’re starting fresh, use:
- Next.js App Router
- API route or server action
- Resend or Postmark
They’re simpler than raw SMTP and usually more reliable in production.
If you want, I can give you:
- a complete contact form example for Next.js App Router, or
- a server action version instead of an API route.