BREAKING CHANGE(mta): migrate internal MTA to @push.rocks/smartmta and remove legacy mail/deliverability implementation
This commit is contained in:
@@ -3,12 +3,14 @@ import * as paths from './paths.js';
|
||||
|
||||
// Certificate types are available via plugins.tsclass
|
||||
|
||||
// Import the email server and its configuration
|
||||
import { UnifiedEmailServer, type IUnifiedEmailServerOptions } from './mail/routing/classes.unified.email.server.js';
|
||||
import type { IEmailRoute, IEmailDomainConfig } from './mail/routing/interfaces.js';
|
||||
// Import the email server and its configuration from smartmta
|
||||
import {
|
||||
UnifiedEmailServer,
|
||||
type IUnifiedEmailServerOptions,
|
||||
type IEmailRoute,
|
||||
type IEmailDomainConfig,
|
||||
} from '@push.rocks/smartmta';
|
||||
import { logger } from './logger.js';
|
||||
// Import the email configuration helpers directly from mail/delivery
|
||||
import { configureEmailStorage, configureEmailServer } from './mail/delivery/index.js';
|
||||
// Import storage manager
|
||||
import { StorageManager, type IStorageConfig } from './storage/index.js';
|
||||
// Import cache system
|
||||
@@ -221,12 +223,6 @@ export class DcRouter {
|
||||
// Set up unified email handling if configured
|
||||
if (this.options.emailConfig) {
|
||||
await this.setupUnifiedEmailHandling();
|
||||
|
||||
// Apply custom email storage configuration if available
|
||||
if (this.emailServer && this.options.emailPortConfig?.receivedEmailsPath) {
|
||||
logger.log('info', 'Applying custom email storage configuration');
|
||||
configureEmailStorage(this.emailServer, this.options);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up DNS server if configured with nameservers and scopes
|
||||
@@ -533,37 +529,26 @@ export class DcRouter {
|
||||
break;
|
||||
}
|
||||
|
||||
// Create action based on mode
|
||||
let action: any;
|
||||
|
||||
if (emailConfig.useSocketHandler) {
|
||||
// Socket-handler mode
|
||||
action = {
|
||||
type: 'socket-handler' as any,
|
||||
socketHandler: this.createMailSocketHandler(port)
|
||||
};
|
||||
} else {
|
||||
// Traditional forwarding mode
|
||||
const defaultPortMapping = {
|
||||
25: 10025, // SMTP
|
||||
587: 10587, // Submission
|
||||
465: 10465 // SMTPS
|
||||
};
|
||||
|
||||
const portMapping = this.options.emailPortConfig?.portMapping || defaultPortMapping;
|
||||
const internalPort = portMapping[port] || port + 10000;
|
||||
|
||||
action = {
|
||||
type: 'forward',
|
||||
target: {
|
||||
host: 'localhost', // Forward to internal email server
|
||||
port: internalPort
|
||||
},
|
||||
tls: {
|
||||
mode: tlsMode as any
|
||||
}
|
||||
};
|
||||
}
|
||||
// Create forward action to route to internal email server ports
|
||||
const defaultPortMapping: Record<number, number> = {
|
||||
25: 10025, // SMTP
|
||||
587: 10587, // Submission
|
||||
465: 10465 // SMTPS
|
||||
};
|
||||
|
||||
const portMapping = this.options.emailPortConfig?.portMapping || defaultPortMapping;
|
||||
const internalPort = portMapping[port] || port + 10000;
|
||||
|
||||
let action: any = {
|
||||
type: 'forward',
|
||||
targets: [{
|
||||
host: 'localhost', // Forward to internal email server
|
||||
port: internalPort
|
||||
}],
|
||||
tls: {
|
||||
mode: tlsMode as any
|
||||
}
|
||||
};
|
||||
|
||||
// For TLS terminate mode, add certificate info
|
||||
if (tlsMode === 'terminate' && action.tls) {
|
||||
@@ -845,7 +830,7 @@ export class DcRouter {
|
||||
|
||||
// Update the unified email server if it exists
|
||||
if (this.emailServer) {
|
||||
this.emailServer.updateRoutes(routes);
|
||||
this.emailServer.updateEmailRoutes(routes);
|
||||
}
|
||||
|
||||
console.log(`Email routes updated with ${routes.length} routes`);
|
||||
@@ -862,67 +847,6 @@ export class DcRouter {
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure MTA for email handling with custom port and storage settings
|
||||
* @param config Configuration for the MTA service
|
||||
*/
|
||||
public async configureEmailMta(config: {
|
||||
internalPort: number;
|
||||
host?: string;
|
||||
secure?: boolean;
|
||||
storagePath?: string;
|
||||
portMapping?: Record<number, number>;
|
||||
}): Promise<boolean> {
|
||||
logger.log('info', 'Configuring MTA service with custom settings');
|
||||
|
||||
|
||||
// Update email port configuration
|
||||
if (!this.options.emailPortConfig) {
|
||||
this.options.emailPortConfig = {};
|
||||
}
|
||||
|
||||
// Configure storage paths for received emails
|
||||
if (config.storagePath) {
|
||||
// Set the storage path for received emails
|
||||
this.options.emailPortConfig.receivedEmailsPath = config.storagePath;
|
||||
}
|
||||
|
||||
// Apply port mapping if provided
|
||||
if (config.portMapping) {
|
||||
this.options.emailPortConfig.portMapping = {
|
||||
...this.options.emailPortConfig.portMapping,
|
||||
...config.portMapping
|
||||
};
|
||||
|
||||
logger.log('info', `Updated MTA port mappings: ${JSON.stringify(this.options.emailPortConfig.portMapping)}`);
|
||||
}
|
||||
|
||||
// Use the dedicated helper to configure the email server
|
||||
// Pass through the options specified by the implementation
|
||||
if (this.emailServer) {
|
||||
configureEmailServer(this.emailServer, {
|
||||
ports: [config.internalPort], // Use whatever port the implementation specifies
|
||||
hostname: config.host,
|
||||
tls: config.secure ? {
|
||||
// Basic TLS settings if secure mode is enabled
|
||||
certPath: this.options.tls?.certPath,
|
||||
keyPath: this.options.tls?.keyPath,
|
||||
caPath: this.options.tls?.caPath
|
||||
} : undefined,
|
||||
storagePath: config.storagePath
|
||||
});
|
||||
}
|
||||
|
||||
// If email handling is already set up, restart it to apply changes
|
||||
if (this.emailServer) {
|
||||
logger.log('info', 'Restarting unified email handling to apply MTA configuration changes');
|
||||
await this.stopUnifiedEmailComponents();
|
||||
await this.setupUnifiedEmailHandling();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register DNS records with the DNS server
|
||||
* @param records Array of DNS records to register
|
||||
@@ -1245,8 +1169,8 @@ export class DcRouter {
|
||||
|
||||
logger.log('info', 'Initializing DKIM keys for email domains...');
|
||||
|
||||
// Get DKIMCreator instance from email server
|
||||
const dkimCreator = (this.emailServer as any).dkimCreator;
|
||||
// Get DKIMCreator instance from email server (public in smartmta)
|
||||
const dkimCreator = this.emailServer.dkimCreator;
|
||||
if (!dkimCreator) {
|
||||
logger.log('warn', 'DKIMCreator not available, skipping DKIM initialization');
|
||||
return;
|
||||
@@ -1408,51 +1332,6 @@ export class DcRouter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create mail socket handler for email traffic
|
||||
*/
|
||||
private createMailSocketHandler(port: number): (socket: plugins.net.Socket) => Promise<void> {
|
||||
return async (socket: plugins.net.Socket) => {
|
||||
if (!this.emailServer) {
|
||||
logger.log('error', 'Mail socket handler called but email server not initialized');
|
||||
socket.end();
|
||||
return;
|
||||
}
|
||||
|
||||
logger.log('debug', `Mail socket handler: handling connection for port ${port}`);
|
||||
|
||||
try {
|
||||
// Port 465 requires immediate TLS
|
||||
if (port === 465) {
|
||||
// Wrap the socket in TLS
|
||||
const tlsOptions = {
|
||||
isServer: true,
|
||||
key: this.options.tls?.keyPath ? plugins.fs.readFileSync(this.options.tls.keyPath, 'utf8') : undefined,
|
||||
cert: this.options.tls?.certPath ? plugins.fs.readFileSync(this.options.tls.certPath, 'utf8') : undefined
|
||||
};
|
||||
|
||||
const tlsSocket = new plugins.tls.TLSSocket(socket, tlsOptions);
|
||||
|
||||
tlsSocket.on('secure', () => {
|
||||
// Pass the secure socket to the email server
|
||||
this.emailServer!.handleSocket(tlsSocket, port);
|
||||
});
|
||||
|
||||
tlsSocket.on('error', (err) => {
|
||||
logger.log('error', `TLS handshake error on port ${port}: ${err.message}`);
|
||||
socket.destroy();
|
||||
});
|
||||
} else {
|
||||
// For ports 25 and 587, pass raw socket (STARTTLS handled by email server)
|
||||
await this.emailServer.handleSocket(socket, port);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log('error', `Mail socket handler error on port ${port}: ${error.message}`);
|
||||
socket.destroy();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up RADIUS server for network authentication
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user