⚡
CentricSell Mail
Developer Integration8 min readUpdated 2026-04-05

How to Send Email in Node.js & TypeScript with Nodemailer & Custom SMTP

Complete guide to sending transactional emails in Node.js, Express, and Next.js using Nodemailer. Configure connection pooling, STARTTLS encryption, and integrate with CentricSell Mail's high-speed SMTP relay.

Executive Key Takeaways

  • •Enable pool: true in Nodemailer to reuse SMTP connections across multiple requests, reducing latency by up to 70%.
  • •Never store SMTP credentials in source code; load them via process.env.
  • •CentricSell Mail provides automated multi-ESP failover behind a single Nodemailer transporter endpoint.
  • •Always set both text and html properties in mailOptions to prevent spam filtering.

1. Installing Nodemailer & TypeScript Types

Install Nodemailer and its TypeScript definitions:

npm install nodemailer
npm install -D @types/nodemailer

2. Configuring Connection Pooling & Transporters

Create a singleton transporter with pool: true. This keeps TCP connections open and multiplexes messages:

3. Complete TypeScript Sending Function

import nodemailer from "nodemailer";

export const mailer = nodemailer.createTransport({
  host: process.env.SMTP_HOST || "smtp.centricsell.com",
  port: Number(process.env.SMTP_PORT) || 587,
  secure: false, // true for 465, false for 587 (STARTTLS)
  auth: {
    user: process.env.CENTRICSELL_API_KEY!,
    pass: process.env.CENTRICSELL_API_SECRET!,
  },
  pool: true,
  maxConnections: 5,
  maxMessages: 100,
});

export async function sendEmail({
  to,
  subject,
  html,
  text,
}: {
  to: string;
  subject: string;
  html: string;
  text: string;
}) {
  const info = await mailer.sendMail({
    from: '"CentricSell Mail" <support@yourdomain.com>',
    to,
    subject,
    text,
    html,
  });

  return info.messageId;
}

4. Sending from Next.js 15 Server Actions

"use server";

import { sendEmail } from "@/lib/email";

export async function handleContactForm(formData: FormData) {
  const email = formData.get("email") as string;
  const message = formData.get("message") as string;

  await sendEmail({
    to: "team@yourdomain.com",
    subject: "New Customer Inquiry",
    text: `From: ${email}\nMessage: ${message}`,
    html: `<p><strong>From:</strong> ${email}</p><p>${message}</p>`,
  });

  return { success: true };
}

5. Production Best Practices & Error Handling

  • Always verify connection health during application startup using mailer.verify().
  • Log info.messageId and info.response to correlate with delivery webhooks.
  • Catch Error: Connection timeout and retry with exponential backoff.
⚡
CentricSell Mail Automation

Automate Developer Integration in 5 Minutes

Stop manually wrestling with DNS records and server configs. CentricSell Mail runs automated pre-flight deliverability checks, provisions dedicated servers over SSH, and routes traffic across Amazon SES, SendGrid, and Mailgun.

Create Free Account →10,000 Free Contacts Included

Frequently Asked Questions

Why should I use connection pooling in Nodemailer?

Without pooling, Nodemailer establishes a new TCP and TLS handshake for every single email, adding 300ms+ of overhead per send. With pool: true, open connections are kept alive and reused.

Does Nodemailer work with Next.js App Router and Server Actions?

Yes! Nodemailer can be called directly inside Server Actions ('use server') or API Route handlers in Next.js.

High-Availability Email Infrastructure

Ready to scale your transactional & bulk email?

Get started with CentricSell Mail in minutes. Bring your existing AWS SES, SendGrid, or Mailgun credentials, or deploy onto your own dedicated VPS with verified SPF, DKIM, and rDNS.

PostgreSQL RLS Isolation
Multi-Provider Failover
Zero Per-Email Fees