No description
Find a file
2025-08-18 22:22:04 +07:00
.claude initial commit 2025-08-18 22:22:04 +07:00
examples initial commit 2025-08-18 22:22:04 +07:00
tests initial commit 2025-08-18 22:22:04 +07:00
workflows initial commit 2025-08-18 22:22:04 +07:00
.eslintrc.js initial commit 2025-08-18 22:22:04 +07:00
.gitignore initial commit 2025-08-18 22:22:04 +07:00
.prettierrc initial commit 2025-08-18 22:22:04 +07:00
CLAUDE.md initial commit 2025-08-18 22:22:04 +07:00
jest.config.js initial commit 2025-08-18 22:22:04 +07:00
LICENSE initial commit 2025-08-18 22:22:04 +07:00
package-lock.json initial commit 2025-08-18 22:22:04 +07:00
package.json initial commit 2025-08-18 22:22:04 +07:00
README.md initial commit 2025-08-18 22:22:04 +07:00
tsconfig.cjs.json initial commit 2025-08-18 22:22:04 +07:00
tsconfig.esm.json initial commit 2025-08-18 22:22:04 +07:00
tsconfig.json initial commit 2025-08-18 22:22:04 +07:00
tsconfig.types.json initial commit 2025-08-18 22:22:04 +07:00

@siwatsystem/smtp-ws-relay-client

npm version TypeScript License: MIT

A production-ready TypeScript client library for SMTP over WebSocket protocol with intelligent queue management, automatic reconnection, and comprehensive error handling.

Features

🚀 Intelligent Queue Management

  • Automatic WebSocket connection when messages are queued
  • Priority-based message processing
  • Configurable batch processing
  • Queue size limits and overflow protection

🔄 Robust Connection Handling

  • Automatic reconnection with exponential backoff
  • Connection state management
  • Heartbeat monitoring
  • Graceful connection lifecycle

High Performance

  • Efficient SMTP channel cycling
  • Concurrent message processing support
  • Optimized resource usage
  • Minimal memory footprint

🛡️ Enterprise-Grade Reliability

  • Comprehensive error handling and classification
  • Timeout management for all operations
  • Retry logic with configurable attempts
  • Graceful degradation and recovery

📊 Monitoring & Observability

  • Real-time statistics and metrics
  • Structured logging with configurable levels
  • Event-driven architecture for monitoring
  • Performance tracking and analytics

Installation

npm install @siwatsystem/smtp-ws-relay-client

Quick Start

import { SMTPOverWSClient, MessagePriority } from '@siwatsystem/smtp-ws-relay-client';

// Create client instance
const client = new SMTPOverWSClient({
    url: 'ws://your-smtp-relay-server:3000/smtp',
    apiKey: 'your-api-key',
    debug: true
});

// Send SMTP commands
try {
    const response1 = await client.sendSMTPCommand('EHLO example.com\\r\\n');
    const response2 = await client.sendSMTPCommand('MAIL FROM: <test@example.com>\\r\\n');
    const response3 = await client.sendSMTPCommand('RCPT TO: <recipient@example.com>\\r\\n');
    
    console.log('SMTP responses:', [response1, response2, response3]);
} catch (error) {
    console.error('SMTP error:', error);
}

// Graceful shutdown
await client.shutdown();

Configuration Options

interface SMTPClientConfig {
    /** WebSocket server URL */
    url: string;
    
    /** API key for authentication */
    apiKey: string;
    
    /** Interval between reconnection attempts (default: 5000ms) */
    reconnectInterval?: number;
    
    /** Maximum reconnection attempts (default: 10) */
    maxReconnectAttempts?: number;
    
    /** Authentication timeout (default: 30000ms) */
    authTimeout?: number;
    
    /** Channel operation timeout (default: 10000ms) */
    channelTimeout?: number;
    
    /** Message timeout (default: 60000ms) */
    messageTimeout?: number;
    
    /** Maximum concurrent messages (default: 1) */
    maxConcurrentMessages?: number;
    
    /** Enable debug logging (default: false) */
    debug?: boolean;
    
    /** Custom logger implementation */
    logger?: Logger;
    
    /** Connection heartbeat interval (default: 30000ms) */
    heartbeatInterval?: number;
    
    /** Queue processing batch size (default: 10) */
    batchSize?: number;
    
    /** Maximum queue size (default: 1000) */
    maxQueueSize?: number;
}

Advanced Usage

Priority-Based Message Queuing

import { MessagePriority } from '@siwatsystem/smtp-ws-relay-client';

// High priority message (processed first)
await client.sendSMTPCommand('URGENT EMAIL DATA\\r\\n', {
    priority: MessagePriority.HIGH,
    timeout: 30000
});

// Normal priority message
await client.sendSMTPCommand('NORMAL EMAIL DATA\\r\\n', {
    priority: MessagePriority.NORMAL
});

// Low priority message (processed last)
await client.sendSMTPCommand('NEWSLETTER DATA\\r\\n', {
    priority: MessagePriority.LOW
});

Event Monitoring

// Connection events
client.on('connected', () => {
    console.log('WebSocket connected');
});

client.on('authenticated', () => {
    console.log('Authentication successful');
});

client.on('disconnected', (reason) => {
    console.log('Disconnected:', reason);
});

// Queue events
client.on('messageQueued', (messageId, queueSize) => {
    console.log(`Message ${messageId} queued. Queue size: ${queueSize}`);
});

client.on('messageProcessed', (messageId, responseTime) => {
    console.log(`Message ${messageId} processed in ${responseTime}ms`);
});

client.on('queueProcessingStarted', (queueSize) => {
    console.log(`Processing ${queueSize} queued messages`);
});

// Error events
client.on('error', (error) => {
    console.error('Client error:', error);
});

client.on('messageFailed', (messageId, error) => {
    console.error(`Message ${messageId} failed:`, error);
});

Statistics and Monitoring

// Get real-time statistics
const stats = client.getStats();
console.log('Client Statistics:', {
    messagesQueued: stats.messagesQueued,
    messagesProcessed: stats.messagesProcessed,
    messagesFailed: stats.messagesFailed,
    averageResponseTime: stats.averageResponseTime,
    connectionUptime: stats.connectionUptime,
    queueSize: stats.queueSize
});

// Monitor connection state
console.log('Current state:', client.getConnectionState());
console.log('Queue size:', client.getQueueSize());

Custom Logger

import { Logger } from '@siwatsystem/smtp-ws-relay-client';

class CustomLogger implements Logger {
    debug(message: string, ...args: any[]): void {
        // Send to your logging service
        console.debug(`[DEBUG] ${message}`, ...args);
    }
    
    info(message: string, ...args: any[]): void {
        console.info(`[INFO] ${message}`, ...args);
    }
    
    warn(message: string, ...args: any[]): void {
        console.warn(`[WARN] ${message}`, ...args);
    }
    
    error(message: string, ...args: any[]): void {
        console.error(`[ERROR] ${message}`, ...args);
    }
}

const client = new SMTPOverWSClient({
    url: 'ws://localhost:3000/smtp',
    apiKey: 'your-api-key',
    logger: new CustomLogger()
});

Error Handling

The library provides comprehensive error classification:

import { 
    ConnectionError, 
    AuthenticationError, 
    ChannelError, 
    TimeoutError,
    QueueError,
    MessageError 
} from '@siwatsystem/smtp-ws-relay-client';

try {
    await client.sendSMTPCommand('EHLO example.com\\r\\n');
} catch (error) {
    if (error instanceof ConnectionError) {
        console.error('Connection failed:', error.message);
    } else if (error instanceof AuthenticationError) {
        console.error('Authentication failed:', error.message);
    } else if (error instanceof TimeoutError) {
        console.error('Operation timed out:', error.message);
    } else if (error instanceof QueueError) {
        console.error('Queue error:', error.message);
    } else if (error instanceof MessageError) {
        console.error('Message processing failed:', error.message);
    }
}

Connection States

The client manages several connection states:

  • DISCONNECTED - No connection to server
  • CONNECTING - Establishing WebSocket connection
  • CONNECTED - WebSocket connected, authentication pending
  • AUTHENTICATING - Sending authentication credentials
  • AUTHENTICATED - Ready to open SMTP channels
  • CHANNEL_OPENING - Opening SMTP channel
  • CHANNEL_READY - SMTP channel active, ready for data
  • CHANNEL_CLOSED - SMTP channel closed
  • CHANNEL_ERROR - SMTP channel error occurred
  • RECONNECTING - Attempting to reconnect
  • FAILED - Connection failed, max retries reached

Protocol Support

This client implements the SMTP over WebSocket protocol specification:

Message Types

  • AUTHENTICATE / AUTHENTICATE_RESPONSE - Authentication flow
  • SMTP_CHANNEL_OPEN / SMTP_CHANNEL_READY - Channel management
  • SMTP_CHANNEL_CLOSED / SMTP_CHANNEL_ERROR - Channel lifecycle
  • SMTP_TO_SERVER / SMTP_FROM_SERVER - Data transfer

Connection Flow

  1. WebSocket Connection - Establish WebSocket to relay server
  2. Authentication - Authenticate using API key
  3. Channel Management - Open/close SMTP channels per message
  4. Data Transfer - Exchange SMTP commands and responses
  5. Cleanup - Close channels and connection when queue empty

Performance Considerations

Queue Management

  • Messages are processed in priority order
  • Batch processing reduces connection overhead
  • Automatic queue size management prevents memory issues

Connection Efficiency

  • Single WebSocket connection handles multiple SMTP sessions
  • Intelligent connect/disconnect based on queue state
  • Connection pooling and reuse optimization

Memory Usage

  • Efficient message queuing with cleanup
  • Automatic resource management
  • Configurable limits and timeouts

Best Practices

Production Configuration

const client = new SMTPOverWSClient({
    url: 'ws://your-production-server/smtp',
    apiKey: process.env.SMTP_RELAY_API_KEY!,
    
    // Connection settings
    reconnectInterval: 10000,
    maxReconnectAttempts: 5,
    heartbeatInterval: 30000,
    
    // Timeouts
    authTimeout: 30000,
    channelTimeout: 15000,
    messageTimeout: 120000,
    
    // Queue settings
    maxQueueSize: 5000,
    batchSize: 50,
    
    // Monitoring
    debug: false,
    logger: new ProductionLogger()
});

Error Recovery

client.on('error', async (error) => {
    // Log error to monitoring system
    logger.error('SMTP client error', { error: error.toJSON() });
    
    // Implement circuit breaker pattern
    if (error instanceof ConnectionError && consecutiveErrors > 10) {
        await client.shutdown();
        // Implement fallback mechanism
    }
});

Graceful Shutdown

process.on('SIGTERM', async () => {
    console.log('Shutting down SMTP client...');
    try {
        await client.shutdown(30000); // 30 second timeout
        console.log('SMTP client shutdown complete');
    } catch (error) {
        console.error('Forced shutdown due to timeout');
    }
    process.exit(0);
});

Development

Building from Source

# Clone repository
git clone https://github.com/siwatsystem/smtp-ws-relay-client.git
cd smtp-ws-relay-client

# Install dependencies
npm install

# Build library
npm run build

# Run tests
npm test

# Run examples
npm run example:basic

Testing

# Run all tests
npm test

# Run with coverage
npm run test:coverage

# Watch mode
npm run test:watch

API Reference

SMTPOverWSClient

Constructor

  • new SMTPOverWSClient(config: SMTPClientConfig)

Methods

  • sendSMTPCommand(data: string, options?: SendOptions): Promise<string>
  • getStats(): ClientStats
  • getConnectionState(): ConnectionState
  • getQueueSize(): number
  • clearQueue(): void
  • shutdown(timeout?: number): Promise<void>

Events

  • connecting, connected, authenticated, disconnected
  • reconnecting, reconnected, error
  • messageQueued, messageProcessed, messageFailed
  • queueProcessingStarted, queueProcessingCompleted
  • channelOpened, channelClosed, channelError
  • stateChanged

Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

Changelog

See CHANGELOG.md for version history and updates.


Built with ❤️ by SiwatSystem