BREAKING CHANGE(mta): migrate internal MTA to @push.rocks/smartmta and remove legacy mail/deliverability implementation
This commit is contained in:
@@ -2,69 +2,63 @@ import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import * as plugins from '../ts/plugins.js';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import {
|
||||
DcRouter,
|
||||
type IDcRouterOptions,
|
||||
type IEmailConfig,
|
||||
type EmailProcessingMode,
|
||||
type IDomainRule
|
||||
} from '../ts/classes.dcrouter.js';
|
||||
import { DcRouter, type IDcRouterOptions } from '../ts/classes.dcrouter.js';
|
||||
import type { IUnifiedEmailServerOptions } from '@push.rocks/smartmta';
|
||||
|
||||
|
||||
tap.test('DcRouter class - Custom email port configuration', async () => {
|
||||
// Define custom port mapping
|
||||
const customPortMapping = {
|
||||
const customPortMapping: Record<number, number> = {
|
||||
25: 11025, // Custom SMTP port mapping
|
||||
587: 11587, // Custom submission port mapping
|
||||
465: 11465, // Custom SMTPS port mapping
|
||||
2525: 12525 // Additional custom port
|
||||
};
|
||||
|
||||
// Create a custom email configuration
|
||||
const emailConfig: IEmailConfig = {
|
||||
ports: [25, 587, 465, 2525], // Added a non-standard port
|
||||
|
||||
// Create a custom email configuration using smartmta interfaces
|
||||
const emailConfig: IUnifiedEmailServerOptions = {
|
||||
ports: [25, 587, 465, 2525],
|
||||
hostname: 'mail.example.com',
|
||||
maxMessageSize: 50 * 1024 * 1024, // 50MB
|
||||
|
||||
defaultMode: 'forward' as EmailProcessingMode,
|
||||
defaultServer: 'fallback-mail.example.com',
|
||||
defaultPort: 25,
|
||||
defaultTls: true,
|
||||
|
||||
domainRules: [
|
||||
domains: [
|
||||
{
|
||||
pattern: '*@example.com',
|
||||
mode: 'forward' as EmailProcessingMode,
|
||||
target: {
|
||||
server: 'mail1.example.com',
|
||||
port: 25,
|
||||
useTls: true
|
||||
domain: 'example.com',
|
||||
dnsMode: 'external-dns',
|
||||
},
|
||||
{
|
||||
domain: 'example.org',
|
||||
dnsMode: 'external-dns',
|
||||
}
|
||||
],
|
||||
routes: [
|
||||
{
|
||||
name: 'forward-example-com',
|
||||
match: {
|
||||
recipients: '*@example.com',
|
||||
},
|
||||
action: {
|
||||
type: 'forward',
|
||||
forward: {
|
||||
host: 'mail1.example.com',
|
||||
port: 25,
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
pattern: '*@example.org',
|
||||
mode: 'mta' as EmailProcessingMode,
|
||||
mtaOptions: {
|
||||
domain: 'example.org',
|
||||
allowLocalDelivery: true
|
||||
name: 'deliver-example-org',
|
||||
match: {
|
||||
recipients: '*@example.org',
|
||||
},
|
||||
action: {
|
||||
type: 'deliver',
|
||||
process: {
|
||||
dkim: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Create custom email storage path
|
||||
const customEmailsPath = path.join(process.cwd(), 'email');
|
||||
|
||||
// Ensure directory exists and is empty
|
||||
if (fs.existsSync(customEmailsPath)) {
|
||||
try {
|
||||
fs.rmSync(customEmailsPath, { recursive: true });
|
||||
} catch (e) {
|
||||
console.warn('Could not remove test directory:', e);
|
||||
}
|
||||
}
|
||||
fs.mkdirSync(customEmailsPath, { recursive: true });
|
||||
|
||||
// Create DcRouter options with custom email port configuration
|
||||
const options: IDcRouterOptions = {
|
||||
emailConfig,
|
||||
@@ -76,7 +70,6 @@ tap.test('DcRouter class - Custom email port configuration', async () => {
|
||||
routeName: 'custom-smtp-route'
|
||||
}
|
||||
},
|
||||
receivedEmailsPath: customEmailsPath
|
||||
},
|
||||
tls: {
|
||||
contactEmail: 'test@example.com'
|
||||
@@ -85,118 +78,82 @@ tap.test('DcRouter class - Custom email port configuration', async () => {
|
||||
|
||||
// Create DcRouter instance
|
||||
const router = new DcRouter(options);
|
||||
|
||||
|
||||
// Verify the options are correctly set
|
||||
expect(router.options.emailPortConfig).toBeTruthy();
|
||||
expect(router.options.emailPortConfig.portMapping).toEqual(customPortMapping);
|
||||
expect(router.options.emailPortConfig.receivedEmailsPath).toEqual(customEmailsPath);
|
||||
|
||||
expect(router.options.emailPortConfig!.portMapping).toEqual(customPortMapping);
|
||||
|
||||
// Test the generateEmailRoutes method
|
||||
if (typeof router['generateEmailRoutes'] === 'function') {
|
||||
const routes = router['generateEmailRoutes'](emailConfig);
|
||||
|
||||
if (typeof (router as any)['generateEmailRoutes'] === 'function') {
|
||||
const routes = (router as any)['generateEmailRoutes'](emailConfig);
|
||||
|
||||
// Verify that all ports are configured
|
||||
expect(routes.length).toBeGreaterThan(0); // At least some routes are configured
|
||||
|
||||
expect(routes.length).toBeGreaterThan(0);
|
||||
|
||||
// Check the custom port configuration
|
||||
const customPortRoute = routes.find(r => {
|
||||
const customPortRoute = routes.find((r: any) => {
|
||||
const ports = r.match.ports;
|
||||
return ports === 2525 || (Array.isArray(ports) && (ports as number[]).includes(2525));
|
||||
});
|
||||
expect(customPortRoute).toBeTruthy();
|
||||
expect(customPortRoute?.name).toEqual('custom-smtp-route');
|
||||
expect(customPortRoute?.action.target.port).toEqual(12525);
|
||||
|
||||
expect(customPortRoute?.action.targets[0].port).toEqual(12525);
|
||||
|
||||
// Check standard port mappings
|
||||
const smtpRoute = routes.find(r => {
|
||||
const smtpRoute = routes.find((r: any) => {
|
||||
const ports = r.match.ports;
|
||||
return ports === 25 || (Array.isArray(ports) && (ports as number[]).includes(25));
|
||||
});
|
||||
expect(smtpRoute?.action.target.port).toEqual(11025);
|
||||
|
||||
const submissionRoute = routes.find(r => {
|
||||
expect(smtpRoute?.action.targets[0].port).toEqual(11025);
|
||||
|
||||
const submissionRoute = routes.find((r: any) => {
|
||||
const ports = r.match.ports;
|
||||
return ports === 587 || (Array.isArray(ports) && (ports as number[]).includes(587));
|
||||
});
|
||||
expect(submissionRoute?.action.target.port).toEqual(11587);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
try {
|
||||
fs.rmSync(customEmailsPath, { recursive: true });
|
||||
} catch (e) {
|
||||
console.warn('Could not remove test directory in cleanup:', e);
|
||||
expect(submissionRoute?.action.targets[0].port).toEqual(11587);
|
||||
}
|
||||
});
|
||||
|
||||
tap.test('DcRouter class - Custom email storage path', async () => {
|
||||
// Create custom email storage path
|
||||
const customEmailsPath = path.join(process.cwd(), 'email');
|
||||
|
||||
// Ensure directory exists and is empty
|
||||
if (fs.existsSync(customEmailsPath)) {
|
||||
try {
|
||||
fs.rmSync(customEmailsPath, { recursive: true });
|
||||
} catch (e) {
|
||||
console.warn('Could not remove test directory:', e);
|
||||
}
|
||||
}
|
||||
fs.mkdirSync(customEmailsPath, { recursive: true });
|
||||
|
||||
tap.test('DcRouter class - Email config with domains and routes', async () => {
|
||||
// Create a basic email configuration
|
||||
// Use high port (2525) to avoid needing root privileges
|
||||
const emailConfig: IEmailConfig = {
|
||||
const emailConfig: IUnifiedEmailServerOptions = {
|
||||
ports: [2525],
|
||||
hostname: 'mail.example.com',
|
||||
domains: [], // Required: domain configurations
|
||||
routes: [] // Required: email routing rules
|
||||
domains: [],
|
||||
routes: []
|
||||
};
|
||||
|
||||
// Create DcRouter options with custom email storage path
|
||||
|
||||
// Create DcRouter options
|
||||
const options: IDcRouterOptions = {
|
||||
emailConfig,
|
||||
emailPortConfig: {
|
||||
receivedEmailsPath: customEmailsPath
|
||||
},
|
||||
tls: {
|
||||
contactEmail: 'test@example.com'
|
||||
},
|
||||
cacheConfig: {
|
||||
enabled: false,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Create DcRouter instance
|
||||
const router = new DcRouter(options);
|
||||
|
||||
|
||||
// Start the router to initialize email services
|
||||
await router.start();
|
||||
|
||||
// Verify that the custom email storage path was configured
|
||||
expect(router.options.emailPortConfig?.receivedEmailsPath).toEqual(customEmailsPath);
|
||||
|
||||
// Verify the directory exists
|
||||
expect(fs.existsSync(customEmailsPath)).toEqual(true);
|
||||
|
||||
|
||||
// Verify unified email server was initialized
|
||||
expect(router.emailServer).toBeTruthy();
|
||||
|
||||
|
||||
// Stop the router
|
||||
await router.stop();
|
||||
|
||||
// Clean up
|
||||
try {
|
||||
fs.rmSync(customEmailsPath, { recursive: true });
|
||||
} catch (e) {
|
||||
console.warn('Could not remove test directory in cleanup:', e);
|
||||
}
|
||||
});
|
||||
|
||||
// Final clean-up test
|
||||
tap.test('clean up after tests', async () => {
|
||||
// No-op - just to make sure everything is cleaned up properly
|
||||
// No-op
|
||||
});
|
||||
|
||||
tap.test('stop', async () => {
|
||||
await tap.stopForcefully();
|
||||
});
|
||||
|
||||
// Export a function to run all tests
|
||||
export default tap.start();
|
||||
export default tap.start();
|
||||
|
||||
Reference in New Issue
Block a user