- Implemented SMTP client utilities in `test/helpers/smtp.client.ts` for creating test clients, sending emails, and testing connections. - Developed SMTP protocol test utilities in `test/helpers/utils.ts` for managing TCP connections, sending commands, and handling responses. - Created a detailed README in `test/readme.md` outlining the test framework, infrastructure, organization, and running instructions. - Ported CMD-01: EHLO Command tests in `test/suite/smtpserver_commands/test.cmd-01.ehlo-command.test.ts` with multiple scenarios including valid and invalid hostnames. - Ported CMD-02: MAIL FROM Command tests in `test/suite/smtpserver_commands/test.cmd-02.mail-from.test.ts` covering valid address acceptance, invalid address rejection, SIZE parameter support, and command sequence enforcement.
		
			
				
	
	
		
			237 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * Test SMTP Client Utilities for Deno
 | |
|  * Provides helpers for creating and testing SMTP client functionality
 | |
|  */
 | |
| 
 | |
| import { smtpClientMod } from '../../ts/mail/delivery/index.ts';
 | |
| import type { ISmtpClientOptions } from '../../ts/mail/delivery/smtpclient/interfaces.ts';
 | |
| import type { SmtpClient } from '../../ts/mail/delivery/smtpclient/smtp-client.ts';
 | |
| import { Email } from '../../ts/mail/core/classes.email.ts';
 | |
| 
 | |
| /**
 | |
|  * Create a test SMTP client with sensible defaults
 | |
|  */
 | |
| export function createTestSmtpClient(options: Partial<ISmtpClientOptions> = {}): SmtpClient {
 | |
|   const defaultOptions: ISmtpClientOptions = {
 | |
|     host: options.host || 'localhost',
 | |
|     port: options.port || 2525,
 | |
|     secure: options.secure || false,
 | |
|     auth: options.auth,
 | |
|     connectionTimeout: options.connectionTimeout || 5000,
 | |
|     socketTimeout: options.socketTimeout || 5000,
 | |
|     maxConnections: options.maxConnections || 5,
 | |
|     maxMessages: options.maxMessages || 100,
 | |
|     debug: options.debug || false,
 | |
|     tls: options.tls || {
 | |
|       rejectUnauthorized: false,
 | |
|     },
 | |
|     pool: options.pool || false,
 | |
|   };
 | |
| 
 | |
|   return smtpClientMod.createSmtpClient(defaultOptions);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Send test email using SMTP client
 | |
|  */
 | |
| export async function sendTestEmail(
 | |
|   client: SmtpClient,
 | |
|   options: {
 | |
|     from?: string;
 | |
|     to?: string | string[];
 | |
|     subject?: string;
 | |
|     text?: string;
 | |
|     html?: string;
 | |
|   } = {}
 | |
| ): Promise<any> {
 | |
|   const mailOptions = {
 | |
|     from: options.from || 'test@example.com',
 | |
|     to: options.to || 'recipient@example.com',
 | |
|     subject: options.subject || 'Test Email',
 | |
|     text: options.text || 'This is a test email',
 | |
|     html: options.html,
 | |
|   };
 | |
| 
 | |
|   const email = new Email({
 | |
|     from: mailOptions.from,
 | |
|     to: mailOptions.to,
 | |
|     subject: mailOptions.subject,
 | |
|     text: mailOptions.text,
 | |
|     html: mailOptions.html,
 | |
|   });
 | |
| 
 | |
|   return client.sendMail(email);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Test SMTP client connection
 | |
|  */
 | |
| export async function testClientConnection(
 | |
|   host: string,
 | |
|   port: number,
 | |
|   timeout: number = 5000
 | |
| ): Promise<boolean> {
 | |
|   const client = createTestSmtpClient({
 | |
|     host,
 | |
|     port,
 | |
|     connectionTimeout: timeout,
 | |
|   });
 | |
| 
 | |
|   try {
 | |
|     const result = await client.verify();
 | |
|     return result;
 | |
|   } catch (error) {
 | |
|     throw error;
 | |
|   } finally {
 | |
|     if (client.close) {
 | |
|       await client.close();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Create authenticated SMTP client
 | |
|  */
 | |
| export function createAuthenticatedClient(
 | |
|   host: string,
 | |
|   port: number,
 | |
|   username: string,
 | |
|   password: string,
 | |
|   authMethod: 'PLAIN' | 'LOGIN' = 'PLAIN'
 | |
| ): SmtpClient {
 | |
|   return createTestSmtpClient({
 | |
|     host,
 | |
|     port,
 | |
|     auth: {
 | |
|       user: username,
 | |
|       pass: password,
 | |
|       method: authMethod,
 | |
|     },
 | |
|     secure: false,
 | |
|   });
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Create TLS-enabled SMTP client
 | |
|  */
 | |
| export function createTlsClient(
 | |
|   host: string,
 | |
|   port: number,
 | |
|   options: {
 | |
|     secure?: boolean;
 | |
|     rejectUnauthorized?: boolean;
 | |
|   } = {}
 | |
| ): SmtpClient {
 | |
|   return createTestSmtpClient({
 | |
|     host,
 | |
|     port,
 | |
|     secure: options.secure || false,
 | |
|     tls: {
 | |
|       rejectUnauthorized: options.rejectUnauthorized || false,
 | |
|     },
 | |
|   });
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Test client pool status
 | |
|  */
 | |
| export async function testClientPoolStatus(client: SmtpClient): Promise<any> {
 | |
|   if (typeof client.getPoolStatus === 'function') {
 | |
|     return client.getPoolStatus();
 | |
|   }
 | |
| 
 | |
|   // Fallback for clients without pool status
 | |
|   return {
 | |
|     size: 1,
 | |
|     available: 1,
 | |
|     pending: 0,
 | |
|     connecting: 0,
 | |
|     active: 0,
 | |
|   };
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Send multiple emails concurrently
 | |
|  */
 | |
| export async function sendConcurrentEmails(
 | |
|   client: SmtpClient,
 | |
|   count: number,
 | |
|   emailOptions: {
 | |
|     from?: string;
 | |
|     to?: string;
 | |
|     subject?: string;
 | |
|     text?: string;
 | |
|   } = {}
 | |
| ): Promise<any[]> {
 | |
|   const promises = [];
 | |
| 
 | |
|   for (let i = 0; i < count; i++) {
 | |
|     promises.push(
 | |
|       sendTestEmail(client, {
 | |
|         ...emailOptions,
 | |
|         subject: `${emailOptions.subject || 'Test Email'} ${i + 1}`,
 | |
|       })
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   return Promise.all(promises);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Measure client throughput
 | |
|  */
 | |
| export async function measureClientThroughput(
 | |
|   client: SmtpClient,
 | |
|   duration: number = 10000,
 | |
|   emailOptions: {
 | |
|     from?: string;
 | |
|     to?: string;
 | |
|     subject?: string;
 | |
|     text?: string;
 | |
|   } = {}
 | |
| ): Promise<{
 | |
|   totalSent: number;
 | |
|   successCount: number;
 | |
|   errorCount: number;
 | |
|   throughput: number;
 | |
| }> {
 | |
|   const startTime = Date.now();
 | |
|   let totalSent = 0;
 | |
|   let successCount = 0;
 | |
|   let errorCount = 0;
 | |
| 
 | |
|   while (Date.now() - startTime < duration) {
 | |
|     try {
 | |
|       await sendTestEmail(client, emailOptions);
 | |
|       successCount++;
 | |
|     } catch (error) {
 | |
|       errorCount++;
 | |
|     }
 | |
|     totalSent++;
 | |
|   }
 | |
| 
 | |
|   const actualDuration = (Date.now() - startTime) / 1000; // in seconds
 | |
|   const throughput = totalSent / actualDuration;
 | |
| 
 | |
|   return {
 | |
|     totalSent,
 | |
|     successCount,
 | |
|     errorCount,
 | |
|     throughput,
 | |
|   };
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Create a pooled SMTP client for concurrent testing
 | |
|  */
 | |
| export function createPooledTestClient(
 | |
|   options: Partial<ISmtpClientOptions> = {}
 | |
| ): SmtpClient {
 | |
|   return createTestSmtpClient({
 | |
|     ...options,
 | |
|     pool: true,
 | |
|     maxConnections: options.maxConnections || 5,
 | |
|     maxMessages: options.maxMessages || 100,
 | |
|   });
 | |
| }
 |