Last updated: 2025-01-22•8 min read
Send Email with Node.js: Complete Guide
Learn how to send transactional emails with Node.js using the Truncus SDK. This guide covers setup, basic sending, templates, and error handling.
Prerequisites
- Node.js 18+ or 20+
- A Truncus account (free tier available)
- A verified sending domain
Installation
Install the Truncus Node.js SDK:
npm install @truncus/node
Or with other package managers:
# Yarn
yarn add @truncus/node
# pnpm
pnpm add @truncus/node
Basic Setup
Initialize the client with your API key:
import { Truncus } from '@truncus/node';
const truncus = new Truncus({
apiKey: process.env.TRUNCUS_API_KEY,
});
Send Your First Email
Send a simple HTML email:
const { data, error } = await truncus.emails.send({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Welcome to our platform',
html: '<h1>Welcome!</h1><p>Thanks for signing up.</p>',
});
if (error) {
console.error('Failed to send:', error.message);
return;
}
console.log('Email sent:', data.id);
Send to Multiple Recipients
Send to multiple addresses:
await truncus.emails.send({
from: 'notifications@yourdomain.com',
to: ['user1@example.com', 'user2@example.com'],
subject: 'Team update',
html: '<p>Here is your weekly summary.</p>',
});
Add CC and BCC:
await truncus.emails.send({
from: 'billing@yourdomain.com',
to: 'customer@example.com',
cc: ['accounts@customer.com'],
bcc: ['records@yourdomain.com'],
subject: 'Invoice #1234',
html: invoiceHtml,
});
Using Reply-To
Set a different reply address:
await truncus.emails.send({
from: 'noreply@yourdomain.com',
replyTo: 'support@yourdomain.com',
to: 'user@example.com',
subject: 'Your support ticket',
html: ticketHtml,
});
Plain Text Fallback
Always include a plain text version for accessibility:
await truncus.emails.send({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Account verification',
html: '<p>Your code is: <strong>123456</strong></p>',
text: 'Your code is: 123456',
});
Sending with Attachments
Attach files to your email:
import { readFileSync } from 'fs';
await truncus.emails.send({
from: 'billing@yourdomain.com',
to: 'customer@example.com',
subject: 'Your invoice',
html: '<p>Please find your invoice attached.</p>',
attachments: [
{
filename: 'invoice.pdf',
content: readFileSync('./invoice.pdf'),
},
],
});
Custom Headers
Add custom email headers:
await truncus.emails.send({
from: 'system@yourdomain.com',
to: 'user@example.com',
subject: 'Password reset',
html: resetHtml,
headers: {
'X-Entity-Ref-ID': userId,
'X-Priority': '1',
},
});
Error Handling
Handle errors properly:
import { Truncus, TruncusError } from '@truncus/node';
const truncus = new Truncus({ apiKey: process.env.TRUNCUS_API_KEY });
try {
const { data, error } = await truncus.emails.send({
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Test',
html: '<p>Hello</p>',
});
if (error) {
// API returned an error
switch (error.code) {
case 'rate_limited':
// Wait and retry
await sleep(error.retryAfter * 1000);
break;
case 'invalid_recipient':
// Handle bad email address
break;
case 'domain_not_verified':
// Domain needs verification
break;
default:
console.error('Send failed:', error.message);
}
return;
}
console.log('Sent:', data.id);
} catch (err) {
// Network or unexpected error
console.error('Unexpected error:', err);
}
TypeScript Support
The SDK is fully typed. Import types as needed:
import { Truncus, SendEmailRequest, SendEmailResponse, TruncusError } from '@truncus/node';
const emailRequest: SendEmailRequest = {
from: 'hello@yourdomain.com',
to: 'user@example.com',
subject: 'Typed email',
html: '<p>This is type-safe</p>',
};
const { data, error } = await truncus.emails.send(emailRequest);
Environment Configuration
Recommended environment setup:
# .env
TRUNCUS_API_KEY=tr_live_xxxx
# For development
TRUNCUS_API_KEY=tr_test_xxxx
Load with dotenv or your framework's env handling:
import 'dotenv/config';
import { Truncus } from '@truncus/node';
const truncus = new Truncus({
apiKey: process.env.TRUNCUS_API_KEY!,
});
Framework Examples
Express.js
import express from 'express';
import { Truncus } from '@truncus/node';
const app = express();
const truncus = new Truncus({ apiKey: process.env.TRUNCUS_API_KEY! });
app.post('/send-welcome', async (req, res) => {
const { email, name } = req.body;
const { data, error } = await truncus.emails.send({
from: 'welcome@yourdomain.com',
to: email,
subject: `Welcome, ${name}!`,
html: `<h1>Hello ${name}</h1>`,
});
if (error) {
return res.status(400).json({ error: error.message });
}
res.json({ messageId: data.id });
});
Next.js API Route
// app/api/contact/route.ts
import { NextResponse } from 'next/server';
import { Truncus } from '@truncus/node';
const truncus = new Truncus({ apiKey: process.env.TRUNCUS_API_KEY! });
export async function POST(request: Request) {
const { email, message } = await request.json();
const { error } = await truncus.emails.send({
from: 'contact@yourdomain.com',
to: 'team@yourdomain.com',
replyTo: email,
subject: 'New contact form submission',
text: message,
});
if (error) {
return NextResponse.json({ error: error.message }, { status: 400 });
}
return NextResponse.json({ success: true });
}
Next Steps
- Get your API key
- Set up GDPR-compliant email handling
- Configure webhooks for delivery tracking