# @siwatsystem/smtp-ws-relay-client [![npm version](https://badge.fury.io/js/@siwatsystem%2Fsmtp-ws-relay-client.svg)](https://badge.fury.io/js/@siwatsystem%2Fsmtp-ws-relay-client) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/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 ```bash npm install @siwatsystem/smtp-ws-relay-client ``` ## Quick Start ```typescript 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: \\r\\n'); const response3 = await client.sendSMTPCommand('RCPT TO: \\r\\n'); console.log('SMTP responses:', [response1, response2, response3]); } catch (error) { console.error('SMTP error:', error); } // Graceful shutdown await client.shutdown(); ``` ## Configuration Options ```typescript 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 ```typescript 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 ```typescript // 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 ```typescript // 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 ```typescript 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: ```typescript 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 ```typescript 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 ```typescript 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 ```typescript 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 ```bash # 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 ```bash # 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` - `getStats(): ClientStats` - `getConnectionState(): ConnectionState` - `getQueueSize(): number` - `clearQueue(): void` - `shutdown(timeout?: number): Promise` #### 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](CONTRIBUTING.md) 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](LICENSE) file for details. ## Support - 📧 Email: [support@siwatsystem.com](mailto:support@siwatsystem.com) - 🐛 Issues: [GitHub Issues](https://github.com/siwatsystem/smtp-ws-relay-client/issues) - 📖 Documentation: [API Docs](https://siwatsystem.github.io/smtp-ws-relay-client/) ## Changelog See [CHANGELOG.md](CHANGELOG.md) for version history and updates. --- Built with ❤️ by [SiwatSystem](https://siwatsystem.com)