update
This commit is contained in:
@ -0,0 +1,321 @@
|
||||
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 MIME tests', async () => {
|
||||
testServer = await startTestServer({
|
||||
port: 2571,
|
||||
tlsEnabled: false,
|
||||
authRequired: false,
|
||||
size: 25 * 1024 * 1024 // 25MB for attachment tests
|
||||
});
|
||||
|
||||
expect(testServer.port).toEqual(2571);
|
||||
});
|
||||
|
||||
tap.test('setup - create SMTP client', async () => {
|
||||
smtpClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
connectionTimeout: 5000,
|
||||
socketTimeout: 60000, // Longer timeout for large attachments
|
||||
debug: true
|
||||
});
|
||||
|
||||
const isConnected = await smtpClient.verify();
|
||||
expect(isConnected).toBeTrue();
|
||||
});
|
||||
|
||||
tap.test('CEP-02: MIME Multipart - should send multipart/alternative (text + HTML)', async () => {
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Multipart Alternative Test',
|
||||
text: 'This is the plain text version of the email.',
|
||||
html: '<html><body><h1>HTML Version</h1><p>This is the <strong>HTML version</strong> of the email.</p></body></html>'
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
|
||||
expect(result.success).toBeTrue();
|
||||
console.log('✅ Multipart/alternative email sent successfully');
|
||||
});
|
||||
|
||||
tap.test('CEP-02: MIME Multipart - should send multipart/mixed with attachments', async () => {
|
||||
const textAttachment = Buffer.from('This is a text file attachment content.');
|
||||
const csvData = 'Name,Email,Score\nJohn Doe,john@example.com,95\nJane Smith,jane@example.com,87';
|
||||
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Multipart Mixed with Attachments',
|
||||
text: 'This email contains attachments.',
|
||||
html: '<p>This email contains <strong>attachments</strong>.</p>',
|
||||
attachments: [
|
||||
{
|
||||
filename: 'document.txt',
|
||||
content: textAttachment,
|
||||
contentType: 'text/plain'
|
||||
},
|
||||
{
|
||||
filename: 'data.csv',
|
||||
content: Buffer.from(csvData),
|
||||
contentType: 'text/csv'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
|
||||
expect(result.success).toBeTrue();
|
||||
console.log('✅ Multipart/mixed with attachments sent successfully');
|
||||
});
|
||||
|
||||
tap.test('CEP-02: MIME Multipart - should handle inline images', async () => {
|
||||
// Create a small test image (1x1 red pixel PNG)
|
||||
const redPixelPng = Buffer.from(
|
||||
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==',
|
||||
'base64'
|
||||
);
|
||||
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Inline Image Test',
|
||||
text: 'This email contains an inline image.',
|
||||
html: '<p>Here is an inline image: <img src="cid:red-pixel" alt="Red Pixel"></p>',
|
||||
attachments: [
|
||||
{
|
||||
filename: 'red-pixel.png',
|
||||
content: redPixelPng,
|
||||
contentType: 'image/png',
|
||||
contentId: 'red-pixel' // Content-ID for inline reference
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
|
||||
expect(result.success).toBeTrue();
|
||||
console.log('✅ Email with inline image sent successfully');
|
||||
});
|
||||
|
||||
tap.test('CEP-02: MIME Multipart - should handle multiple attachment types', async () => {
|
||||
const attachments = [
|
||||
{
|
||||
filename: 'text.txt',
|
||||
content: Buffer.from('Plain text file'),
|
||||
contentType: 'text/plain'
|
||||
},
|
||||
{
|
||||
filename: 'data.json',
|
||||
content: Buffer.from(JSON.stringify({ test: 'data', value: 123 })),
|
||||
contentType: 'application/json'
|
||||
},
|
||||
{
|
||||
filename: 'binary.bin',
|
||||
content: Buffer.from([0x00, 0x01, 0x02, 0x03, 0xFF, 0xFE, 0xFD]),
|
||||
contentType: 'application/octet-stream'
|
||||
},
|
||||
{
|
||||
filename: 'document.pdf',
|
||||
content: Buffer.from('%PDF-1.4\n%fake pdf content for testing'),
|
||||
contentType: 'application/pdf'
|
||||
}
|
||||
];
|
||||
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Multiple Attachment Types',
|
||||
text: 'Testing various attachment types',
|
||||
attachments
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
|
||||
expect(result.success).toBeTrue();
|
||||
console.log('✅ Multiple attachment types handled correctly');
|
||||
});
|
||||
|
||||
tap.test('CEP-02: MIME Multipart - should encode binary attachments with base64', async () => {
|
||||
// Create binary data with all byte values
|
||||
const binaryData = Buffer.alloc(256);
|
||||
for (let i = 0; i < 256; i++) {
|
||||
binaryData[i] = i;
|
||||
}
|
||||
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Binary Attachment Encoding Test',
|
||||
text: 'This email contains binary data that must be base64 encoded',
|
||||
attachments: [
|
||||
{
|
||||
filename: 'binary-data.bin',
|
||||
content: binaryData,
|
||||
contentType: 'application/octet-stream',
|
||||
encoding: 'base64' // Explicitly specify encoding
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
|
||||
expect(result.success).toBeTrue();
|
||||
console.log('✅ Binary attachment base64 encoded correctly');
|
||||
});
|
||||
|
||||
tap.test('CEP-02: MIME Multipart - should handle large attachments', async () => {
|
||||
// Create a 5MB attachment
|
||||
const largeData = Buffer.alloc(5 * 1024 * 1024);
|
||||
for (let i = 0; i < largeData.length; i++) {
|
||||
largeData[i] = i % 256;
|
||||
}
|
||||
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Large Attachment Test',
|
||||
text: 'This email contains a large attachment',
|
||||
attachments: [
|
||||
{
|
||||
filename: 'large-file.dat',
|
||||
content: largeData,
|
||||
contentType: 'application/octet-stream'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const startTime = Date.now();
|
||||
const result = await smtpClient.sendMail(email);
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
expect(result.success).toBeTrue();
|
||||
console.log(`✅ Large attachment (5MB) sent in ${duration}ms`);
|
||||
});
|
||||
|
||||
tap.test('CEP-02: MIME Multipart - should handle nested multipart structures', async () => {
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Complex Multipart Structure',
|
||||
text: 'Plain text version',
|
||||
html: '<p>HTML version with <img src="cid:logo" alt="Logo"></p>',
|
||||
attachments: [
|
||||
{
|
||||
filename: 'logo.png',
|
||||
content: Buffer.from('fake png data'),
|
||||
contentType: 'image/png',
|
||||
contentId: 'logo' // Inline image
|
||||
},
|
||||
{
|
||||
filename: 'attachment.txt',
|
||||
content: Buffer.from('Regular attachment'),
|
||||
contentType: 'text/plain'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
|
||||
expect(result.success).toBeTrue();
|
||||
console.log('✅ Nested multipart structure (mixed + related + alternative) handled');
|
||||
});
|
||||
|
||||
tap.test('CEP-02: MIME Multipart - should handle attachment filenames with special characters', async () => {
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Special Filename Test',
|
||||
text: 'Testing attachments with special filenames',
|
||||
attachments: [
|
||||
{
|
||||
filename: 'file with spaces.txt',
|
||||
content: Buffer.from('Content 1'),
|
||||
contentType: 'text/plain'
|
||||
},
|
||||
{
|
||||
filename: 'файл.txt', // Cyrillic
|
||||
content: Buffer.from('Content 2'),
|
||||
contentType: 'text/plain'
|
||||
},
|
||||
{
|
||||
filename: '文件.txt', // Chinese
|
||||
content: Buffer.from('Content 3'),
|
||||
contentType: 'text/plain'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
|
||||
expect(result.success).toBeTrue();
|
||||
console.log('✅ Special characters in filenames handled correctly');
|
||||
});
|
||||
|
||||
tap.test('CEP-02: MIME Multipart - should handle empty attachments', async () => {
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Empty Attachment Test',
|
||||
text: 'This email has an empty attachment',
|
||||
attachments: [
|
||||
{
|
||||
filename: 'empty.txt',
|
||||
content: Buffer.from(''), // Empty content
|
||||
contentType: 'text/plain'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
|
||||
expect(result.success).toBeTrue();
|
||||
console.log('✅ Empty attachment handled correctly');
|
||||
});
|
||||
|
||||
tap.test('CEP-02: MIME Multipart - should respect content-type parameters', async () => {
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Content-Type Parameters Test',
|
||||
text: 'Testing content-type with charset',
|
||||
html: '<p>HTML with specific charset</p>',
|
||||
attachments: [
|
||||
{
|
||||
filename: 'utf8-text.txt',
|
||||
content: Buffer.from('UTF-8 text: 你好世界'),
|
||||
contentType: 'text/plain; charset=utf-8'
|
||||
},
|
||||
{
|
||||
filename: 'data.xml',
|
||||
content: Buffer.from('<?xml version="1.0" encoding="UTF-8"?><root>Test</root>'),
|
||||
contentType: 'application/xml; charset=utf-8'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
|
||||
expect(result.success).toBeTrue();
|
||||
console.log('✅ Content-type parameters preserved correctly');
|
||||
});
|
||||
|
||||
tap.test('cleanup - close SMTP client', async () => {
|
||||
if (smtpClient && smtpClient.isConnected()) {
|
||||
await smtpClient.close();
|
||||
}
|
||||
});
|
||||
|
||||
tap.test('cleanup - stop SMTP server', async () => {
|
||||
await stopTestServer(testServer);
|
||||
});
|
||||
|
||||
tap.start();
|
Reference in New Issue
Block a user