- 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,
|
|
});
|
|
}
|