dcrouter/test/suite/smtpclient_commands/test.ccmd-03.rcpt-to-multiple.ts
2025-05-25 19:05:43 +00:00

283 lines
9.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
let smtpClient: SmtpClient;
tap.test('setup - start SMTP server for RCPT TO tests', async () => {
testServer = await startTestServer({
port: 2543,
tlsEnabled: false,
authRequired: false,
maxRecipients: 10 // Set recipient limit
});
expect(testServer.port).toEqual(2543);
});
tap.test('setup - create SMTP client', async () => {
smtpClient = createSmtpClient({
host: testServer.hostname,
port: testServer.port,
secure: false,
connectionTimeout: 5000,
debug: true
});
const isConnected = await smtpClient.verify();
expect(isConnected).toBeTrue();
});
tap.test('CCMD-03: RCPT TO - should send to single recipient', async () => {
const email = new Email({
from: 'sender@example.com',
to: 'single@example.com',
subject: 'Single Recipient Test',
text: 'Testing single RCPT TO command'
});
const result = await smtpClient.sendMail(email);
expect(result.success).toBeTrue();
expect(result.acceptedRecipients).toContain('single@example.com');
expect(result.acceptedRecipients.length).toEqual(1);
expect(result.envelope?.to).toContain('single@example.com');
console.log('✅ Single RCPT TO command successful');
});
tap.test('CCMD-03: RCPT TO - should send to multiple TO recipients', async () => {
const recipients = [
'recipient1@example.com',
'recipient2@example.com',
'recipient3@example.com'
];
const email = new Email({
from: 'sender@example.com',
to: recipients,
subject: 'Multiple Recipients Test',
text: 'Testing multiple RCPT TO commands'
});
const result = await smtpClient.sendMail(email);
expect(result.success).toBeTrue();
expect(result.acceptedRecipients.length).toEqual(3);
recipients.forEach(recipient => {
expect(result.acceptedRecipients).toContain(recipient);
});
console.log(`✅ Sent to ${result.acceptedRecipients.length} recipients`);
});
tap.test('CCMD-03: RCPT TO - should handle CC recipients', async () => {
const email = new Email({
from: 'sender@example.com',
to: 'primary@example.com',
cc: ['cc1@example.com', 'cc2@example.com'],
subject: 'CC Recipients Test',
text: 'Testing RCPT TO with CC recipients'
});
const result = await smtpClient.sendMail(email);
expect(result.success).toBeTrue();
expect(result.acceptedRecipients.length).toEqual(3);
expect(result.acceptedRecipients).toContain('primary@example.com');
expect(result.acceptedRecipients).toContain('cc1@example.com');
expect(result.acceptedRecipients).toContain('cc2@example.com');
console.log('✅ CC recipients handled correctly');
});
tap.test('CCMD-03: RCPT TO - should handle BCC recipients', async () => {
const email = new Email({
from: 'sender@example.com',
to: 'visible@example.com',
bcc: ['hidden1@example.com', 'hidden2@example.com'],
subject: 'BCC Recipients Test',
text: 'Testing RCPT TO with BCC recipients'
});
const result = await smtpClient.sendMail(email);
expect(result.success).toBeTrue();
expect(result.acceptedRecipients.length).toEqual(3);
expect(result.acceptedRecipients).toContain('visible@example.com');
expect(result.acceptedRecipients).toContain('hidden1@example.com');
expect(result.acceptedRecipients).toContain('hidden2@example.com');
// BCC recipients should be in envelope but not in headers
expect(result.envelope?.to.length).toEqual(3);
console.log('✅ BCC recipients handled correctly');
});
tap.test('CCMD-03: RCPT TO - should handle mixed TO, CC, and BCC', async () => {
const email = new Email({
from: 'sender@example.com',
to: ['to1@example.com', 'to2@example.com'],
cc: ['cc1@example.com', 'cc2@example.com'],
bcc: ['bcc1@example.com', 'bcc2@example.com'],
subject: 'Mixed Recipients Test',
text: 'Testing all recipient types together'
});
const result = await smtpClient.sendMail(email);
expect(result.success).toBeTrue();
expect(result.acceptedRecipients.length).toEqual(6);
console.log('✅ Mixed recipient types handled correctly');
console.log(` TO: 2, CC: 2, BCC: 2 = Total: ${result.acceptedRecipients.length}`);
});
tap.test('CCMD-03: RCPT TO - should handle recipient limit', async () => {
// Create more recipients than server allows
const manyRecipients = [];
for (let i = 0; i < 15; i++) {
manyRecipients.push(`recipient${i}@example.com`);
}
const email = new Email({
from: 'sender@example.com',
to: manyRecipients,
subject: 'Recipient Limit Test',
text: 'Testing server recipient limits'
});
const result = await smtpClient.sendMail(email);
// Server should accept up to its limit
if (result.rejectedRecipients.length > 0) {
console.log(`✅ Server enforced recipient limit:`);
console.log(` Accepted: ${result.acceptedRecipients.length}`);
console.log(` Rejected: ${result.rejectedRecipients.length}`);
expect(result.acceptedRecipients.length).toBeLessThanOrEqual(10);
} else {
// Server accepted all
expect(result.acceptedRecipients.length).toEqual(15);
console.log(' Server accepted all recipients');
}
});
tap.test('CCMD-03: RCPT TO - should handle invalid recipients gracefully', async () => {
const mixedRecipients = [
'valid1@example.com',
'invalid@address@with@multiple@ats.com',
'valid2@example.com',
'no-domain@',
'valid3@example.com'
];
// Filter out invalid recipients before creating the email
const validRecipients = mixedRecipients.filter(r => {
// Basic validation: must have @ and non-empty parts before and after @
const parts = r.split('@');
return parts.length === 2 && parts[0].length > 0 && parts[1].length > 0;
});
const email = new Email({
from: 'sender@example.com',
to: validRecipients,
subject: 'Mixed Valid/Invalid Recipients',
text: 'Testing partial recipient acceptance'
});
const result = await smtpClient.sendMail(email);
expect(result.success).toBeTrue();
expect(result.acceptedRecipients).toContain('valid1@example.com');
expect(result.acceptedRecipients).toContain('valid2@example.com');
expect(result.acceptedRecipients).toContain('valid3@example.com');
console.log('✅ Valid recipients accepted, invalid filtered');
});
tap.test('CCMD-03: RCPT TO - should handle duplicate recipients', async () => {
const email = new Email({
from: 'sender@example.com',
to: ['user@example.com', 'user@example.com'],
cc: ['user@example.com'],
bcc: ['user@example.com'],
subject: 'Duplicate Recipients Test',
text: 'Testing duplicate recipient handling'
});
const result = await smtpClient.sendMail(email);
expect(result.success).toBeTrue();
// Check if duplicates were removed
const uniqueAccepted = [...new Set(result.acceptedRecipients)];
console.log(`✅ Duplicate handling: ${result.acceptedRecipients.length} total, ${uniqueAccepted.length} unique`);
});
tap.test('CCMD-03: RCPT TO - should handle special characters in recipient addresses', async () => {
const specialRecipients = [
'user+tag@example.com',
'first.last@example.com',
'user_name@example.com',
'user-name@example.com',
'"quoted.user"@example.com'
];
const email = new Email({
from: 'sender@example.com',
to: specialRecipients.filter(r => !r.includes('"')), // Skip quoted for Email class
subject: 'Special Characters Test',
text: 'Testing special characters in recipient addresses'
});
const result = await smtpClient.sendMail(email);
expect(result.success).toBeTrue();
expect(result.acceptedRecipients.length).toBeGreaterThan(0);
console.log(`✅ Special character recipients accepted: ${result.acceptedRecipients.length}`);
});
tap.test('CCMD-03: RCPT TO - should maintain recipient order', async () => {
const orderedRecipients = [
'first@example.com',
'second@example.com',
'third@example.com',
'fourth@example.com'
];
const email = new Email({
from: 'sender@example.com',
to: orderedRecipients,
subject: 'Recipient Order Test',
text: 'Testing if recipient order is maintained'
});
const result = await smtpClient.sendMail(email);
expect(result.success).toBeTrue();
expect(result.envelope?.to.length).toEqual(orderedRecipients.length);
// Check order preservation
orderedRecipients.forEach((recipient, index) => {
expect(result.envelope?.to[index]).toEqual(recipient);
});
console.log('✅ Recipient order maintained in envelope');
});
tap.test('cleanup - close SMTP client', async () => {
if (smtpClient && smtpClient.isConnected()) {
await smtpClient.close();
}
});
tap.test('cleanup - stop SMTP server', async () => {
await stopTestServer(testServer);
});
export default tap.start();