Send emails with Next.js
In this quickstart, you'll learn how to send transactional emails from your Next.js 13, 14, or 15 (App Router) app with Sidemail. You'll set up the SDK, send your first email, and see examples for common use cases like welcome emails, password resets, and server actions.
Note: The Sidemail SDK is designed for server-side usage only. Use it in Route Handlers, Server Actions, or Server Components. Do not use it in Client Components.
Before you start
- Create a Sidemail account → get your API key
- Add a sending domain → set up your domain for sending
1. Install
npm install sidemail
2. Configure API key
Add your Sidemail API key to .env.local:
SIDEMAIL_API_KEY=your-api-key
3. Setup client
Create a shared instance of the Sidemail client.
// lib/sidemail.js
import configureSidemail from "sidemail";
const sidemail = configureSidemail({
apiKey: process.env.SIDEMAIL_API_KEY,
});
export default sidemail;
4. Send a welcome email
Send an email when a user registers using a Route Handler.
// app/api/register/route.js
import { NextResponse } from "next/server";
import sidemail from "@/lib/sidemail";
export async function POST(request) {
const { email, name } = await request.json();
// ... create user in database ...
await sidemail.sendEmail({
toAddress: email,
fromAddress: "[email protected]",
fromName: "Your App",
templateName: "Welcome",
templateProps: { firstName: name },
});
return NextResponse.json({ message: "User registered" });
}
5. Send a password reset email
// app/api/auth/forgot-password/route.js
import { NextResponse } from "next/server";
import sidemail from "@/lib/sidemail";
export async function POST(request) {
const { email } = await request.json();
const token = "secure-reset-token"; // Generate this securely
await sidemail.sendEmail({
toAddress: email,
fromAddress: "[email protected]",
fromName: "Your App",
templateName: "Password Reset",
templateProps: {
actionUrl: `https://myapp.com/reset/${token}`,
},
});
return NextResponse.json({ message: "Reset email sent" });
}
6. Send a weekly report (Cron Job)
Next.js doesn't have a built-in scheduler. Instead, you create an API route and trigger it using an external service like Vercel Cron, GitHub Actions, or a standard cron job.
// app/api/cron/weekly-report/route.js
import { NextResponse } from "next/server";
import sidemail from "@/lib/sidemail";
export async function GET() {
// In a real app, fetch this from your database
const newSignups = 150;
const chartData = [100, 200, 300, 400, 200, 300, 200, 500];
await sidemail.sendEmail({
toAddress: "[email protected]",
fromAddress: "[email protected]",
fromName: "My App",
templateName: "Weekly Report",
templateProps: {
signups: newSignups,
chart: chartData,
},
});
return NextResponse.json({ message: "Weekly report sent" });
}
7. Send email via Server Action
Send an email directly from a form submission using Server Actions.
// app/actions.js
"use server";
import sidemail from "@/lib/sidemail";
export async function sendInvoice(formData) {
const email = formData.get("email");
await sidemail.sendEmail({
toAddress: email,
fromAddress: "[email protected]",
fromName: "Your App",
subject: "Your Invoice",
text: "Here is your invoice.",
});
}
8. Send HTML email
// app/api/send-html/route.js
import { NextResponse } from "next/server";
import sidemail from "@/lib/sidemail";
export async function POST(request) {
const { email } = await request.json();
const htmlContent = `
<div>
<h1>Invoice</h1>
<p>Amount due: $99</p>
</div>
`;
await sidemail.sendEmail({
toAddress: email,
fromAddress: "[email protected]",
fromName: "Your App",
subject: "Your Invoice",
html: htmlContent,
});
return NextResponse.json({ message: "Invoice sent" });
}
9. Send Markdown email
Store your markdown content in a file and load it (learn more).
import { promises as fs } from "fs";
import path from "path";
import sidemail from "@/lib/sidemail";
export async function POST(request) {
const templatePath = path.join(process.cwd(), "templates/emails/welcome.md");
const markdownContent = await fs.readFile(templatePath, "utf8");
await sidemail.sendEmail({
toAddress: "[email protected]",
markdown: markdownContent,
templateProps: {
name: "John",
link: "https://example.com",
},
});
// ...
}
10. Send plain text email
await sidemail.sendEmail({
toAddress: "[email protected]",
fromAddress: "[email protected]",
fromName: "Your App",
subject: "Hello",
text: "Hello! 👋",
});
11. Schedule email
Send email later. Set scheduledAt to an ISO date string.
// Schedule for 1 hour from now
const scheduledAt = new Date(Date.now() + 60 * 60 * 1000).toISOString();
await sidemail.sendEmail({
toAddress: "[email protected]",
fromAddress: "[email protected]",
fromName: "Your App",
templateName: "Welcome",
templateProps: { firstName: "Alex" },
scheduledAt: scheduledAt,
});
12. Send with attachment
Use the sidemail.fileToAttachment helper to attach files.
import { promises as fs } from "fs";
import path from "path";
import sidemail from "@/lib/sidemail";
const pdfPath = path.join(process.cwd(), "public", "invoice.pdf");
const pdfData = await fs.readFile(pdfPath);
const attachment = sidemail.fileToAttachment("invoice.pdf", pdfData);
await sidemail.sendEmail({
toAddress: "[email protected]",
fromAddress: "[email protected]",
fromName: "Your App",
subject: "Your invoice",
text: "See attached.",
attachments: [attachment],
});
13. Handle errors
try {
await sidemail.sendEmail({
// ...
});
} catch (error) {
console.error("Sidemail error:", error.message);
return NextResponse.json({ error: "Failed to send email" }, { status: 500 });
}