import { expect, tap } from '@git.zone/tstest/tapbundle'; import { EmailRouter, type IEmailRoute, type IEmailContext } from '../ts/mail/routing/index.js'; import { Email } from '../ts/mail/core/classes.email.js'; tap.test('EmailRouter - should create and manage routes', async () => { const router = new EmailRouter([]); // Test initial state expect(router.getRoutes()).toEqual([]); // Add some test routes const routes: IEmailRoute[] = [ { name: 'forward-example', priority: 10, match: { recipients: '*@example.com' }, action: { type: 'forward', forward: { host: 'mail.example.com', port: 25 } } }, { name: 'reject-spam', priority: 20, match: { senders: '*@spammer.com' }, action: { type: 'reject', reject: { code: 550, message: 'Spam not allowed' } } } ]; router.updateRoutes(routes); expect(router.getRoutes().length).toEqual(2); }); tap.test('EmailRouter - should evaluate routes based on priority', async () => { const router = new EmailRouter([]); const routes: IEmailRoute[] = [ { name: 'low-priority', priority: 5, match: { recipients: '*@test.com' }, action: { type: 'deliver' } }, { name: 'high-priority', priority: 10, match: { recipients: 'admin@test.com' }, action: { type: 'process', process: { scan: true } } } ]; router.updateRoutes(routes); // Create test context const email = new Email({ from: 'sender@example.com', to: 'admin@test.com', subject: 'Test email', text: 'Test email content' }); const context: IEmailContext = { email, session: { id: 'test-session', remoteAddress: '192.168.1.1', matchedRoute: null } as any }; const route = await router.evaluateRoutes(context); expect(route).not.toEqual(null); expect(route?.name).toEqual('high-priority'); }); tap.test('EmailRouter - should match recipient patterns', async () => { const router = new EmailRouter([]); const routes: IEmailRoute[] = [ { name: 'exact-match', match: { recipients: 'admin@example.com' }, action: { type: 'forward', forward: { host: 'admin-server.com', port: 25 } } }, { name: 'wildcard-match', match: { recipients: '*@example.com' }, action: { type: 'deliver' } } ]; router.updateRoutes(routes); // Test exact match const email1 = new Email({ from: 'sender@test.com', to: 'admin@example.com', subject: 'Admin email', text: 'Admin email content' }); const context1: IEmailContext = { email: email1, session: { id: 'test1', remoteAddress: '10.0.0.1' } as any }; const route1 = await router.evaluateRoutes(context1); expect(route1?.name).toEqual('exact-match'); // Test wildcard match const email2 = new Email({ from: 'sender@test.com', to: 'user@example.com', subject: 'User email', text: 'User email content' }); const context2: IEmailContext = { email: email2, session: { id: 'test2', remoteAddress: '10.0.0.2' } as any }; const route2 = await router.evaluateRoutes(context2); expect(route2?.name).toEqual('wildcard-match'); }); tap.test('EmailRouter - should match IP ranges with CIDR notation', async () => { const router = new EmailRouter([]); const routes: IEmailRoute[] = [ { name: 'internal-network', match: { clientIp: '10.0.0.0/24' }, action: { type: 'deliver' } }, { name: 'external-network', match: { clientIp: ['192.168.1.0/24', '172.16.0.0/16'] }, action: { type: 'process', process: { scan: true } } } ]; router.updateRoutes(routes); // Test internal network match const email = new Email({ from: 'internal@company.com', to: 'user@company.com', subject: 'Internal email', text: 'Internal email content' }); const context1: IEmailContext = { email, session: { id: 'test1', remoteAddress: '10.0.0.15' } as any }; const route1 = await router.evaluateRoutes(context1); expect(route1?.name).toEqual('internal-network'); // Test external network match const context2: IEmailContext = { email, session: { id: 'test2', remoteAddress: '192.168.1.100' } as any }; const route2 = await router.evaluateRoutes(context2); expect(route2?.name).toEqual('external-network'); }); tap.test('EmailRouter - should handle authentication matching', async () => { const router = new EmailRouter([]); const routes: IEmailRoute[] = [ { name: 'authenticated-users', match: { authenticated: true }, action: { type: 'deliver' } }, { name: 'unauthenticated-users', match: { authenticated: false }, action: { type: 'reject', reject: { code: 550, message: 'Authentication required' } } } ]; router.updateRoutes(routes); const email = new Email({ from: 'user@example.com', to: 'recipient@test.com', subject: 'Test', text: 'Test content' }); // Test authenticated session const context1: IEmailContext = { email, session: { id: 'test1', remoteAddress: '10.0.0.1', authenticated: true, authenticatedUser: 'user@example.com' } as any }; const route1 = await router.evaluateRoutes(context1); expect(route1?.name).toEqual('authenticated-users'); // Test unauthenticated session const context2: IEmailContext = { email, session: { id: 'test2', remoteAddress: '10.0.0.2', authenticated: false } as any }; const route2 = await router.evaluateRoutes(context2); expect(route2?.name).toEqual('unauthenticated-users'); }); export default tap.start();