Files
dcrouter/test/test.email-socket-handler.ts

230 lines
6.8 KiB
TypeScript

import { tap, expect } from '@git.zone/tstest/tapbundle';
import { DcRouter } from '../ts/classes.dcrouter.js';
import * as plugins from '../ts/plugins.js';
let dcRouter: DcRouter;
tap.test('should use traditional port forwarding when useSocketHandler is false', async () => {
dcRouter = new DcRouter({
emailConfig: {
ports: [2525, 2587, 2465],
hostname: 'mail.test.local',
domains: ['test.local'],
routes: [],
useSocketHandler: false // Traditional mode
},
smartProxyConfig: {
routes: []
}
});
await dcRouter.start();
// Check that email server is created and listening on ports
const emailServer = (dcRouter as any).emailServer;
expect(emailServer).toBeDefined();
// Check SmartProxy routes are forward type
const smartProxy = (dcRouter as any).smartProxy;
const routes = smartProxy?.options?.routes || [];
const emailRoutes = routes.filter((route: any) =>
route.name?.includes('-route')
);
emailRoutes.forEach((route: any) => {
expect(route.action.type).toEqual('forward');
expect(route.action.target).toBeDefined();
expect(route.action.target.host).toEqual('localhost');
});
await dcRouter.stop();
});
tap.test('should use socket-handler mode when useSocketHandler is true', async () => {
dcRouter = new DcRouter({
emailConfig: {
ports: [2525, 2587, 2465],
hostname: 'mail.test.local',
domains: ['test.local'],
routes: [],
useSocketHandler: true // Socket-handler mode
},
smartProxyConfig: {
routes: []
}
});
await dcRouter.start();
// Check that email server is created
const emailServer = (dcRouter as any).emailServer;
expect(emailServer).toBeDefined();
// Check SmartProxy routes are socket-handler type
const smartProxy = (dcRouter as any).smartProxy;
const routes = smartProxy?.options?.routes || [];
const emailRoutes = routes.filter((route: any) =>
route.name?.includes('-route')
);
emailRoutes.forEach((route: any) => {
expect(route.action.type).toEqual('socket-handler');
expect(route.action.socketHandler).toBeDefined();
expect(typeof route.action.socketHandler).toEqual('function');
});
await dcRouter.stop();
});
tap.test('should generate correct email routes for each port', async () => {
const emailConfig = {
ports: [2525, 2587, 2465],
hostname: 'mail.test.local',
domains: ['test.local'],
routes: [],
useSocketHandler: true
};
dcRouter = new DcRouter({ emailConfig });
// Access the private method to generate routes
const emailRoutes = (dcRouter as any).generateEmailRoutes(emailConfig);
expect(emailRoutes.length).toEqual(3);
// Check route for port 2525 (non-standard ports use generic naming)
const port2525Route = emailRoutes.find((r: any) => r.name === 'email-port-2525-route');
expect(port2525Route).toBeDefined();
expect(port2525Route.match.ports).toContain(2525);
expect(port2525Route.action.type).toEqual('socket-handler');
// Check route for port 2587
const port2587Route = emailRoutes.find((r: any) => r.name === 'email-port-2587-route');
expect(port2587Route).toBeDefined();
expect(port2587Route.match.ports).toContain(2587);
expect(port2587Route.action.type).toEqual('socket-handler');
// Check route for port 2465
const port2465Route = emailRoutes.find((r: any) => r.name === 'email-port-2465-route');
expect(port2465Route).toBeDefined();
expect(port2465Route.match.ports).toContain(2465);
expect(port2465Route.action.type).toEqual('socket-handler');
});
tap.test('email socket handler should handle different ports correctly', async () => {
dcRouter = new DcRouter({
emailConfig: {
ports: [2525, 2587, 2465],
hostname: 'mail.test.local',
domains: ['test.local'],
routes: [],
useSocketHandler: true
}
});
await dcRouter.start();
// Test port 2525 handler (plain SMTP)
const port2525Handler = (dcRouter as any).createMailSocketHandler(2525);
expect(port2525Handler).toBeDefined();
expect(typeof port2525Handler).toEqual('function');
// Test port 2465 handler (SMTPS - should wrap in TLS)
const port2465Handler = (dcRouter as any).createMailSocketHandler(2465);
expect(port2465Handler).toBeDefined();
expect(typeof port2465Handler).toEqual('function');
await dcRouter.stop();
});
tap.test('email server handleSocket method should work', async () => {
dcRouter = new DcRouter({
emailConfig: {
ports: [2525],
hostname: 'mail.test.local',
domains: ['test.local'],
routes: [],
useSocketHandler: true
}
});
await dcRouter.start();
const emailServer = (dcRouter as any).emailServer;
expect(emailServer).toBeDefined();
expect(emailServer.handleSocket).toBeDefined();
expect(typeof emailServer.handleSocket).toEqual('function');
// Create a mock socket
const mockSocket = new plugins.net.Socket();
let socketDestroyed = false;
mockSocket.destroy = () => {
socketDestroyed = true;
};
// Test handleSocket
try {
await emailServer.handleSocket(mockSocket, 2525);
// It will fail because we don't have a real socket, but it should handle it gracefully
} catch (error) {
// Expected to error with mock socket
}
await dcRouter.stop();
});
tap.test('should not create SMTP servers when useSocketHandler is true', async () => {
dcRouter = new DcRouter({
emailConfig: {
ports: [2525, 2587, 2465],
hostname: 'mail.test.local',
domains: ['test.local'],
routes: [],
useSocketHandler: true
}
});
await dcRouter.start();
// The email server should not have any SMTP server instances
const emailServer = (dcRouter as any).emailServer;
expect(emailServer).toBeDefined();
// The servers array should be empty (no port binding)
expect(emailServer.servers).toBeDefined();
expect(emailServer.servers.length).toEqual(0);
await dcRouter.stop();
});
tap.test('TLS handling should differ between ports', async () => {
// Use standard ports 25 and 465 to test TLS behavior
// This test doesn't start the server, just checks route generation
const emailConfig = {
ports: [25, 465],
hostname: 'mail.test.local',
domains: ['test.local'],
routes: [],
useSocketHandler: false // Use traditional mode to check TLS config
};
dcRouter = new DcRouter({ emailConfig });
const emailRoutes = (dcRouter as any).generateEmailRoutes(emailConfig);
// Port 25 should use passthrough
const smtpRoute = emailRoutes.find((r: any) => r.match.ports[0] === 25);
expect(smtpRoute.action.tls.mode).toEqual('passthrough');
// Port 465 should use terminate
const smtpsRoute = emailRoutes.find((r: any) => r.match.ports[0] === 465);
expect(smtpsRoute.action.tls.mode).toEqual('terminate');
expect(smtpsRoute.action.tls.certificate).toEqual('auto');
});
tap.test('stop', async () => {
await tap.stopForcefully();
});
export default tap.start();