Examples
Typescript
Python
- Python Integration Overview
- Examples
Javascript
- JavaScript Overview
- Examples
Go
- Go Integration Overview
- Examples
PHP
- PHP Integration Overview
- Examples
cURL
Examples
Next.js SMTP Integration
Using SMTP with Next.js (App Router and Pages Router)
Next.js SMTP Integration
Learn how to integrate SMTP functionality with Next.js using both the App Router and Pages Router approaches.
Installation
Copy
npm install nodemailer
npm install -D @types/nodemailer
Configuration
Add SMTP configuration to your environment variables (.env.local
):
Copy
SMTP_HOST=smtp.shoutbox.net
SMTP_PORT=587
SMTP_USER=shoutbox
SMTP_PASS=your_api_key_here
SMTP Client Setup
Copy
// lib/smtp.ts
import nodemailer from "nodemailer";
export const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: parseInt(process.env.SMTP_PORT || "587"),
secure: process.env.SMTP_PORT === "465",
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
export interface EmailRequest {
from: string;
to: string;
subject: string;
html: string;
attachments?: Array<{
filename: string;
content: Buffer;
}>;
}
export async function sendEmail(request: EmailRequest) {
return transporter.sendMail(request);
}
App Router Integration
API Route Handler (Route Handlers)
Copy
// app/api/send-email/route.ts
import { sendEmail } from "@/lib/smtp";
import { NextResponse } from "next/server";
export async function POST(request: Request) {
try {
const { to, subject, html } = await request.json();
const result = await sendEmail({
from: "[email protected]",
to,
subject,
html,
});
return NextResponse.json({ success: true, messageId: result.messageId });
} catch (error) {
console.error("SMTP Error:", error);
return NextResponse.json(
{ success: false, error: error.message },
{ status: 500 }
);
}
}
Server Component Usage
Copy
// app/contact/page.tsx
import { sendEmail } from "@/lib/smtp";
async function ContactPage() {
async function sendContactEmail(formData: FormData) {
"use server";
try {
await sendEmail({
from: "[email protected]",
to: formData.get("email") as string,
subject: "Contact Form Submission",
html: formData.get("message") as string,
});
} catch (error) {
console.error("Failed to send email:", error);
throw new Error("Failed to send email");
}
}
return (
<form action={sendContactEmail}>
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>
);
}
export default ContactPage;
File Attachments in Server Actions
Copy
// app/upload/page.tsx
import { sendEmail } from "@/lib/smtp";
async function UploadPage() {
async function sendWithAttachment(formData: FormData) {
"use server";
const file = formData.get("file") as File;
const buffer = Buffer.from(await file.arrayBuffer());
try {
await sendEmail({
from: "[email protected]",
to: formData.get("email") as string,
subject: "File Attachment",
html: "<h1>Your file is attached</h1>",
attachments: [
{
filename: file.name,
content: buffer,
},
],
});
} catch (error) {
console.error("Failed to send email:", error);
throw new Error("Failed to send email");
}
}
return (
<form action={sendWithAttachment}>
<input type="email" name="email" required />
<input type="file" name="file" required />
<button type="submit">Send</button>
</form>
);
}
export default UploadPage;
Pages Router Integration
API Route
Copy
// pages/api/send-email.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { sendEmail } from "@/lib/smtp";
export const config = {
api: {
bodyParser: {
sizeLimit: "10mb",
},
},
};
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== "POST") {
return res.status(405).json({ message: "Method not allowed" });
}
try {
const { to, subject, html } = req.body;
const result = await sendEmail({
from: "[email protected]",
to,
subject,
html,
});
res.status(200).json({ success: true, messageId: result.messageId });
} catch (error) {
console.error("SMTP Error:", error);
res.status(500).json({ success: false, error: error.message });
}
}
File Upload API Route
Copy
// pages/api/send-with-attachment.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { sendEmail } from "@/lib/smtp";
import formidable from "formidable";
import { createReadStream } from "fs";
export const config = {
api: {
bodyParser: false,
},
};
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== "POST") {
return res.status(405).json({ message: "Method not allowed" });
}
try {
const form = formidable({});
const [fields, files] = await form.parse(req);
const file = files.file?.[0];
if (!file) {
return res.status(400).json({ error: "No file uploaded" });
}
const result = await sendEmail({
from: "[email protected]",
to: fields.email?.[0] || "",
subject: "File Attachment",
html: "<h1>Your file is attached</h1>",
attachments: [
{
filename: file.originalFilename || "attachment",
content: createReadStream(file.filepath),
},
],
});
res.status(200).json({ success: true, messageId: result.messageId });
} catch (error) {
console.error("SMTP Error:", error);
res.status(500).json({ success: false, error: error.message });
}
}
Best Practices
Security
- Always keep SMTP credentials in environment variables
- Validate email inputs on both client and server
- Implement rate limiting for your API routes
- Use appropriate CORS settings
- Validate file uploads and implement size limits
Error Handling
Copy
// lib/errors.ts
export class SMTPError extends Error {
constructor(
message: string,
public code?: string,
public responseCode?: number
) {
super(message);
this.name = "SMTPError";
}
}
// Reusable error handler
const handleSMTPError = (error: unknown) => {
console.error("SMTP Error:", error);
if (error instanceof SMTPError) {
switch (error.code) {
case "ECONNECTION":
return "Failed to connect to email server";
case "EAUTH":
return "Authentication failed";
default:
return "Failed to send email";
}
}
return "An unexpected error occurred";
};
Rate Limiting
Copy
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { rateLimit } from "./lib/rate-limit";
export async function middleware(request: NextRequest) {
if (request.nextUrl.pathname.startsWith("/api/send-email")) {
const ip = request.ip ?? "127.0.0.1";
const { success } = await rateLimit(ip);
if (!success) {
return NextResponse.json({ error: "Too many requests" }, { status: 429 });
}
}
return NextResponse.next();
}
TypeScript Types
Copy
// types/email.ts
export interface EmailAttachment {
filename: string;
content: Buffer | NodeJS.ReadableStream;
contentType?: string;
}
export interface EmailRequest {
from: string;
to: string;
subject: string;
html: string;
attachments?: EmailAttachment[];
}
export interface EmailResponse {
success: boolean;
messageId?: string;
error?: string;
}
Testing
Copy
// __tests__/api/send-email.test.ts
import { createMocks } from "node-mocks-http";
import handler from "../../pages/api/send-email";
jest.mock("nodemailer", () => ({
createTransport: jest.fn().mockReturnValue({
sendMail: jest.fn().mockResolvedValue({
messageId: "test-message-id",
}),
}),
}));
describe("/api/send-email", () => {
it("sends email successfully", async () => {
const { req, res } = createMocks({
method: "POST",
body: {
to: "[email protected]",
subject: "Test",
html: "<p>Test content</p>",
},
});
await handler(req, res);
expect(res._getStatusCode()).toBe(200);
expect(JSON.parse(res._getData())).toEqual(
expect.objectContaining({
success: true,
messageId: expect.any(String),
})
);
});
});
Rate Limits
The same rate limits apply to both SMTP and REST API usage:
- 60 requests per minute per API key
- Maximum attachment size: 10MB
- Maximum recipients per email: 50
Please contact support if you need higher limits for your use case.
Support
For additional support or questions, please contact our support team.
On this page
- Next.js SMTP Integration
- Installation
- Configuration
- SMTP Client Setup
- App Router Integration
- API Route Handler (Route Handlers)
- Server Component Usage
- File Attachments in Server Actions
- Pages Router Integration
- API Route
- File Upload API Route
- Best Practices
- Security
- Error Handling
- Rate Limiting
- TypeScript Types
- Testing
- Rate Limits
- Support
Assistant
Responses are generated using AI and may contain mistakes.