🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@truncus/email

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@truncus/email

Node.js SDK for Truncus Email API

latest
Source
npmnpm
Version
0.2.0
Version published
Maintainers
1
Created
Source

@truncus/email

Node.js SDK for Truncus — transactional email infrastructure built on AWS SES with deliverability built-in.

Installation

npm install @truncus/email
# or
pnpm add @truncus/email
# or
yarn add @truncus/email

Quick Start

import { Truncus } from '@truncus/email';

const truncus = new Truncus({ apiKey: 'tr_live_...' });

const result = await truncus.sendEmail({
  to: 'user@example.com',
  from: 'hello@mail.yourdomain.com',
  subject: 'Welcome!',
  html: '<h1>Hello World</h1>',
});

console.log(result.id);     // Email ID
console.log(result.status); // 'sent'

Configuration

const truncus = new Truncus({
  apiKey: 'tr_live_...', // Required
  baseUrl: 'https://truncus.co', // Optional, defaults to production
  timeout: 30000,        // Optional, request timeout in ms (default 30s)
});

API Reference

Emails

sendEmail(options)

Send a transactional email.

const result = await truncus.sendEmail({
  // Required
  to: 'user@example.com',
  from: 'hello@mail.yourdomain.com', // Must match a verified domain
  subject: 'Welcome!',
  html: '<h1>Hello World</h1>',

  // Optional
  text: 'Hello World',              // Plain-text fallback
  cc: ['cc@example.com'],
  bcc: ['bcc@example.com'],
  templateId: 'tmpl_...',           // Use a saved template instead of html
  variables: { name: 'John' },      // Template variables ({{name}})
  metadata: { userId: '123' },      // Custom metadata (stored, not sent)
  idempotencyKey: 'order-123',      // Prevent duplicate sends (auto-generated if omitted)
  tenantId: 'tenant_abc',           // Multi-tenant suppression isolation
  sendAt: '2026-03-10T09:00:00Z',  // Schedule for future delivery (ISO 8601, must be future)
  sandbox: true,                    // Skip SES — test without sending
  trackOpens: true,                 // 1×1 tracking pixel (default: true)
  trackClicks: true,                // Rewrite links through click proxy (default: true)
  attachments: [
    {
      filename: 'invoice.pdf',
      content: '<base64-encoded-content>',
      content_type: 'application/pdf',
    },
  ],
});

// result.status === 'sent'          — sent immediately
// result.status === 'scheduled'     — queued for sendAt time
// result.sendAt                     — ISO 8601 delivery time (scheduled emails)
// result.sandbox                    — true if sandbox mode was active

getEmail(emailId)

Retrieve details for a specific email, including open and click tracking stats.

const email = await truncus.getEmail('email_id');

console.log(email.status);    // 'delivered'
console.log(email.openCount); // 3 (total opens, including repeat opens)
console.log(email.openedAt);  // '2026-03-04T10:23:00Z' (first open)
console.log(email.clickCount);// 1

cancelEmail(emailId)

Cancel a scheduled email before it is dispatched. Only works on emails with status === 'scheduled'.

const result = await truncus.cancelEmail('email_id');
console.log(result.status); // 'cancelled'

Events

listEvents(options?)

List email events. Includes 'opened' and 'clicked' event types.

// All recent events
const { events } = await truncus.listEvents();

// Events for a specific email
const { events } = await truncus.listEvents({ emailId: 'email_id' });

// Filter by type
const { events } = await truncus.listEvents({ type: 'opened', limit: 50 });
const { events } = await truncus.listEvents({ type: 'clicked', limit: 50 });
const { events } = await truncus.listEvents({ type: 'delivered' });

Event types: queued | sent | delivered | bounce | complaint | failed | retry_scheduled | retry_attempted | opened | clicked

Domains

createDomain(options)

Add a sending domain. Returns DNS records to configure.

const domain = await truncus.createDomain({ domain: 'mail.yourdomain.com' });

// Configure these DNS records at your registrar:
console.log(domain.dnsRecords);
// [
//   { type: 'TXT', name: '_truncus.mail.yourdomain.com', value: 'truncus-verification=...' },
//   { type: 'TXT', name: 'mail.yourdomain.com', value: 'v=spf1 include:amazonses.com ~all' },
//   { type: 'CNAME', name: '...._domainkey.mail.yourdomain.com', value: '....dkim.amazonses.com' },
//   { type: 'TXT', name: '_dmarc.mail.yourdomain.com', value: 'v=DMARC1; p=quarantine; ...' },
// ]

verifyDomain(domainId)

Trigger DNS verification after configuring records.

const result = await truncus.verifyDomain('domain_id');
console.log(result.verified); // true when DNS is correct

listDomains()

List all domains with sending stats.

const { domains } = await truncus.listDomains();
domains.forEach((d) => {
  console.log(d.domain, d.status, d.sentToday);
});

Suppression

checkSuppression(email, tenantId?)

Check whether an address is on the suppression list before sending.

const status = await truncus.checkSuppression('user@example.com');
console.log(status.suppressed); // true / false
console.log(status.reason);     // 'bounce' | 'complaint' | null

For multi-tenant apps, scope the check to a specific tenant:

const status = await truncus.checkSuppression('user@example.com', 'tenant_abc');

Stats

getStats()

Aggregate sending stats for the account.

const stats = await truncus.getStats();
console.log(stats.sentToday);
console.log(stats.deliveryRate); // 0.98 (98%)
console.log(stats.bounceRate);   // 0.01 (1%)

Sandbox Mode

Test your integration without sending real emails:

const result = await truncus.sendEmail({
  to: 'user@example.com',
  from: 'any@address.com', // Domain validation skipped in sandbox
  subject: 'Test',
  html: '<p>Test</p>',
  sandbox: true,
});

console.log(result.sandbox); // true
console.log(result.status);  // 'sent' (simulated)

Sandbox skips SES entirely. No emails are delivered. Open/click tracking is also disabled.

Scheduled Sending

Schedule an email for future delivery. The email is queued immediately and dispatched at sendAt:

const result = await truncus.sendEmail({
  to: 'user@example.com',
  from: 'hello@mail.yourdomain.com',
  subject: 'Your weekly digest',
  html: '...',
  sendAt: '2026-03-10T09:00:00Z', // Must be a future datetime
});

console.log(result.status); // 'scheduled'
console.log(result.sendAt); // '2026-03-10T09:00:00.000Z'

// Cancel before dispatch
await truncus.cancelEmail(result.id);

Open & Click Tracking

Tracking is enabled by default. Truncus injects a 1×1 pixel for opens and rewrites links for click tracking. Unsubscribe links are never rewritten.

// Default — both opens and clicks tracked
const result = await truncus.sendEmail({ ..., html: '...' });

// Disable tracking
const result = await truncus.sendEmail({
  ...,
  html: '...',
  trackOpens: false,
  trackClicks: false,
});

// Check engagement after sending
const email = await truncus.getEmail(result.id);
console.log(email.openedAt);   // First open timestamp
console.log(email.openCount);  // Total opens (repeat opens counted)
console.log(email.clickCount); // Total link clicks

Events also fire for opens and clicks — query them with listEvents({ type: 'opened' }) or listEvents({ type: 'clicked' }).

Idempotency

Prevent duplicate sends by providing a stable idempotency key. If you retry with the same key, the original response is returned without sending again:

const result = await truncus.sendEmail({
  to: 'user@example.com',
  from: 'hello@mail.yourdomain.com',
  subject: 'Order Confirmation',
  html: '...',
  idempotencyKey: `order-${orderId}-confirmation`,
});

An idempotency key is auto-generated (UUID v4) when not provided.

Multi-tenant Apps

Isolate suppression lists per tenant so a bounce in one customer's account doesn't affect others:

const result = await truncus.sendEmail({
  to: 'user@example.com',
  from: 'hello@mail.yourdomain.com',
  subject: 'Welcome!',
  html: '...',
  tenantId: 'tenant_123',
});

Error Handling

import { TruncusError } from '@truncus/email';

try {
  await truncus.sendEmail({ ... });
} catch (error) {
  if (error instanceof TruncusError) {
    console.log(error.code);    // 'DOMAIN_NOT_VERIFIED'
    console.log(error.message); // 'Domain is not verified'
    console.log(error.status);  // 400
  }
}

Error Codes

CodeStatusDescription
MISSING_API_KEY401Authorization header missing
INVALID_API_KEY401API key is invalid or revoked
SCOPE_REQUIRED403API key missing required scope
INVALID_REQUEST400Request body validation failed
DOMAIN_NOT_FOUND404Domain doesn't exist
DOMAIN_NOT_VERIFIED400Domain pending DNS verification
DOMAIN_PAUSED400Domain paused due to high bounce/complaint rate
WARMUP_CAP_EXCEEDED429Daily sending limit reached
ALL_RECIPIENTS_SUPPRESSED422All recipients are on suppression list
PROVIDER_ERROR502AWS SES returned an error
TIMEOUT408Request timed out
NETWORK_ERROR0Network connectivity issue

TypeScript

Full type definitions are included. Key types:

import type {
  SendEmailOptions,
  SendEmailResponse,
  EmailDetails,
  EmailStatus,
  EventType,
  EmailEvent,
  Domain,
  DomainStatus,
  SuppressionStatus,
  TruncusConfig,
} from '@truncus/email';

License

MIT

Keywords

email

FAQs

Package last updated on 08 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts