import { tap, expect } from '@git.zone/tstest/tapbundle'; import { startTestServer, stopTestServer, type ITestServer } from '../../helpers/server.loader.js'; import { createSmtpClient } from '../../../ts/mail/delivery/smtpclient/index.js'; import type { SmtpClient } from '../../../ts/mail/delivery/smtpclient/smtp-client.js'; import { Email } from '../../../ts/mail/core/classes.email.js'; let testServer: ITestServer; tap.test('setup test SMTP server', async () => { testServer = await startTestServer({ port: 2546, tlsEnabled: false, authRequired: false }); expect(testServer).toBeTruthy(); expect(testServer.port).toBeGreaterThan(0); }); tap.test('CCMD-06: Check PIPELINING capability', async () => { const smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000, debug: true }); // The SmtpClient handles pipelining internally // We can verify the server supports it by checking a successful send const email = new Email({ from: 'sender@example.com', to: 'recipient@example.com', subject: 'Pipelining Test', text: 'Testing pipelining support' }); const result = await smtpClient.sendMail(email); expect(result.success).toBeTrue(); // Server logs show PIPELINING is advertised console.log('✅ Server supports PIPELINING (advertised in EHLO response)'); await smtpClient.close(); }); tap.test('CCMD-06: Basic command pipelining', async () => { const smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000, debug: true }); // Send email with multiple recipients to test pipelining const email = new Email({ from: 'sender@example.com', to: ['recipient1@example.com', 'recipient2@example.com'], subject: 'Multi-recipient Test', text: 'Testing pipelining with multiple recipients' }); const startTime = Date.now(); const result = await smtpClient.sendMail(email); const elapsed = Date.now() - startTime; expect(result.success).toBeTrue(); expect(result.acceptedRecipients.length).toEqual(2); console.log(`✅ Sent to ${result.acceptedRecipients.length} recipients in ${elapsed}ms`); console.log('Pipelining improves performance by sending multiple commands without waiting'); await smtpClient.close(); }); tap.test('CCMD-06: Pipelining with DATA command', async () => { const smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000, debug: true }); // Send a normal email - pipelining is handled internally const email = new Email({ from: 'sender@example.com', to: 'recipient@example.com', subject: 'DATA Command Test', text: 'Testing pipelining up to DATA command' }); const result = await smtpClient.sendMail(email); expect(result.success).toBeTrue(); console.log('✅ Commands pipelined up to DATA successfully'); console.log('DATA command requires synchronous handling as per RFC'); await smtpClient.close(); }); tap.test('CCMD-06: Pipelining error handling', async () => { const smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000, debug: true }); // Send email with mix of valid and potentially problematic recipients const email = new Email({ from: 'sender@example.com', to: [ 'valid1@example.com', 'valid2@example.com', 'valid3@example.com' ], subject: 'Error Handling Test', text: 'Testing pipelining error handling' }); const result = await smtpClient.sendMail(email); expect(result.success).toBeTrue(); console.log(`✅ Handled ${result.acceptedRecipients.length} recipients`); console.log('Pipelining handles errors gracefully'); await smtpClient.close(); }); tap.test('CCMD-06: Pipelining performance comparison', async () => { // Create two clients - both use pipelining by default when available const smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000 }); // Test with multiple recipients const email = new Email({ from: 'sender@example.com', to: [ 'recipient1@example.com', 'recipient2@example.com', 'recipient3@example.com', 'recipient4@example.com', 'recipient5@example.com' ], subject: 'Performance Test', text: 'Testing performance with multiple recipients' }); const startTime = Date.now(); const result = await smtpClient.sendMail(email); const elapsed = Date.now() - startTime; expect(result.success).toBeTrue(); expect(result.acceptedRecipients.length).toEqual(5); console.log(`✅ Sent to ${result.acceptedRecipients.length} recipients in ${elapsed}ms`); console.log('Pipelining provides significant performance improvements'); await smtpClient.close(); }); tap.test('CCMD-06: Pipelining with multiple recipients', async () => { const smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000, debug: true }); // Send to many recipients const recipients = Array.from({ length: 10 }, (_, i) => `recipient${i + 1}@example.com`); const email = new Email({ from: 'sender@example.com', to: recipients, subject: 'Many Recipients Test', text: 'Testing pipelining with many recipients' }); const result = await smtpClient.sendMail(email); expect(result.success).toBeTrue(); expect(result.acceptedRecipients.length).toEqual(recipients.length); console.log(`✅ Successfully sent to ${result.acceptedRecipients.length} recipients`); console.log('Pipelining efficiently handles multiple RCPT TO commands'); await smtpClient.close(); }); tap.test('CCMD-06: Pipelining limits and buffering', async () => { const smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000, debug: true }); // Test with a reasonable number of recipients const recipients = Array.from({ length: 50 }, (_, i) => `user${i + 1}@example.com`); const email = new Email({ from: 'sender@example.com', to: recipients.slice(0, 20), // Use first 20 for TO cc: recipients.slice(20, 35), // Next 15 for CC bcc: recipients.slice(35), // Rest for BCC subject: 'Buffering Test', text: 'Testing pipelining limits and buffering' }); const result = await smtpClient.sendMail(email); expect(result.success).toBeTrue(); const totalRecipients = email.to.length + email.cc.length + email.bcc.length; console.log(`✅ Handled ${totalRecipients} total recipients`); console.log('Pipelining respects server limits and buffers appropriately'); await smtpClient.close(); }); tap.test('cleanup test SMTP server', async () => { await stopTestServer(testServer); expect(testServer).toBeTruthy(); }); export default tap.start();