import { tap, expect } from '@push.rocks/tapbundle'; import * as net from 'net'; import { startTestServer, stopTestServer, TEST_PORT, sendEmailWithRawSocket } from '../server.loader.js'; let testServer: any; tap.test('setup - start test server', async () => { testServer = await startTestServer(); await new Promise(resolve => setTimeout(resolve, 1000)); }); tap.test('Special Character Handling - Comprehensive Unicode test', 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: Special Character Test - Unicode & Symbols ñáéíóú`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, `MIME-Version: 1.0`, `Content-Type: text/plain; charset=utf-8`, `Content-Transfer-Encoding: 8bit`, '', 'This email tests special character handling:', '', '=== UNICODE CHARACTERS ===', 'Accented letters: àáâãäåæçèéêëìíîïñòóôõöøùúûüý', 'German umlauts: äöüÄÖÜß', 'Scandinavian: åäöÅÄÖ', 'French: àâéèêëïîôœùûüÿç', 'Spanish: ñáéíóúü¿¡', 'Polish: ąćęłńóśźż', 'Russian: абвгдеёжзийклмнопрстуфхцчшщъыьэюя', 'Greek: αβγδεζηθικλμνξοπρστυφχψω', 'Arabic: العربية', 'Hebrew: עברית', 'Chinese: 中文测试', 'Japanese: 日本語テスト', 'Korean: 한국어 테스트', 'Thai: ภาษาไทย', '', '=== MATHEMATICAL SYMBOLS ===', 'Math: ∑∏∫∆∇∂∞±×÷≠≤≥≈∝∪∩⊂⊃∈∀∃', 'Greek letters: αβγδεζηθικλμνξοπρστυφχψω', 'Arrows: ←→↑↓↔↕⇐⇒⇑⇓⇔⇕', '', '=== CURRENCY & SYMBOLS ===', 'Currency: $€£¥¢₹₽₩₪₫₨₦₡₵₴₸₼₲₱', 'Symbols: ©®™§¶†‡•…‰‱°℃℉№', 'Punctuation: «»""''‚„‹›–—―‖‗''""‚„…‰′″‴‵‶‷‸‹›※‼‽⁇⁈⁉⁏⁐⁑⁒⁓⁔⁕⁖⁗⁘⁙⁚⁛⁜⁝⁞', '', '=== EMOJI & SYMBOLS ===', 'Common: ☀☁☂☃☄★☆☇☈☉☊☋☌☍☎☏☐☑☒☓☔☕☖☗☘☙☚☛☜☝☞☟☠☡☢☣☤☥☦☧☨☩☪☫☬☭☮☯☰☱☲☳☴☵☶☷', 'Smileys: ☺☻☹☿♀♁♂♃♄♅♆♇', 'Hearts: ♡♢♣♤♥♦♧♨♩♪♫♬♭♮♯', '', '=== SPECIAL FORMATTING ===', 'Zero-width chars: ​‌‍‎‏', 'Combining: e̊åa̋o̧ç', 'Ligatures: fffiflffifflſtst', 'Fractions: ½⅓⅔¼¾⅛⅜⅝⅞', 'Superscript: ⁰¹²³⁴⁵⁶⁷⁸⁹', 'Subscript: ₀₁₂₃₄₅₆₇₈₉', '', 'End of special character test.', '.', '' ].join('\r\n'); console.log('Sending email with comprehensive Unicode characters'); 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 special characters accepted successfully'); expect(true).toBeTrue(); 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('Special Character Handling - Control characters', 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: Control Character Test`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, `MIME-Version: 1.0`, `Content-Type: text/plain; charset=utf-8`, '', '=== CONTROL CHARACTERS TEST ===', 'Tab character: (between words)', 'Non-breaking space: word word', 'Soft hyphen: super­cali­fragi­listic­expi­ali­docious', 'Vertical tab: word\x0Bword', 'Form feed: word\x0Cword', 'Backspace: word\x08word', '', '=== LINE ENDING TESTS ===', 'Unix LF: Line1\nLine2', 'Windows CRLF: Line3\r\nLine4', 'Mac CR: Line5\rLine6', '', '=== BOUNDARY CHARACTERS ===', 'SMTP boundary test: . (dot at start)', 'Double dots: .. (escaped in SMTP)', 'CRLF.CRLF sequence test', '.', '' ].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 control characters accepted'); expect(true).toBeTrue(); 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('Special Character Handling - Subject header 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?B?8J+YgCBFbW9qaSBpbiBTdWJqZWN0IOKcqCDwn4yI?=`, `Subject: =?UTF-8?Q?Quoted=2DPrintable=20Subject=20=C3=A1=C3=A9=C3=AD=C3=B3=C3=BA?=`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, '', 'Testing encoded subject headers with special characters.', '.', '' ].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 encoded subject headers accepted'); expect(true).toBeTrue(); 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('Special Character Handling - Address headers with special chars', 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: "José García" `, `To: "François Müller" , "北京用户" `, `Cc: =?UTF-8?B?IkFubmEgw4XDpMO2Ig==?= `, `Reply-To: "Søren Ñoño" `, `Subject: Special names in address headers`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, '', 'Testing special characters in email addresses and display names.', '.', '' ].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 special characters in addresses accepted'); expect(true).toBeTrue(); 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('Special Character Handling - Mixed encodings', 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 = 'mixed-encoding-boundary'; const email = [ `From: sender@example.com`, `To: recipient@example.com`, `Subject: Mixed 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: 8bit`, '', 'UTF-8 part: ñáéíóú 中文 日本語', '', `--${boundary}`, `Content-Type: text/plain; charset=iso-8859-1`, `Content-Transfer-Encoding: quoted-printable`, '', 'ISO-8859-1 part: =F1=E1=E9=ED=F3=FA', '', `--${boundary}`, `Content-Type: text/plain; charset=windows-1252`, '', 'Windows-1252 part: €‚ƒ„…†‡', '', `--${boundary}`, `Content-Type: text/plain; charset=utf-16`, `Content-Transfer-Encoding: base64`, '', Buffer.from('UTF-16 text: ñoño', 'utf16le').toString('base64'), '', `--${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 mixed character encodings accepted'); expect(true).toBeTrue(); 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(); }); tap.start();