import { tap, expect } from '@git.zone/tstest/tapbundle'; import * as plugins from '../plugins.js'; import * as net from 'net'; import { startTestServer, stopTestServer, TEST_PORT, sendEmailWithRawSocket } from '../server.loader.js'; import type { SmtpServer } from '../../../ts/mail/delivery/smtpserver/index.js'; let testServer: SmtpServer; tap.test('setup - start test server', async () => { testServer = await startTestServer(); await plugins.smartdelay.delayFor(1000); }); tap.test('Nested MIME Structures - should handle deeply nested multipart structure', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; socket.on('data', (data) => { dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (dataBuffer.includes('220 ')) { // Send EHLO socket.write('EHLO testclient\r\n'); } else if (dataBuffer.includes('250 ') && dataBuffer.includes('EHLO')) { // Send MAIL FROM socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('250 ') && dataBuffer.includes('sender accepted')) { // Send RCPT TO socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('250 ') && dataBuffer.includes('recipient accepted')) { // Send DATA socket.write('DATA\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('354 ')) { // Create deeply nested MIME structure (4 levels) const outerBoundary = '----=_Outer_Boundary_' + Date.now(); const middleBoundary = '----=_Middle_Boundary_' + Date.now(); const innerBoundary = '----=_Inner_Boundary_' + Date.now(); const deepBoundary = '----=_Deep_Boundary_' + Date.now(); let emailContent = [ 'Subject: Deeply Nested MIME Structure Test', 'From: sender@example.com', 'To: recipient@example.com', 'MIME-Version: 1.0', `Content-Type: multipart/mixed; boundary="${outerBoundary}"`, '', 'This is a multipart message with deeply nested structure.', '', // Level 1: Outer boundary `--${outerBoundary}`, 'Content-Type: text/plain', '', 'This is the first part at the outer level.', '', `--${outerBoundary}`, `Content-Type: multipart/alternative; boundary="${middleBoundary}"`, '', // Level 2: Middle boundary `--${middleBoundary}`, 'Content-Type: text/plain', '', 'Alternative plain text version.', '', `--${middleBoundary}`, `Content-Type: multipart/related; boundary="${innerBoundary}"`, '', // Level 3: Inner boundary `--${innerBoundary}`, 'Content-Type: text/html', '', '

HTML with related content

', '', `--${innerBoundary}`, 'Content-Type: image/png', 'Content-ID: ', 'Content-Transfer-Encoding: base64', '', 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==', '', `--${innerBoundary}`, `Content-Type: multipart/mixed; boundary="${deepBoundary}"`, '', // Level 4: Deep boundary `--${deepBoundary}`, 'Content-Type: application/octet-stream', 'Content-Disposition: attachment; filename="data.bin"', '', 'Binary data simulation', '', `--${deepBoundary}`, 'Content-Type: message/rfc822', '', 'Subject: Embedded Message', 'From: embedded@example.com', 'To: recipient@example.com', '', 'This is an embedded email message.', '', `--${deepBoundary}--`, '', `--${innerBoundary}--`, '', `--${middleBoundary}--`, '', `--${outerBoundary}`, 'Content-Type: application/pdf', 'Content-Disposition: attachment; filename="document.pdf"', '', 'PDF document data simulation', '', `--${outerBoundary}--`, '.', '' ].join('\r\n'); console.log('Sending email with 4-level nested MIME structure'); socket.write(emailContent); dataBuffer = ''; } else if (dataBuffer.includes('250 ') && dataBuffer.includes('Message accepted') || dataBuffer.includes('552 ') || dataBuffer.includes('554 ') || dataBuffer.includes('500 ')) { // Either accepted or gracefully rejected const accepted = dataBuffer.includes('250 '); console.log(`Nested MIME structure test ${accepted ? 'accepted' : 'rejected'}`); socket.write('QUIT\r\n'); socket.end(); done.resolve(); } }); socket.on('error', (err) => { console.error('Socket error:', err); done.reject(err); }); socket.on('timeout', () => { console.error('Socket timeout'); socket.destroy(); done.reject(new Error('Socket timeout')); }); await done.promise; }); tap.test('Nested MIME Structures - should handle circular references in multipart structure', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; socket.on('data', (data) => { dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (dataBuffer.includes('220 ')) { socket.write('EHLO testclient\r\n'); } else if (dataBuffer.includes('250 ') && dataBuffer.includes('EHLO')) { socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('250 ') && dataBuffer.includes('sender accepted')) { socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('250 ') && dataBuffer.includes('recipient accepted')) { socket.write('DATA\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('354 ')) { // Create structure with references between parts const boundary1 = '----=_Boundary1_' + Date.now(); const boundary2 = '----=_Boundary2_' + Date.now(); let emailContent = [ 'Subject: Multipart with Cross-References', 'From: sender@example.com', 'To: recipient@example.com', 'MIME-Version: 1.0', `Content-Type: multipart/related; boundary="${boundary1}"`, '', `--${boundary1}`, `Content-Type: multipart/alternative; boundary="${boundary2}"`, 'Content-ID: ', '', `--${boundary2}`, 'Content-Type: text/html', '', 'See related part: Link', '', `--${boundary2}`, 'Content-Type: text/plain', '', 'Plain text with reference to part2', '', `--${boundary2}--`, '', `--${boundary1}`, 'Content-Type: application/xml', 'Content-ID: ', '', '', '', `--${boundary1}--`, '.', '' ].join('\r\n'); socket.write(emailContent); dataBuffer = ''; } else if (dataBuffer.includes('250 ') && dataBuffer.includes('Message accepted') || dataBuffer.includes('552 ') || dataBuffer.includes('554 ') || dataBuffer.includes('500 ')) { const accepted = dataBuffer.includes('250 '); console.log(`Cross-reference test ${accepted ? 'accepted' : 'rejected'}`); socket.write('QUIT\r\n'); socket.end(); done.resolve(); } }); socket.on('error', (err) => { console.error('Socket error:', err); done.reject(err); }); socket.on('timeout', () => { console.error('Socket timeout'); socket.destroy(); done.reject(new Error('Socket timeout')); }); await done.promise; }); tap.test('Nested MIME Structures - should handle mixed nesting with various encodings', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; socket.on('data', (data) => { dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (dataBuffer.includes('220 ')) { socket.write('EHLO testclient\r\n'); } else if (dataBuffer.includes('250 ') && dataBuffer.includes('EHLO')) { socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('250 ') && dataBuffer.includes('sender accepted')) { socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('250 ') && dataBuffer.includes('recipient accepted')) { socket.write('DATA\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('354 ')) { // Create structure with various encodings const boundary1 = '----=_Encoding_Outer_' + Date.now(); const boundary2 = '----=_Encoding_Inner_' + Date.now(); let emailContent = [ 'Subject: Mixed Encodings in Nested Structure', 'From: sender@example.com', 'To: recipient@example.com', 'MIME-Version: 1.0', `Content-Type: multipart/mixed; boundary="${boundary1}"`, '', `--${boundary1}`, 'Content-Type: text/plain; charset="utf-8"', 'Content-Transfer-Encoding: quoted-printable', '', 'This is quoted-printable encoded: =C3=A9=C3=A8=C3=AA', '', `--${boundary1}`, `Content-Type: multipart/alternative; boundary="${boundary2}"`, '', `--${boundary2}`, 'Content-Type: text/plain; charset="iso-8859-1"', 'Content-Transfer-Encoding: 8bit', '', 'Text with 8-bit characters: ñáéíóú', '', `--${boundary2}`, 'Content-Type: text/html; charset="utf-16"', 'Content-Transfer-Encoding: base64', '', '//48AGgAdABtAGwAPgA8AGIAbwBkAHkAPgBVAFQARgAtADEANgAgAHQAZQB4AHQAPAAvAGIAbwBkAHkAPgA8AC8AaAB0AG0AbAA+', '', `--${boundary2}--`, '', `--${boundary1}`, 'Content-Type: application/octet-stream', 'Content-Transfer-Encoding: base64', 'Content-Disposition: attachment; filename="binary.dat"', '', 'VGhpcyBpcyBiaW5hcnkgZGF0YQ==', '', `--${boundary1}--`, '.', '' ].join('\r\n'); socket.write(emailContent); dataBuffer = ''; } else if (dataBuffer.includes('250 ') && dataBuffer.includes('Message accepted') || dataBuffer.includes('552 ') || dataBuffer.includes('554 ') || dataBuffer.includes('500 ')) { const accepted = dataBuffer.includes('250 '); console.log(`Mixed encodings test ${accepted ? 'accepted' : 'rejected'}`); socket.write('QUIT\r\n'); socket.end(); done.resolve(); } }); socket.on('error', (err) => { console.error('Socket error:', err); done.reject(err); }); socket.on('timeout', () => { console.error('Socket timeout'); socket.destroy(); done.reject(new Error('Socket timeout')); }); await done.promise; }); tap.test('cleanup - stop test server', async () => { await stopTestServer(testServer); }); tap.start();