waitlist-mailer
Version:
WaitlistMailer is a powerful TypeScript library for managing waitlists and sending confirmation emails. It supports local, MongoDB, and SQL storage, customizable email templates, bulk email sending, automatic retries, and advanced queries. Perfect for Nod
314 lines (255 loc) • 11.5 kB
Markdown
# WaitlistMailer
[](https://www.npmjs.com/package/waitlist-mailer)
[](https://opensource.org/licenses/MIT)
[](https://www.npmjs.com/package/waitlist-mailer)
[](https://nodejs.org)
[](https://www.mongodb.com)
[](https://www.postgresql.org)
[](https://www.npmjs.com/package/waitlist-mailer)
**WaitlistMailer** is a TypeScript-based NPM package for managing waitlists and sending confirmation emails. It supports **local**, **MongoDB**, and **SQL (PostgreSQL/MySQL/SQLite)** storage, with **customizable HTML templates**, an **event-driven architecture**, and advanced features like **bulk sending**, **automatic retries**, **validator.js validation**, and **query capabilities**.
---
## What's New in Version 1.1.0
- **Improved Error Handling**: Detailed event emissions for better debugging and error tracking.
- **Support for Multiple SMTP Providers**: Now works with any SMTP provider, not just Gmail.
- **Handlebars Integration**: Dynamic and reusable email templates using Handlebars.
- **Comprehensive Test Suite**: Full test coverage for all core functionalities.
- **Persistent Storage**: Data remains in the database unless explicitly cleared.
---
## Table of Contents
- [Description](#description)
- [Key Features](#key-features)
- [Installation](#installation)
- [Usage](#usage)
- [Initial Setup](#initial-setup)
- [Adding Emails to the Waitlist](#adding-emails-to-the-waitlist)
- [Removing Emails](#removing-emails)
- [Viewing the Waitlist](#viewing-the-waitlist)
- [Clearing the Waitlist](#clearing-the-waitlist)
- [Sending Confirmation Emails](#sending-confirmation-emails)
- [Bulk Email Sending](#bulk-email-sending)
- [Saving the Waitlist](#saving-the-waitlist)
- [Advanced Queries](#advanced-queries)
- [Event Handling](#event-handling)
- [Closing Resources](#closing-resources)
- [API](#api)
- [Common Errors](#common-errors)
- [Contributions](#contributions)
- [License](#license)
- [Version History](#version-history)
---
## Description
**WaitlistMailer** simplifies waitlist management in **Node.js** with robust email validation, flexible storage options, and efficient email delivery via **Nodemailer**. It's designed for scalability and ease of use, supporting both in-memory and persistent storage with MongoDB or SQL databases.
---
## Key Features
- **Email Validation**: Strict validation using `validator.js`.
- **Storage Options**: Local (in-memory), MongoDB (`Waitlist` collection), or SQL (`waitlist` table: PostgreSQL/MySQL/SQLite).
- **Dynamic Templates**: HTML emails with Handlebars for inline or file-based templates.
- **Nodemailer Integration**: Reliable SMTP delivery with support for multiple providers.
- **Event-Driven**: Emits events like `onEmailSent`, `onBulkConfirmationComplete`, and `onWaitlistSaved`.
- **Retries**: Automatic retry for failed email sends.
- **Bulk Sending**: Mass emailing with retry support.
- **Database Indexing**: Indexed `email` and `createdAt` fields for optimized queries.
- **Advanced Queries**: Pattern-based search and date range counting.
> ⚠️ **Note**: Requires Node.js >= 14. Install via `npm install waitlist-mailer`.
---
## Installation
```bash
npm install waitlist-mailer@1.1.0 nodemailer validator events mongoose sequelize pg mysql2 sqlite3 handlebars
```
### Dependencies
- **validator**: Email validation.
- **mongoose**: MongoDB support (optional).
- **sequelize, pg, mysql2, sqlite3**: SQL support (optional).
- **handlebars**: Dynamic template rendering.
### Environment Variables
Create `.env.local`:
```ini
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=your-email@example.com
SMTP_PASS=your-app-password
MONGO_URI=mongodb://localhost:27017/waitlistdb
SQL_DIALECT=mysql
SQL_HOST=localhost
SQL_PORT=3306
SQL_USER=root
SQL_PASSWORD=
SQL_DATABASE=waitlistdb
```
---
## Usage
### Initial Setup
```typescript
import WaitlistMailer, { StorageType } from 'waitlist-mailer';
const mailConfig = {
host: process.env.SMTP_HOST!,
port: parseInt(process.env.SMTP_PORT!),
user: process.env.SMTP_USER!,
pass: process.env.SMTP_PASS!,
};
// SQL Example (MySQL)
const mailer = new WaitlistMailer(StorageType.Sql, mailConfig, {
companyName: 'My Company',
sqlConfig: {
dialect: 'mysql',
host: process.env.SQL_HOST!,
port: parseInt(process.env.SQL_PORT!),
username: process.env.SQL_USER!,
password: process.env.SQL_PASSWORD!,
database: process.env.SQL_DATABASE!,
},
});
await mailer.waitForInitialization();
```
### Adding Emails to the Waitlist
```typescript
const success = await mailer.addEmail('user@example.com');
console.log(success ? 'Email added' : 'Failed (invalid or duplicate)');
```
### Removing Emails
```typescript
const removed = await mailer.removeEmail('user@example.com');
console.log(removed ? 'Email removed' : 'Email not found');
```
### Viewing the Waitlist
```typescript
const emails = mailer.getWaitlist();
console.log('Current waitlist:', emails);
```
### Clearing the Waitlist
```typescript
await mailer.clearWaitlist();
console.log('Waitlist cleared');
```
### Sending Confirmation Emails
#### Using Handlebars Templates
Create `templates/confirmation.hbs`:
```html
<h1>Welcome, {{email}}!</h1>
<p>Thanks for joining {{companyName}}. {{customMessage}}</p>
```
```typescript
const sent = await mailer.sendConfirmationFromFile(
'user@example.com',
(email) => `Welcome, ${email}!`,
'./templates/confirmation.hbs',
{ customMessage: 'We\'re excited to have you!' }
);
console.log(sent ? 'Email sent' : 'Failed to send');
```
### Bulk Email Sending
```typescript
const subjectFn = (email) => `Hello, ${email}!`;
const bodyFn = (email) => `<h1>Welcome</h1><p>Join us, ${email}!</p>`;
const successCount = await mailer.sendBulkConfirmation(subjectFn, bodyFn, 3, 1000);
console.log(`Sent to ${successCount} users`);
```
⚠️ **Warning**: Check SMTP rate limits (e.g., Gmail: 500/day).
### Saving the Waitlist
```typescript
const saved = await mailer.saveWaitlist();
console.log(saved ? 'Waitlist saved' : 'Failed to save');
```
### Advanced Queries
#### Find Emails by Pattern
```typescript
const matches = await mailer.findEmailsByPattern('example');
console.log('Matching emails:', matches); // e.g., ['user@example.com']
```
#### Count by Date Range
```typescript
const count = await mailer.countWaitlistByDate(
new Date('2023-01-01'),
new Date('2023-12-31')
);
console.log(`Emails in 2023: ${count}`);
```
### Event Handling
```typescript
mailer.on('onEmailAdded', (email) => console.log(`Added: ${email}`));
mailer.on('onEmailRemoved', (email) => console.log(`Removed: ${email}`));
mailer.on('onEmailSent', (email, info) => console.log(`Sent to ${email}: ${info.messageId}`));
mailer.on('onEmailRetry', (email, attempt) => console.log(`Retrying ${email}, attempt ${attempt}`));
mailer.on('onBulkConfirmationComplete', ({ successCount, total }) => console.log(`Bulk: ${successCount}/${total}`));
mailer.on('onWaitlistSaved', (emails) => console.log('Saved:', emails));
mailer.on('onWaitlistCleared', () => console.log('Waitlist cleared'));
mailer.on('onValidationError', ({ message }) => console.error(`Validation error: ${message}`));
mailer.on('onDuplicateEmail', (email) => console.log(`Duplicate email: ${email}`));
mailer.on('onError', ({ context, message, error }) => console.error(`Error in ${context}: ${message}`, error));
mailer.on('onTransporterReady', () => console.log('Transporter ready'));
mailer.on('onTransporterError', (error) => console.error('Transporter error:', error));
mailer.on('onDbConnected', () => console.log('MongoDB connected'));
mailer.on('onDbError', (error) => console.error('MongoDB error:', error));
mailer.on('onSqlConnected', () => console.log('SQL connected'));
mailer.on('onSqlError', (error) => console.error('SQL error:', error));
mailer.on('onInitialized', () => console.log('WaitlistMailer initialized'));
```
### Closing Resources
```typescript
await mailer.close();
console.log('Resources closed');
```
---
## API
### Constructor
```typescript
new WaitlistMailer(storage: StorageType, mailConfig: MailConfig, options?: WaitlistMailerOptions)
```
- **storage**: Storage type (`Local`, `Db`, or `Sql`).
- **mailConfig**: { host: string, port: number, user: string, pass: string }.
- **options**: { companyName?: string, mongoUri?: string, sqlConfig?: SQL config object }.
### Methods
| Method | Description | Returns |
|--------|-------------|---------|
| `addEmail(email)` | Adds validated email | `Promise<boolean>` |
| `removeEmail(email)` | Removes email | `Promise<boolean>` |
| `getWaitlist()` | Returns all emails | `string[]` |
| `clearWaitlist()` | Clears waitlist | `Promise<void>` |
| `sendConfirmation(...)` | Sends email | `Promise<boolean>` |
| `sendBulkConfirmation(...)` | Bulk emails | `Promise<number>` |
| `saveWaitlist()` | Persists waitlist to storage | `Promise<boolean>` |
| `findEmailsByPattern(pattern)` | Finds emails matching a pattern | `Promise<string[]>` |
| `countWaitlistByDate(start, end)` | Counts emails by date range | `Promise<number>` |
| `close()` | Closes database connections | `Promise<void>` |
### Events
- `onEmailAdded(email: string)`
- `onEmailRemoved(email: string)`
- `onEmailSent(email: string, info: SentMessageInfo)`
- `onEmailRetry(email: string, attempt: number)`
- `onBulkConfirmationComplete({ successCount: number, total: number })`
- `onWaitlistSaved(emails: string[])`
- `onWaitlistCleared()`
- `onValidationError({ message: string })`
- `onDuplicateEmail(email: string)`
- `onError({ context: string, message: string, error: unknown })`
- `onTransporterReady()`
- `onTransporterError(error: Error)`
- `onDbConnected()`
- `onDbError(error: Error)`
- `onSqlConnected()`
- `onSqlError(error: Error)`
- `onInitialized()`
---
## Common Errors
- **SMTP Connection Refused**: Invalid mailConfig.
Fix: Verify host, port, user, and pass.
- **Invalid Email**: Format error.
Fix: Use valid email format.
- **Duplicate Email**: Already in waitlist.
Fix: Check existing emails.
---
## Contributions
- Fork the repo.
- Submit pull requests.
- Report issues.
---
## License
MIT - Free to use, modify, and distribute with attribution.
---
## Version History
| Version | Date | Description |
|---------|------|-------------|
| 1.1.0 | March 5, 2025 | - Improved error handling<br>- Support for multiple SMTP providers<br>- Handlebars for templates<br>- Comprehensive tests |
| 1.0.0 | March 3, 2025 | - Bulk sending<br>- Database indexing |
| 0.1.0 | TBD | Initial release |
---