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('Email Routing - Local domain routing', 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) => { if (completed) return; dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO localhost\r\n'); dataBuffer = ''; } else if (step === 'ehlo' && dataBuffer.includes('250')) { step = 'mail'; // Local sender socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (step === 'mail' && dataBuffer.includes('250')) { step = 'rcpt'; // Local recipient socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (step === 'rcpt') { const accepted = dataBuffer.includes('250'); console.log(`Local domain routing: ${accepted ? 'accepted' : 'rejected'}`); if (accepted) { step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } else { socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } else if (step === 'data' && dataBuffer.includes('354')) { const email = [ `From: test@example.com`, `To: local@localhost`, `Subject: Local Domain Routing Test`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, '', 'This email tests local domain routing.', 'The server should route this email locally.', '.', '' ].join('\r\n'); socket.write(email); dataBuffer = ''; step = 'sent'; } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) { if (!completed) { completed = true; console.log('Local domain email routed 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('Email Routing - External domain routing', 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) => { if (completed) return; dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO localhost\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'; // External recipient socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (step === 'rcpt') { const accepted = dataBuffer.includes('250'); console.log(`External domain routing: ${accepted ? 'accepted' : 'rejected'}`); if (accepted) { step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } else { socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } else if (step === 'data' && dataBuffer.includes('354')) { const email = [ `From: sender@example.com`, `To: recipient@external.com`, `Subject: External Domain Routing Test`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, '', 'This email tests external domain routing.', 'The server should accept this for relay.', '.', '' ].join('\r\n'); socket.write(email); dataBuffer = ''; step = 'sent'; } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) { if (!completed) { completed = true; console.log('External domain email accepted for relay'); 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('Email Routing - Multiple recipients', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; let step = 'greeting'; let recipientCount = 0; const totalRecipients = 5; let completed = false; socket.on('data', (data) => { if (completed) return; dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO localhost\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'; recipientCount++; socket.write(`RCPT TO:\r\n`); dataBuffer = ''; } else if (step === 'rcpt' && dataBuffer.includes('250')) { if (recipientCount < totalRecipients) { recipientCount++; socket.write(`RCPT TO:\r\n`); dataBuffer = ''; } else { console.log(`All ${totalRecipients} recipients accepted`); step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } } else if (step === 'data' && dataBuffer.includes('354')) { const recipients = Array.from({length: totalRecipients}, (_, i) => `recipient${i+1}@example.com`); const email = [ `From: sender@example.com`, `To: ${recipients.join(', ')}`, `Subject: Multiple Recipients Routing Test`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, '', 'This email tests routing to multiple recipients.', `Total recipients: ${totalRecipients}`, '.', '' ].join('\r\n'); socket.write(email); dataBuffer = ''; step = 'sent'; } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) { if (!completed) { completed = true; console.log('Email with multiple recipients routed 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('Email Routing - Invalid domain handling', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; let step = 'greeting'; let testType = 'invalid-tld'; const testCases = [ { email: 'user@invalid-tld', type: 'invalid-tld' }, { email: 'user@.com', type: 'missing-domain' }, { email: 'user@domain..com', type: 'double-dot' }, { email: 'user@-domain.com', type: 'leading-dash' }, { email: 'user@domain-.com', type: 'trailing-dash' } ]; let currentTest = 0; socket.on('data', (data) => { dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO localhost\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'; testType = testCases[currentTest].type; socket.write(`RCPT TO:<${testCases[currentTest].email}>\r\n`); dataBuffer = ''; } else if (step === 'rcpt') { const rejected = dataBuffer.includes('550') || dataBuffer.includes('553') || dataBuffer.includes('501'); console.log(`Invalid domain test (${testType}): ${rejected ? 'properly rejected' : 'unexpectedly accepted'}`); currentTest++; if (currentTest < testCases.length) { // Reset for next test socket.write('RSET\r\n'); step = 'rset'; dataBuffer = ''; } else { socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } else if (step === 'rset' && dataBuffer.includes('250')) { step = 'mail'; socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } }); socket.on('error', (err) => { console.error('Socket error:', err); done.reject(err); }); await done.promise; }); tap.test('Email Routing - Mixed local and external recipients', 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; const recipients = [ 'local@localhost', 'external@example.com', 'another@localhost', 'remote@external.com' ]; let currentRecipient = 0; let acceptedRecipients: string[] = []; socket.on('data', (data) => { if (completed) return; dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO localhost\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:<${recipients[currentRecipient]}>\r\n`); dataBuffer = ''; } else if (step === 'rcpt') { if (dataBuffer.includes('250')) { acceptedRecipients.push(recipients[currentRecipient]); console.log(`Recipient ${recipients[currentRecipient]} accepted`); } else { console.log(`Recipient ${recipients[currentRecipient]} rejected`); } currentRecipient++; if (currentRecipient < recipients.length) { socket.write(`RCPT TO:<${recipients[currentRecipient]}>\r\n`); dataBuffer = ''; } else if (acceptedRecipients.length > 0) { step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } else { socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } else if (step === 'data' && dataBuffer.includes('354')) { const email = [ `From: sender@example.com`, `To: ${acceptedRecipients.join(', ')}`, `Subject: Mixed Recipients Routing Test`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, '', 'This email tests routing to mixed local and external recipients.', `Accepted recipients: ${acceptedRecipients.length}`, '.', '' ].join('\r\n'); socket.write(email); dataBuffer = ''; step = 'sent'; } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) { if (!completed) { completed = true; console.log('Email with mixed recipients routed successfully'); expect(acceptedRecipients.length).toBeGreaterThan(0); 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('Email Routing - Subdomain routing', 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; const subdomainTests = [ 'user@mail.example.com', 'user@smtp.corp.example.com', 'user@deep.sub.domain.example.com' ]; let currentTest = 0; socket.on('data', (data) => { if (completed) return; dataBuffer += data.toString(); console.log('Server response:', data.toString()); if (step === 'greeting' && dataBuffer.includes('220 ')) { step = 'ehlo'; socket.write('EHLO localhost\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:<${subdomainTests[currentTest]}>\r\n`); dataBuffer = ''; } else if (step === 'rcpt') { const accepted = dataBuffer.includes('250'); console.log(`Subdomain routing test (${subdomainTests[currentTest]}): ${accepted ? 'accepted' : 'rejected'}`); currentTest++; if (currentTest < subdomainTests.length) { socket.write('RSET\r\n'); step = 'rset'; dataBuffer = ''; } else { step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } } else if (step === 'rset' && dataBuffer.includes('250')) { step = 'mail'; socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (step === 'data' && dataBuffer.includes('354')) { const email = [ `From: sender@example.com`, `To: ${subdomainTests[subdomainTests.length - 1]}`, `Subject: Subdomain Routing Test`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, '', 'This email tests subdomain routing.', '.', '' ].join('\r\n'); socket.write(email); dataBuffer = ''; step = 'sent'; } else if (step === 'sent' && dataBuffer.includes('250 ') && dataBuffer.includes('message queued')) { if (!completed) { completed = true; console.log('Subdomain routing test completed'); 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();