npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bernierllc/email-sender-manager

v1.2.0

Published

Database-backed email sender configuration management with provider verification integration

Readme

@bernierllc/email-sender-manager

Database-backed email sender configuration management with provider verification integration. Manage, verify, and intelligently select email sender configurations for your applications.

Installation

npm install @bernierllc/email-sender-manager

Features

  • Database-Backed Storage: Persistent sender configurations with transaction support
  • Provider Integration: Verify sender configurations with email providers (SendGrid, Mailgun, etc.)
  • Smart Sender Selection: Intelligent sender selection based on domain matching, priority, or round-robin strategies
  • Bootstrap System: Automatic database schema creation and default sender seeding
  • Full TypeScript Support: Complete type definitions with strict mode compliance
  • Comprehensive Validation: Email format validation, domain restrictions, and configuration checks

Quick Start

import { EmailSenderManager } from '@bernierllc/email-sender-manager';
import type { DatabaseAdapter } from '@bernierllc/email-sender-manager';

// Implement your database adapter
const databaseAdapter: DatabaseAdapter = {
  async execute(query: string, params?: unknown[]): Promise<void> {
    // Your database execute logic
  },
  async query<T = unknown>(query: string, params?: unknown[]): Promise<T[]> {
    // Your database query logic
  },
  async queryOne<T = unknown>(query: string, params?: unknown[]): Promise<T | null> {
    // Your database queryOne logic
  },
  async transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T> {
    // Your transaction logic
  },
};

// Initialize manager
const manager = new EmailSenderManager({
  database: databaseAdapter,
  bootstrap: {
    enabled: true,
    createTables: true,
    seedDefaultSenders: true,
    defaultSenders: [
      {
        name: 'Default Sender',
        fromEmail: '[email protected]',
        fromName: 'My App',
        provider: 'sendgrid',
        priority: 1,
      },
    ],
    environment: 'production',
  },
  selection: {
    strategy: 'domain_match',
    fallbackToDefault: true,
    domainMatchingRules: [],
  },
});

// Bootstrap database
await manager.bootstrapDatabase();

Core Concepts

Sender Configuration

A sender configuration represents an email address that can send emails through your application:

interface SenderConfiguration {
  id: string;
  name: string;
  description?: string;
  fromEmail: string;
  fromName: string;
  replyToEmail?: string;
  replyToName?: string;
  provider: string;
  providerSenderId?: string;
  providerMetadata?: Record<string, unknown>;
  isVerified: boolean;
  verificationStatus: 'pending' | 'verified' | 'failed' | 'expired';
  lastVerifiedAt?: Date;
  isDefault: boolean;
  isActive: boolean;
  priority: number; // Lower = higher priority
  allowedDomains?: string[];
  domain: string;
  createdAt: Date;
  updatedAt: Date;
  createdBy: string;
  lastModifiedBy: string;
}

Provider Integration

Providers verify sender configurations with email service providers:

interface SenderProviderPlugin {
  readonly providerId: string;
  readonly name: string;
  validateSender(email: string): Promise<ProviderValidationResult>;
  getVerifiedSenders(): Promise<ProviderSender[]>;
  syncSender(sender: SenderConfiguration): Promise<SyncResult>;
  getCapabilities(): string[];
}

Usage Examples

Creating Senders

// Create a new sender
const sender = await manager.createSender({
  name: 'Marketing Team',
  fromEmail: '[email protected]',
  fromName: 'Marketing Department',
  replyToEmail: '[email protected]',
  provider: 'sendgrid',
  priority: 10,
  allowedDomains: ['example.com', '*.example.com'],
  createdBy: 'admin-user',
});

console.log(`Created sender: ${sender.id}`);

Updating Senders

// Update sender configuration
const updated = await manager.updateSender(sender.id, {
  name: 'Updated Name',
  priority: 5,
  isActive: true,
  lastModifiedBy: 'admin-user',
});

Listing Senders

// List all active senders
const activeSenders = await manager.listSenders({
  isActive: true,
  orderBy: 'priority',
  orderDirection: 'asc',
});

// List verified senders for a specific provider
const verifiedSenders = await manager.listSenders({
  provider: 'sendgrid',
  isVerified: true,
  limit: 10,
  offset: 0,
});

// Paginate through results
console.log(`Total: ${activeSenders.total}, Showing: ${activeSenders.items.length}`);
console.log(`Has more: ${activeSenders.hasMore}`);

Sender Selection

// Select best sender for an email
const bestSender = await manager.selectBestSender('[email protected]', {
  strategy: 'domain_match', // or 'priority' or 'round_robin'
  allowUnverified: false,
});

if (bestSender) {
  console.log(`Using sender: ${bestSender.fromEmail} (priority: ${bestSender.priority})`);
}

// Select sender for specific provider
const sendgridSender = await manager.selectBestSender('[email protected]', {
  provider: 'sendgrid',
  strategy: 'priority',
});

Provider Verification

import type { SenderProviderPlugin } from '@bernierllc/email-sender-manager';

// Implement a provider plugin
class SendGridProvider implements SenderProviderPlugin {
  readonly providerId = 'sendgrid';
  readonly name = 'SendGrid';

  constructor(private apiKey: string) {}

  async validateSender(email: string): Promise<ProviderValidationResult> {
    // Call SendGrid API to verify sender
    const verifiedSenders = await this.getVerifiedSenders();
    const match = verifiedSenders.find((s) => s.email === email);

    return {
      isVerified: Boolean(match?.isVerified),
      verificationStatus: match?.verificationStatus || 'not_found',
      lastChecked: new Date(),
      metadata: { providerId: match?.id },
    };
  }

  async getVerifiedSenders(): Promise<ProviderSender[]> {
    // Fetch from SendGrid API
    return [];
  }

  async syncSender(sender: SenderConfiguration): Promise<SyncResult> {
    // Sync with SendGrid
    return { success: true, senderId: sender.id, synced: true };
  }

  getCapabilities(): string[] {
    return ['verification', 'sync'];
  }
}

// Register provider
const provider = new SendGridProvider(process.env.SENDGRID_API_KEY!);
await manager.registerProvider(provider);

// Verify a sender
const verification = await manager.verifySender(sender.id);
console.log(`Verified: ${verification.isVerified}`);

Bootstrap Configuration

const manager = new EmailSenderManager({
  database: databaseAdapter,
  bootstrap: {
    enabled: true,
    createTables: true,
    seedDefaultSenders: true,
    defaultSenders: [
      {
        name: 'Default Sender',
        fromEmail: '[email protected]',
        fromName: 'My Application',
        provider: 'sendgrid',
        priority: 1,
      },
      {
        name: 'Marketing Sender',
        fromEmail: '[email protected]',
        fromName: 'Marketing Team',
        provider: 'sendgrid',
        priority: 10,
        allowedDomains: ['example.com'],
      },
    ],
    environment: 'production',
  },
});

// Run bootstrap
const result = await manager.bootstrapDatabase();
console.log(result.message);
// Output: "Bootstrap completed successfully. Tables created: true, Senders seeded: 2"

Selection Strategies

Domain Matching

Selects senders based on domain relationships:

  1. Exact domain match: example.com sender for [email protected]
  2. Subdomain match: example.com sender for [email protected]
  3. Allowed domains: Senders with allowedDomains configuration
  4. Fallback to priority: If no domain match found
const sender = await manager.selectBestSender('[email protected]', {
  strategy: 'domain_match',
});

Priority-Based

Selects sender with lowest priority number (higher priority):

const sender = await manager.selectBestSender('[email protected]', {
  strategy: 'priority',
});

Round-Robin

Distributes selections evenly across available senders:

const sender = await manager.selectBestSender('[email protected]', {
  strategy: 'round_robin',
});

Domain Utilities

import {
  extractDomain,
  isDomainMatch,
  isValidEmail,
  getParentDomain,
  isSubdomainOf,
} from '@bernierllc/email-sender-manager';

// Extract domain from email
const domain = extractDomain('[email protected]'); // "example.com"

// Check domain matching with wildcards
const matches = isDomainMatch('app.example.com', '*.example.com'); // true

// Validate email format
const valid = isValidEmail('[email protected]'); // true

// Get parent domain
const parent = getParentDomain('app.example.com'); // "example.com"

// Check subdomain relationship
const isSub = isSubdomainOf('app.example.com', 'example.com'); // true

Validation

import { validateCreateSenderRequest } from '@bernierllc/email-sender-manager';

// Validate sender creation request
const validation = validateCreateSenderRequest({
  name: 'Test Sender',
  fromEmail: '[email protected]',
  fromName: 'Test',
  provider: 'sendgrid',
  createdBy: 'admin',
});

if (validation.errors.length > 0) {
  console.error('Validation errors:', validation.errors);
}

if (validation.warnings.length > 0) {
  console.warn('Validation warnings:', validation.warnings);
}

Database Schema

The package automatically creates the following database schema:

CREATE TABLE IF NOT EXISTS email_senders (
  id VARCHAR(255) PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  description TEXT,
  from_email VARCHAR(255) NOT NULL UNIQUE,
  from_name VARCHAR(255) NOT NULL,
  reply_to_email VARCHAR(255),
  reply_to_name VARCHAR(255),
  provider VARCHAR(100) NOT NULL,
  provider_sender_id VARCHAR(255),
  provider_metadata JSON,
  is_verified BOOLEAN DEFAULT FALSE,
  verification_status VARCHAR(50) DEFAULT 'pending',
  last_verified_at TIMESTAMP NULL,
  verification_error TEXT,
  is_default BOOLEAN DEFAULT FALSE,
  is_active BOOLEAN DEFAULT TRUE,
  priority INTEGER DEFAULT 100,
  allowed_domains JSON,
  domain VARCHAR(255) NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  created_by VARCHAR(255),
  last_modified_by VARCHAR(255),
  INDEX idx_email_senders_from_email (from_email),
  INDEX idx_email_senders_domain (domain),
  INDEX idx_email_senders_provider (provider),
  INDEX idx_email_senders_active (is_active),
  INDEX idx_email_senders_default (is_default),
  INDEX idx_email_senders_priority (priority)
);

API Reference

EmailSenderManager

Main class for managing sender configurations.

Constructor

constructor(config: SenderManagerConfig)

Methods

  • bootstrapDatabase(): Promise<BootstrapResult> - Initialize database and seed default senders
  • createSender(request: CreateSenderRequest): Promise<SenderConfiguration> - Create new sender
  • updateSender(id: string, updates: UpdateSenderRequest): Promise<SenderConfiguration> - Update existing sender
  • deleteSender(id: string): Promise<void> - Delete sender
  • getSender(id: string): Promise<SenderConfiguration | null> - Get sender by ID
  • listSenders(options?: ListSendersOptions): Promise<PaginatedResult<SenderConfiguration>> - List senders with filters
  • validateSender(id: string): Promise<SenderValidationResult> - Validate sender configuration
  • verifySender(id: string, provider?: string): Promise<VerificationResult> - Verify sender with provider
  • selectBestSender(fromEmail: string, options?: SelectionOptions): Promise<SenderConfiguration | null> - Select optimal sender
  • getDefaultSender(provider?: string): Promise<SenderConfiguration | null> - Get default sender
  • getSendersByDomain(domain: string): Promise<SenderConfiguration[]> - Get senders for domain
  • registerProvider(provider: SenderProviderPlugin): Promise<void> - Register provider plugin
  • syncWithProviders(): Promise<SyncResult[]> - Sync all senders with providers
  • cleanupInactiveSenders(): Promise<CleanupResult> - Remove inactive senders

Integration Status

  • Logger: Not applicable - Core utility package with database-backed state (logging handled at service layer)
  • Docs-Suite: Ready - Comprehensive API documentation with TypeDoc comments exported
  • NeverHub: Not applicable - Core utility package focused on email sender configuration management. NeverHub integration is appropriate at the service layer where sender selection events and metrics would be published to the event bus. This package provides the foundational primitives for sender management without environment-dependent behavior.

Testing

The package includes comprehensive tests with 90%+ coverage:

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests once
npm run test:run

License

Copyright (c) 2025 Bernier LLC

This file is licensed to the client under a limited-use license. The client may use and modify this code only within the scope of the project it was delivered for. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.

See Also