dcrouter/test/suite/smtpclient_commands/test.ccmd-06.command-pipelining.ts
2025-05-25 19:05:43 +00:00

233 lines
6.9 KiB
TypeScript

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();