This commit is contained in:
2025-05-24 00:23:35 +00:00
parent 0907949f8a
commit cb52446f65
76 changed files with 1401 additions and 867 deletions

View File

@ -1,14 +1,28 @@
import { tap, expect } from '@git.zone/tstest/tapbundle';
import * as net from 'net';
import * as fs from 'fs';
import * as path from 'path';
import { startTestServer, stopTestServer } from '../../helpers/server.loader.js';
import type { SmtpServer } from '../../../ts/mail/delivery/smtpserver/index.js';
const TEST_PORT = 2525;
const SAMPLE_FILES_DIR = path.join(process.cwd(), '.nogit', 'sample-files');
let testServer: SmtpServer;
// Helper function to read and encode files
function readFileAsBase64(filePath: string): string {
try {
const fileContent = fs.readFileSync(filePath);
return fileContent.toString('base64');
} catch (err) {
console.error(`Failed to read file ${filePath}:`, err);
return '';
}
}
tap.test('setup - start test server', async () => {
testServer = await startTestServer();
testServer = await startTestServer({ port: TEST_PORT });
await new Promise(resolve => setTimeout(resolve, 1000));
});
@ -59,11 +73,11 @@ tap.test('Attachment Handling - Multiple file types', async (tools) => {
special: '∑∆≈'
}, null, 2);
// Minimal PNG (1x1 pixel transparent)
const pngBase64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==';
// Minimal PDF header
const pdfBase64 = 'JVBERi0xLjQKJcOkw7zDtsOVDQo=';
// Read real files from sample directory
const sampleImage = readFileAsBase64(path.join(SAMPLE_FILES_DIR, '003-pdflatex-image/image.jpg'));
const minimalPdf = readFileAsBase64(path.join(SAMPLE_FILES_DIR, '001-trivial/minimal-document.pdf'));
const multiPagePdf = readFileAsBase64(path.join(SAMPLE_FILES_DIR, '004-pdflatex-4-pages/pdflatex-4-pages.pdf'));
const pdfWithAttachment = readFileAsBase64(path.join(SAMPLE_FILES_DIR, '025-attachment/with-attachment.pdf'));
const email = [
`From: sender@example.com`,
@ -96,11 +110,11 @@ tap.test('Attachment Handling - Multiple file types', async (tools) => {
jsonAttachment,
'',
`--${boundary}`,
`Content-Type: image/png`,
`Content-Disposition: attachment; filename="image.png"`,
`Content-Type: image/jpeg`,
`Content-Disposition: attachment; filename="sample-image.jpg"`,
`Content-Transfer-Encoding: base64`,
'',
pngBase64,
sampleImage,
'',
`--${boundary}`,
`Content-Type: application/octet-stream`,
@ -130,10 +144,24 @@ tap.test('Attachment Handling - Multiple file types', async (tools) => {
'',
`--${boundary}`,
`Content-Type: application/pdf`,
`Content-Disposition: attachment; filename="document.pdf"`,
`Content-Disposition: attachment; filename="minimal-document.pdf"`,
`Content-Transfer-Encoding: base64`,
'',
pdfBase64,
minimalPdf,
'',
`--${boundary}`,
`Content-Type: application/pdf`,
`Content-Disposition: attachment; filename="multi-page-document.pdf"`,
`Content-Transfer-Encoding: base64`,
'',
multiPagePdf,
'',
`--${boundary}`,
`Content-Type: application/pdf`,
`Content-Disposition: attachment; filename="pdf-with-embedded-attachment.pdf"`,
`Content-Transfer-Encoding: base64`,
'',
pdfWithAttachment,
'',
`--${boundary}`,
`Content-Type: text/html; charset=utf-8`,
@ -149,7 +177,7 @@ tap.test('Attachment Handling - Multiple file types', async (tools) => {
''
].join('\r\n');
console.log('Sending email with 8 different attachment types');
console.log('Sending email with 10 different attachment types including real PDFs');
socket.write(email);
dataBuffer = '';
step = 'sent';
@ -212,9 +240,10 @@ tap.test('Attachment Handling - Large attachment', async (tools) => {
} else if (step === 'data' && dataBuffer.includes('354')) {
const boundary = 'large-attachment-boundary';
// Create a 100KB attachment
const largeData = 'A'.repeat(100000);
const largeBase64 = Buffer.from(largeData).toString('base64');
// Use a real large PDF file
const largePdf = readFileAsBase64(path.join(SAMPLE_FILES_DIR, '009-pdflatex-geotopo/GeoTopo.pdf'));
const largePdfSize = Buffer.from(largePdf, 'base64').length;
console.log(`Large PDF size: ${(largePdfSize / 1024).toFixed(2)}KB`);
const email = [
`From: sender@example.com`,
@ -231,18 +260,18 @@ tap.test('Attachment Handling - Large attachment', async (tools) => {
'This email contains a large attachment.',
'',
`--${boundary}`,
`Content-Type: application/octet-stream`,
`Content-Disposition: attachment; filename="large-file.dat"`,
`Content-Type: application/pdf`,
`Content-Disposition: attachment; filename="large-geotopo.pdf"`,
`Content-Transfer-Encoding: base64`,
'',
largeBase64,
largePdf,
'',
`--${boundary}--`,
'.',
''
].join('\r\n');
console.log('Sending email with 100KB attachment');
console.log(`Sending email with large PDF attachment (${(largePdfSize / 1024).toFixed(2)}KB)`);
socket.write(email);
dataBuffer = '';
step = 'sent';
@ -332,7 +361,7 @@ tap.test('Attachment Handling - Inline vs attachment disposition', async (tools)
`Content-Disposition: inline; filename="inline1.png"`,
`Content-Transfer-Encoding: base64`,
'',
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
readFileAsBase64(path.join(SAMPLE_FILES_DIR, '008-reportlab-inline-image/smile.png')) || 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
'',
`--${boundary}`,
`Content-Type: image/png`,
@ -340,14 +369,14 @@ tap.test('Attachment Handling - Inline vs attachment disposition', async (tools)
`Content-Disposition: inline; filename="inline2.png"`,
`Content-Transfer-Encoding: base64`,
'',
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==',
readFileAsBase64(path.join(SAMPLE_FILES_DIR, '019-grayscale-image/page-0-X0.png')) || 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==',
'',
`--${boundary}`,
`Content-Type: application/pdf`,
`Content-Disposition: attachment; filename="document.pdf"`,
`Content-Transfer-Encoding: base64`,
'',
'JVBERi0xLjQKJcOkw7zDtsOVDQo=',
readFileAsBase64(path.join(SAMPLE_FILES_DIR, '013-reportlab-overlay/reportlab-overlay.pdf')) || 'JVBERi0xLjQKJcOkw7zDtsOVDQo=',
'',
`--${boundary}--`,
'.',
@ -553,8 +582,8 @@ tap.test('Attachment Handling - Empty and malformed attachments', async (tools)
'Attachment without filename',
'',
`--${boundary}`,
`Content-Type: image/png`,
`Content-Disposition: attachment; filename="broken.png"`,
`Content-Type: application/pdf`,
`Content-Disposition: attachment; filename="broken.pdf"`,
`Content-Transfer-Encoding: base64`,
'',
'NOT-VALID-BASE64-@#$%', // Invalid base64
@ -595,7 +624,7 @@ tap.test('Attachment Handling - Empty and malformed attachments', async (tools)
});
tap.test('cleanup - stop test server', async () => {
await stopTestServer();
await stopTestServer(testServer);
});
tap.start();