import { tap, expect } from '@git.zone/tstest/tapbundle'; import * as net from 'net'; import { startTestServer, stopTestServer } from '../../helpers/server.loader.js' import type { ITestServer } from '../../helpers/server.loader.js'; const TEST_PORT = 2525; let testServer: ITestServer; tap.test('setup - start test server', async () => { testServer = await startTestServer({ port: TEST_PORT }); await new Promise(resolve => setTimeout(resolve, 1000)); }); tap.test('MIME Handling - Comprehensive multipart message', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; let step = 'greeting'; let completed = false; socket.on('data', (data) => { dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO testclient\r\n'); dataBuffer = ''; } else if (step === 'ehlo' && dataBuffer.includes('250')) { step = 'mail'; socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (step === 'mail' && dataBuffer.includes('250')) { step = 'rcpt'; socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (step === 'rcpt' && dataBuffer.includes('250')) { step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } else if (step === 'data' && dataBuffer.includes('354')) { // Create comprehensive MIME test email const boundary = 'mime-test-boundary-12345'; const innerBoundary = 'inner-mime-boundary-67890'; const email = [ `From: sender@example.com`, `To: recipient@example.com`, `Subject: MIME Handling Test - Comprehensive`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, `MIME-Version: 1.0`, `Content-Type: multipart/mixed; boundary="${boundary}"`, '', 'This is a multi-part message in MIME format.', '', `--${boundary}`, `Content-Type: text/plain; charset=utf-8`, `Content-Transfer-Encoding: 7bit`, '', 'This is the plain text part of the email.', 'It tests basic MIME text handling.', '', `--${boundary}`, `Content-Type: text/html; charset=utf-8`, `Content-Transfer-Encoding: quoted-printable`, '', '', 'MIME Test', '', '

HTML MIME Content

', '

This tests HTML MIME content handling.

', '

Special chars: =E2=98=85 =E2=9C=93 =E2=9D=A4

', '', '', '', `--${boundary}`, `Content-Type: multipart/alternative; boundary="${innerBoundary}"`, '', `--${innerBoundary}`, `Content-Type: text/plain; charset=iso-8859-1`, `Content-Transfer-Encoding: base64`, '', 'VGhpcyBpcyBiYXNlNjQgZW5jb2RlZCB0ZXh0IGNvbnRlbnQu', '', `--${innerBoundary}`, `Content-Type: application/json; charset=utf-8`, '', '{"message": "JSON MIME content", "test": true, "special": "àáâãäå"}', '', `--${innerBoundary}--`, '', `--${boundary}`, `Content-Type: image/png`, `Content-Disposition: attachment; filename="test.png"`, `Content-Transfer-Encoding: base64`, '', 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==', '', `--${boundary}`, `Content-Type: text/csv`, `Content-Disposition: attachment; filename="data.csv"`, '', 'Name,Age,Email', 'John,25,john@example.com', 'Jane,30,jane@example.com', '', `--${boundary}`, `Content-Type: application/pdf`, `Content-Disposition: attachment; filename="document.pdf"`, `Content-Transfer-Encoding: base64`, '', 'JVBERi0xLjQKJcOkw7zDtsOVDQo=', '', `--${boundary}--`, '.', '' ].join('\r\n'); console.log('Sending comprehensive MIME email with multiple parts and encodings'); socket.write(email); step = 'sent'; dataBuffer = ''; } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) { if (!completed) { completed = true; console.log('Complex MIME message accepted successfully'); expect(true).toEqual(true); socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } }); socket.on('error', (err) => { console.error('Socket error:', err); done.reject(err); }); await done.promise; }); tap.test('MIME Handling - Quoted-printable encoding', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; let step = 'greeting'; let completed = false; socket.on('data', (data) => { dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO testclient\r\n'); dataBuffer = ''; } else if (step === 'ehlo' && dataBuffer.includes('250')) { step = 'mail'; socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (step === 'mail' && dataBuffer.includes('250')) { step = 'rcpt'; socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (step === 'rcpt' && dataBuffer.includes('250')) { step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } else if (step === 'data' && dataBuffer.includes('354')) { const email = [ `From: sender@example.com`, `To: recipient@example.com`, `Subject: =?UTF-8?Q?Quoted=2DPrintable=20Test=20=F0=9F=8C=9F?=`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, `MIME-Version: 1.0`, `Content-Type: text/plain; charset=utf-8`, `Content-Transfer-Encoding: quoted-printable`, '', 'This is a test of quoted-printable encoding.', 'Special characters: =C3=A9 =C3=A8 =C3=AA =C3=AB', 'Long line that needs to be wrapped with soft line breaks at 76 character=', 's per line to comply with MIME standards for quoted-printable encoding.', 'Emoji: =F0=9F=98=80 =F0=9F=91=8D =F0=9F=8C=9F', '.', '' ].join('\r\n'); socket.write(email); step = 'sent'; dataBuffer = ''; } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) { if (!completed) { completed = true; console.log('Quoted-printable encoded email accepted'); expect(true).toEqual(true); socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } }); socket.on('error', (err) => { console.error('Socket error:', err); done.reject(err); }); await done.promise; }); tap.test('MIME Handling - Base64 encoding', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; let step = 'greeting'; let completed = false; socket.on('data', (data) => { dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO testclient\r\n'); dataBuffer = ''; } else if (step === 'ehlo' && dataBuffer.includes('250')) { step = 'mail'; socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (step === 'mail' && dataBuffer.includes('250')) { step = 'rcpt'; socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (step === 'rcpt' && dataBuffer.includes('250')) { step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } else if (step === 'data' && dataBuffer.includes('354')) { const boundary = 'base64-test-boundary'; const textContent = 'This is a test of base64 encoding with various content types.\nSpecial chars: éèêë\nEmoji: 😀 👍 🌟'; const base64Content = Buffer.from(textContent).toString('base64'); const email = [ `From: sender@example.com`, `To: recipient@example.com`, `Subject: Base64 Encoding Test`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, `MIME-Version: 1.0`, `Content-Type: multipart/mixed; boundary="${boundary}"`, '', `--${boundary}`, `Content-Type: text/plain; charset=utf-8`, `Content-Transfer-Encoding: base64`, '', base64Content, '', `--${boundary}`, `Content-Type: application/octet-stream`, `Content-Disposition: attachment; filename="binary.dat"`, `Content-Transfer-Encoding: base64`, '', 'VGhpcyBpcyBiaW5hcnkgZGF0YSBmb3IgdGVzdGluZw==', '', `--${boundary}--`, '.', '' ].join('\r\n'); socket.write(email); step = 'sent'; dataBuffer = ''; } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) { if (!completed) { completed = true; console.log('Base64 encoded email accepted'); expect(true).toEqual(true); socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } }); socket.on('error', (err) => { console.error('Socket error:', err); done.reject(err); }); await done.promise; }); tap.test('MIME Handling - Content-Disposition headers', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; let step = 'greeting'; let completed = false; socket.on('data', (data) => { dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO testclient\r\n'); dataBuffer = ''; } else if (step === 'ehlo' && dataBuffer.includes('250')) { step = 'mail'; socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (step === 'mail' && dataBuffer.includes('250')) { step = 'rcpt'; socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (step === 'rcpt' && dataBuffer.includes('250')) { step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } else if (step === 'data' && dataBuffer.includes('354')) { const boundary = 'disposition-test-boundary'; const email = [ `From: sender@example.com`, `To: recipient@example.com`, `Subject: Content-Disposition Test`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, `MIME-Version: 1.0`, `Content-Type: multipart/mixed; boundary="${boundary}"`, '', `--${boundary}`, `Content-Type: text/plain`, `Content-Disposition: inline`, '', 'This is inline text content.', '', `--${boundary}`, `Content-Type: image/jpeg`, `Content-Disposition: attachment; filename="photo.jpg"`, `Content-Transfer-Encoding: base64`, '', '/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAEBAQ==', '', `--${boundary}`, `Content-Type: application/pdf`, `Content-Disposition: attachment; filename="report.pdf"; size=1234`, `Content-Description: Monthly Report`, '', 'PDF content here', '', `--${boundary}`, `Content-Type: text/html`, `Content-Disposition: inline; filename="content.html"`, '', 'Inline HTML content', '', `--${boundary}--`, '.', '' ].join('\r\n'); socket.write(email); step = 'sent'; dataBuffer = ''; } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) { if (!completed) { completed = true; console.log('Email with various Content-Disposition headers accepted'); expect(true).toEqual(true); socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } }); socket.on('error', (err) => { console.error('Socket error:', err); done.reject(err); }); await done.promise; }); tap.test('MIME Handling - International character sets', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; let step = 'greeting'; let completed = false; socket.on('data', (data) => { dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO testclient\r\n'); dataBuffer = ''; } else if (step === 'ehlo' && dataBuffer.includes('250')) { step = 'mail'; socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (step === 'mail' && dataBuffer.includes('250')) { step = 'rcpt'; socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (step === 'rcpt' && dataBuffer.includes('250')) { step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } else if (step === 'data' && dataBuffer.includes('354')) { const boundary = 'intl-charset-boundary'; const email = [ `From: sender@example.com`, `To: recipient@example.com`, `Subject: International Character Sets`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, `MIME-Version: 1.0`, `Content-Type: multipart/mixed; boundary="${boundary}"`, '', `--${boundary}`, `Content-Type: text/plain; charset=utf-8`, '', 'UTF-8: Français, Español, Deutsch, 中文, 日本語, 한국어, العربية', '', `--${boundary}`, `Content-Type: text/plain; charset=iso-8859-1`, '', 'ISO-8859-1: Français, Español, Português', '', `--${boundary}`, `Content-Type: text/plain; charset=windows-1252`, '', 'Windows-1252: Special chars: €‚ƒ„…†‡', '', `--${boundary}`, `Content-Type: text/plain; charset=shift_jis`, '', 'Shift-JIS: Japanese text', '', `--${boundary}--`, '.', '' ].join('\r\n'); socket.write(email); step = 'sent'; dataBuffer = ''; } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) { if (!completed) { completed = true; console.log('Email with international character sets accepted'); expect(true).toEqual(true); socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } }); socket.on('error', (err) => { console.error('Socket error:', err); done.reject(err); }); await done.promise; }); tap.test('cleanup - stop test server', async () => { await stopTestServer(testServer); }); export default tap.start();