# @siwatsystem/mxrelay-consumer [![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. Includes full Nodemailer transport compatibility. ## Features **Intelligent Queue Management** - Automatic WebSocket connection when messages are queued - Priority-based message processing (CRITICAL > HIGH > NORMAL > LOW) - Configurable queue limits and overflow protection - Auto-disconnect when queue is empty **Robust Connection Handling** - Automatic reconnection with exponential backoff - Connection state management and lifecycle - Heartbeat monitoring and timeout handling - Graceful connection recovery **High Performance** - Efficient SMTP channel cycling per message - Minimal resource usage with smart connection management - Concurrent message processing support - Optimized WebSocket communication **Enterprise-Grade Reliability** - Comprehensive SMTP error handling with meaningful messages - Timeout management for all operations - Retry logic with configurable attempts - Structured error classification **Nodemailer Integration** - Full Nodemailer transport compatibility - Transparent bridge for all email features - Support for attachments, HTML, multipart messages - Standard Nodemailer API compatibility ## Installation ```bash npm install @siwatsystem/mxrelay-consumer # or bun add @siwatsystem/mxrelay-consumer ``` ## Quick Start ### Direct Client Usage ```typescript import { SMTPOverWSClient } from '@siwatsystem/mxrelay-consumer'; const client = new SMTPOverWSClient({ url: 'wss://api.siwatsystem.com/smtp', apiKey: 'your-api-key', debug: true }); // Send SMTP commands directly try { const response = await client.sendSMTPCommand(` MAIL FROM: RCPT TO: DATA Subject: Test Email Hello from SMTP over WebSocket! . QUIT `); console.log('Email sent:', response); } catch (error) { console.error('SMTP error:', error.message); } finally { await client.shutdown(); } ``` ### Nodemailer Transport ```typescript import nodemailer from 'nodemailer'; import { createTransport } from '@siwatsystem/mxrelay-consumer'; // Create transport (uses defaults: api.siwatsystem.com:443 secure) const transport = createTransport('your-api-key'); // Or with custom options const transport = createTransport('your-api-key', { host: 'custom.server.com', port: 80, secure: false, debug: true }); const transporter = nodemailer.createTransporter(transport); // Send email using standard Nodemailer API const info = await transporter.sendMail({ from: 'sender@example.com', to: 'recipient@example.com', subject: 'Test Email via SMTP WebSocket', text: 'Plain text version', html: '

HTML version

', attachments: [ { filename: 'document.pdf', path: './document.pdf' } ] }); console.log('Message sent:', info.messageId); await transport.close(); ``` ## Configuration ### Client Configuration ```typescript interface SMTPClientConfig { url: string; // WebSocket server URL apiKey: string; // Authentication API key debug?: boolean; // Enable debug logging (default: false) maxQueueSize?: number; // Queue capacity limit (default: 1000) reconnectInterval?: number; // Reconnect delay (default: 5000ms) maxReconnectAttempts?: number; // Max retry attempts (default: 10) authTimeout?: number; // Auth timeout (default: 30000ms) channelTimeout?: number; // Channel timeout (default: 10000ms) messageTimeout?: number; // Message timeout (default: 60000ms) heartbeatInterval?: number; // Heartbeat interval (default: 30000ms) maxConcurrentMessages?: number; // Concurrent limit (default: 1) } ``` ### Transport Configuration ```typescript interface TransportOptions { host?: string; // Server host (default: 'api.siwatsystem.com') port?: number; // Server port (default: 443) secure?: boolean; // Use wss:// (default: true) debug?: boolean; // Enable debug mode (default: false) // ... other SMTPClientConfig options } ``` ## Advanced Usage ### Priority-Based Messaging ```typescript import { MessagePriority } from '@siwatsystem/mxrelay-consumer'; // High priority (processed first) await client.sendSMTPCommand('URGENT EMAIL DATA', { priority: MessagePriority.HIGH, timeout: 30000 }); // Critical priority (highest) await client.sendSMTPCommand('CRITICAL ALERT EMAIL', { priority: MessagePriority.CRITICAL }); ``` ### Event Monitoring ```typescript // Connection events client.on('connected', () => console.log('WebSocket connected')); client.on('authenticated', () => console.log('Authentication successful')); client.on('disconnected', () => console.log('Connection lost')); // 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`); }); // Error events client.on('error', (error) => console.error('Client error:', error)); ``` ### Statistics and Monitoring ```typescript const stats = client.getStats(); console.log('Client Statistics:', { messagesQueued: stats.messagesQueued, messagesProcessed: stats.messagesProcessed, messagesFailed: stats.messagesFailed, averageResponseTime: stats.averageResponseTime, queueSize: stats.queueSize }); ``` ## Error Handling ### SMTP Error Detection The transport properly detects and categorizes SMTP errors: ```typescript try { await transporter.sendMail({ from: 'unauthorized@domain.com', // Invalid sender to: 'recipient@example.com', subject: 'Test' }); } catch (error) { console.error('SMTP Error:', error.message); // Output: "Sender not authorized: Sender domain not authorized for your IP or subnet" console.log('Error details:', { smtpCode: error.context.smtpCode, // "550" rejectedRecipients: error.context.rejectedRecipients }); } ``` ### Error Classification ```typescript import { ConnectionError, AuthenticationError, MessageError, TimeoutError } from '@siwatsystem/mxrelay-consumer'; try { await client.sendSMTPCommand('MAIL FROM: '); } 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 MessageError) { console.error('SMTP error:', error.message, 'Code:', error.context.smtpCode); } else if (error instanceof TimeoutError) { console.error('Operation timed out:', error.message); } } ``` ## Connection States The client manages connection states automatically: - `DISCONNECTED` - No connection - `CONNECTING` - Establishing WebSocket connection - `CONNECTED` - WebSocket connected, authentication pending - `AUTHENTICATING` - Sending credentials - `AUTHENTICATED` - Ready for SMTP operations - `CHANNEL_OPENING` - Opening SMTP channel - `CHANNEL_READY` - SMTP channel active - `CHANNEL_CLOSED` - SMTP channel closed - `RECONNECTING` - Attempting reconnection - `FAILED` - Connection failed, max retries reached ## Development This project uses Bun as the primary runtime. TypeScript files can be run directly without building. ### Setup ```bash # Clone repository git clone https://git.siwatsystem.com/siwat/mxrelay-consumer.git cd mxrelay-consumer # Install dependencies bun install # Run examples directly bun run examples/nodemailer-transport.ts # Run with environment variable MXRELAY_API_KEY=your-key bun run examples/nodemailer-transport.ts ``` ### Build & Test ```bash # Build (optional - bun runs TypeScript directly) bun run build # Run tests bun test # Run linting bun run lint # Format code bun run format ``` ## Protocol Implementation ### WebSocket 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` - SMTP data exchange ### Connection Flow 1. **WebSocket Connection** - Connect to relay server 2. **Authentication** - Authenticate using API key 3. **Channel Management** - Open SMTP channel per message 4. **Data Transfer** - Exchange SMTP commands and responses 5. **Cleanup** - Close channel and disconnect when queue empty ## Best Practices ### Production Configuration ```typescript const client = new SMTPOverWSClient({ url: 'wss://api.siwatsystem.com/smtp', apiKey: process.env.MXRELAY_API_KEY, // Production settings debug: false, maxQueueSize: 5000, reconnectInterval: 10000, maxReconnectAttempts: 5, messageTimeout: 120000 }); ``` ### Graceful Shutdown ```typescript process.on('SIGTERM', async () => { console.log('Shutting down...'); try { await client.shutdown(30000); // 30 second timeout console.log('Shutdown complete'); } catch (error) { console.error('Forced shutdown'); } process.exit(0); }); ``` ## API Reference ### createTransport(apiKey, options?) Creates a Nodemailer-compatible transport. - `apiKey` - Your API key for authentication - `options` - Optional transport configuration ### SMTPOverWSClient Main client class for direct SMTP operations. #### Methods - `sendSMTPCommand(data, options?)` - Send SMTP command - `getStats()` - Get client statistics - `getConnectionState()` - Get current state - `getQueueSize()` - Get queue size - `shutdown(timeout?)` - Graceful shutdown #### Events - Connection: `connecting`, `connected`, `authenticated`, `disconnected` - Queue: `messageQueued`, `messageProcessed`, `messageFailed` - State: `stateChanged`, `error` ## License MIT License - see [LICENSE](LICENSE) file for details. ## Support - Issues: [Git Repository Issues](https://git.siwatsystem.com/siwat/mxrelay-consumer/issues) - Documentation: [Project Repository](https://git.siwatsystem.com/siwat/mxrelay-consumer) --- Built by SiwatSystem