Guides
Node.js Integration
Send emails from Node.js applications using Nodemailer or the NorthRelay SDK
Node.js Integration
This guide shows two approaches for sending email from Node.js: Nodemailer (SMTP) and the @northrelay/sdk package (REST API).
Using Nodemailer (SMTP)
Installation
npm install nodemailerBasic Example
const nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
host: "smtp.north-pipe.ca",
port: 587,
secure: false, // true for port 465, false for port 587 (STARTTLS)
auth: {
user: process.env.NORTHRELAY_USER,
pass: process.env.NORTHRELAY_API_KEY,
},
});
async function sendEmail() {
const info = await transporter.sendMail({
from: '"My App" <notifications@yourdomain.com>',
to: "recipient@example.com",
subject: "Welcome to My App",
text: "Thanks for signing up!",
html: "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
});
console.log("Message sent:", info.messageId);
return info;
}
sendEmail();TypeScript Example
import nodemailer from "nodemailer";
import type { Transporter } from "nodemailer";
const transporter: Transporter = nodemailer.createTransport({
host: "smtp.north-pipe.ca",
port: 587,
secure: false,
auth: {
user: process.env.NORTHRELAY_USER!,
pass: process.env.NORTHRELAY_API_KEY!,
},
});
interface SendEmailOptions {
to: string;
subject: string;
text: string;
html?: string;
}
async function sendEmail(options: SendEmailOptions) {
const info = await transporter.sendMail({
from: `"My App" <${process.env.NORTHRELAY_FROM}>`,
to: options.to,
subject: options.subject,
text: options.text,
html: options.html,
});
return info;
}Using @northrelay/sdk (REST API)
Installation
npm install @northrelay/sdkBasic Example
import { NorthRelayClient } from "@northrelay/sdk";
const client = new NorthRelayClient({
apiKey: process.env.NORTHRELAY_API_KEY!,
});
async function sendEmail() {
const result = await client.emails.send({
from: { email: "notifications@yourdomain.com", name: "My App" },
to: [{ email: "recipient@example.com" }],
content: {
subject: "Welcome to My App",
text: "Thanks for signing up!",
html: "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
},
});
console.log("Email queued:", result.data.messageId, result.data.status);
return result.data;
}
sendEmail().catch(console.error);Sending to Multiple Recipients
const result = await client.emails.send({
from: { email: "notifications@yourdomain.com" },
to: [{ email: "alice@example.com" }, { email: "bob@example.com" }],
content: {
subject: "Team Update",
text: "Here is the weekly team update.",
},
});A message takes at most 100 distinct recipients across to, cc and bcc.
Sending a Template
const result = await client.emails.sendTemplate(
"template_id",
[{ email: "jane@example.com", name: "Jane" }],
{ first_name: "Jane", order_id: "1234" },
{ from: { email: "orders@yourdomain.com" } }
);Error Handling
Nodemailer Error Handling
import nodemailer from "nodemailer";
const transporter = nodemailer.createTransport({
host: "smtp.north-pipe.ca",
port: 587,
secure: false,
auth: {
user: process.env.NORTHRELAY_USER!,
pass: process.env.NORTHRELAY_API_KEY!,
},
});
async function sendEmail(to: string, subject: string, html: string) {
try {
const info = await transporter.sendMail({
from: process.env.NORTHRELAY_FROM!,
to,
subject,
html,
});
return { success: true, messageId: info.messageId };
} catch (error: any) {
if (error.responseCode === 535) {
console.error("Authentication failed. Check your API key.");
} else if (error.responseCode === 451) {
console.error("Rate limit exceeded. Upgrade your plan or wait.");
} else if (error.code === "ECONNREFUSED") {
console.error("Connection refused. Check your firewall and port 587.");
} else if (error.code === "ETIMEDOUT") {
console.error("Connection timed out. Check network connectivity.");
} else {
console.error("Email send failed:", error.message);
}
return { success: false, error: error.message };
}
}SDK Error Handling
import { NorthRelayClient, NorthRelayError, RateLimitError } from "@northrelay/sdk";
const client = new NorthRelayClient({
apiKey: process.env.NORTHRELAY_API_KEY!,
});
async function sendEmail(to: string, subject: string, html: string) {
try {
const result = await client.emails.send({
from: { email: process.env.NORTHRELAY_FROM! },
to: [{ email: to }],
content: { subject, html },
});
return { success: true, messageId: result.data.messageId };
} catch (error) {
if (error instanceof RateLimitError) {
console.error(`Rate limited. Retry after ${error.retryAfter} seconds.`);
} else if (error instanceof NorthRelayError) {
console.error(`API error [${error.code}] (${error.statusCode}): ${error.message}`);
if (error.fixAction) {
console.error(`Suggested fix: ${error.fixAction}`);
}
} else {
console.error("Unexpected error:", error);
}
return { success: false };
}
}RateLimitError, ValidationError, AuthenticationError and the other error classes all extend NorthRelayError. See the TypeScript SDK for the full list.
Express.js Integration
Use the transporter as a singleton to reuse the SMTP connection pool across requests.
// lib/mailer.ts
import nodemailer from "nodemailer";
export const transporter = nodemailer.createTransport({
host: "smtp.north-pipe.ca",
port: 587,
secure: false,
auth: {
user: process.env.NORTHRELAY_USER!,
pass: process.env.NORTHRELAY_API_KEY!,
},
pool: true, // Enable connection pooling
maxConnections: 5,
maxMessages: 100,
});
export async function sendEmail(to: string, subject: string, html: string) {
return transporter.sendMail({
from: process.env.NORTHRELAY_FROM!,
to,
subject,
html,
});
}// routes/auth.ts
import express from "express";
import { sendEmail } from "../lib/mailer";
const router = express.Router();
router.post("/register", async (req, res) => {
const { email, name } = req.body;
// ... create user in database ...
await sendEmail(
email,
"Welcome!",
`<h1>Hi ${name}!</h1><p>Welcome to our platform.</p>`
);
res.json({ success: true });
});
export default router;Environment Variables
Store your NorthRelay credentials in environment variables. Never commit API keys to source control.
# .env
NORTHRELAY_USER=your-email@example.com
NORTHRELAY_API_KEY=nr_live_xxxxxxxxxxxx
NORTHRELAY_FROM="My App <notifications@yourdomain.com>"Load with dotenv or your framework's built-in env support:
import "dotenv/config";
// process.env.NORTHRELAY_API_KEY is now availableAdd .env to your .gitignore to prevent accidental credential exposure.
Related Guides
- SMTP Configuration — Full SMTP settings reference
- DNS Setup Guide — Configure SPF, DKIM, and DMARC
- Troubleshooting — Common issues and fixes