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 '../../helpers/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('IP Reputation - Suspicious hostname in EHLO', 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 ')) { // Use suspicious hostname socket.write('EHLO suspicious-host.badreputation.com\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('250') || dataBuffer.includes('550') || dataBuffer.includes('521')) { const accepted = dataBuffer.includes('250'); const rejected = dataBuffer.includes('550') || dataBuffer.includes('521'); console.log(`Suspicious hostname: accepted=${accepted}, rejected=${rejected}`); expect(accepted || rejected).toEqual(true); if (rejected) { console.log('IP reputation check working - suspicious host rejected at EHLO'); } 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('IP Reputation - Blacklisted sender domain', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; let step = 'greeting'; 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'; // Use known spam/blacklisted domain socket.write('MAIL FROM:\r\n'); dataBuffer = ''; } else if (step === 'mail') { if (dataBuffer.includes('250')) { console.log('Blacklisted sender accepted at MAIL FROM'); step = 'rcpt'; socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('550') || dataBuffer.includes('553')) { console.log('Blacklisted sender rejected - IP reputation check working'); expect(true).toEqual(true); socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } else if (step === 'rcpt') { const accepted = dataBuffer.includes('250'); const rejected = dataBuffer.includes('550') || dataBuffer.includes('553'); console.log(`Blacklisted domain at RCPT: accepted=${accepted}, rejected=${rejected}`); expect(accepted || rejected).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('IP Reputation - Known good sender', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; let step = 'greeting'; 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'; // Use legitimate sender 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')) { console.log('Good sender accepted - IP reputation allows legitimate senders'); 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('IP Reputation - Multiple connections from same IP', async (tools) => { const done = tools.defer(); const connections: net.Socket[] = []; let completedConnections = 0; const totalConnections = 3; // Create multiple connections rapidly for (let i = 0; i < totalConnections; i++) { const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); connections.push(socket); socket.on('data', (data) => { const response = data.toString(); console.log(`Connection ${i + 1} response:`, response); if (response.includes('220')) { socket.write('EHLO testclient\r\n'); } else if (response.includes('250')) { socket.write('QUIT\r\n'); socket.end(); } else if (response.includes('421') || response.includes('550')) { // Connection rejected due to rate limiting or reputation console.log(`Connection ${i + 1} rejected - IP reputation/rate limiting active`); socket.end(); } }); socket.on('close', () => { completedConnections++; if (completedConnections === totalConnections) { console.log('All connections completed'); expect(true).toEqual(true); done.resolve(); } }); socket.on('error', (err) => { console.error(`Connection ${i + 1} error:`, err.message); completedConnections++; if (completedConnections === totalConnections) { done.resolve(); } }); // Small delay between connections if (i < totalConnections - 1) { await plugins.smartdelay.delayFor(100); } } await done.promise; }); tap.test('IP Reputation - Suspicious patterns in email', async (tools) => { const done = tools.defer(); const socket = net.createConnection({ host: 'localhost', port: TEST_PORT, timeout: 30000 }); let dataBuffer = ''; let step = 'greeting'; 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'; // Multiple recipients (spam pattern) socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (step === 'rcpt' && dataBuffer.includes('250')) { step = 'rcpt2'; socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (step === 'rcpt2' && dataBuffer.includes('250')) { step = 'rcpt3'; socket.write('RCPT TO:\r\n'); dataBuffer = ''; } else if (step === 'rcpt3') { if (dataBuffer.includes('250')) { step = 'data'; socket.write('DATA\r\n'); dataBuffer = ''; } else if (dataBuffer.includes('452') || dataBuffer.includes('550')) { console.log('Multiple recipients limited - reputation control active'); expect(true).toEqual(true); socket.write('QUIT\r\n'); socket.end(); done.resolve(); } } else if (step === 'data' && dataBuffer.includes('354')) { // Email with spam-like content const email = [ `From: sender@example.com`, `To: recipient1@example.com, recipient2@example.com, recipient3@example.com`, `Subject: URGENT!!! You've won $1,000,000!!!`, `Date: ${new Date().toUTCString()}`, `Message-ID: `, '', 'CLICK HERE NOW!!! Limited time offer!!!', 'Visit http://suspicious-link.com/win-money', 'Act NOW before it\'s too late!!!', '.', '' ].join('\r\n'); socket.write(email); dataBuffer = ''; } else if (dataBuffer.includes('250 ') || dataBuffer.includes('550 ')) { const result = dataBuffer.includes('250') ? 'accepted' : 'rejected'; console.log(`Suspicious content email ${result}`); 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); }); tap.start();