233 lines
6.9 KiB
TypeScript
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(); |