Provider Failover

Automatically fail over to backup providers when the primary provider fails. Supports retries, delays, and monitoring callbacks.

Global Failover Configuration

Mail.configure({
  default: 'smtp',
  from: { address: 'noreply@example.com', name: 'My App' },
  mailers: {
    smtp: {
      driver: 'smtp',
      host: process.env.SMTP_HOST!,
      port: 587,
      auth: { user: process.env.SMTP_USER!, pass: process.env.SMTP_PASS! },
    },
    sendgrid: {
      driver: 'sendgrid',
      apiKey: process.env.SENDGRID_API_KEY!,
    },
    ses: {
      driver: 'ses',
      region: 'us-east-1',
    },
  },
  failover: {
    chain: ['sendgrid', 'ses'],
    maxRetriesPerProvider: 2,
    retryDelay: 1000,
    failoverDelay: 500,
  },
});

Flow: SMTP (2 retries) -> SendGrid (2 retries) -> SES (2 retries) -> Error

Per-Mailer Failover Overrides

Override the global failover config for a specific mailer:

Mail.configure({
  default: 'smtp',
  mailers: {
    smtp: {
      driver: 'smtp',
      host: process.env.SMTP_HOST!,
      port: 587,
      auth: { user: process.env.SMTP_USER!, pass: process.env.SMTP_PASS! },
      failover: {
        chain: ['postmark'],       // Only fail over to Postmark for SMTP
        maxRetriesPerProvider: 3,
      },
    },
    postmark: {
      driver: 'postmark',
      serverToken: process.env.POSTMARK_SERVER_TOKEN!,
    },
  },
  failover: {
    chain: ['sendgrid', 'ses'],  // Global fallback (used by other mailers)
  },
});

onFailover Callback

Monitor failover events for logging or alerting:

Mail.configure({
  // ...
  failover: {
    chain: ['sendgrid', 'ses'],
    onFailover: (event) => {
      console.log(`Failover: ${event.failedMailer}${event.nextMailer}`);
      console.log(`Error: ${event.error}`);
      console.log(`Attempt: ${event.attemptIndex}, Time: ${event.timestamp}`);
      // Send to your monitoring/alerting system
    },
  },
});

FailoverEvent

interface FailoverEvent {
  failedMailer: string;     // Name of the mailer that failed
  error: string;            // Error message from the failed attempt
  nextMailer: string;       // Name of the next mailer to try
  attemptIndex: number;     // Total number of attempts so far
  timestamp: string;        // ISO 8601 timestamp
}

Response Metadata

After sending with failover configured, the MailResponse includes failover details:

const result = await Mail.to('user@example.com')
  .subject('Hello!')
  .html('<h1>Hello!</h1>')
  .send();

console.log(result.success);           // true
console.log(result.provider);          // 'sendgrid' (which provider actually sent)
console.log(result.failoverUsed);      // true (failover was triggered)
console.log(result.failoverAttempts);  // Array of FailoverDetail objects

FailoverDetail

interface FailoverDetail {
  mailer: string;           // Name of the mailer
  success: boolean;         // Whether this attempt succeeded
  error?: string;           // Error message (if failed)
  durationMs: number;       // Duration of the attempt in milliseconds
}

FailoverManager Direct API

For advanced usage:

import { FailoverManager } from '@impruthvi/nodemail';

const failoverManager = new FailoverManager();

const result = await failoverManager.sendWithFailover(
  mailOptions,           // MailOptions
  'smtp',                // Primary provider name
  smtpProvider,          // Primary MailProvider instance
  failoverConfig,        // FailoverConfig
  (name) => getProvider(name), // Provider resolver function
);

Failover Config Reference

PropertyTypeDefaultDescription
chainstring[](required)Ordered list of backup mailer names
maxRetriesPerProvidernumber1Retries per provider before moving to next
retryDelaynumber0Delay (ms) between retries on the same provider
failoverDelaynumber0Delay (ms) before switching to the next provider
onFailover(event: FailoverEvent) => void--Callback fired on each failover transition