update
This commit is contained in:
@ -1,26 +1,49 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
import * as paths from '../../paths.js';
|
||||
import { MtaConnector } from '../delivery/classes.connector.mta.js';
|
||||
import { RuleManager } from '../core/classes.rulemanager.js';
|
||||
import { ApiManager } from './classes.apimanager.js';
|
||||
import { TemplateManager } from '../core/classes.templatemanager.js';
|
||||
import { EmailValidator } from '../core/classes.emailvalidator.js';
|
||||
import { BounceManager } from '../core/classes.bouncemanager.js';
|
||||
import { logger } from '../../logger.js';
|
||||
import type { SzPlatformService } from '../../classes.platformservice.js';
|
||||
|
||||
// Import MTA service
|
||||
import { MtaService } from '../delivery/classes.mta.js';
|
||||
// Import types from platform interfaces
|
||||
import type { default as platformInterfaces } from '../../types/platform.interfaces.js';
|
||||
import { UnifiedEmailServer } from '../routing/classes.unified.email.server.js';
|
||||
import { DomainRouter } from '../routing/classes.domain.router.js';
|
||||
import { Email } from '../core/classes.email.js';
|
||||
|
||||
// Import configuration interfaces
|
||||
import type { IEmailConfig } from '../../config/email.config.js';
|
||||
import { ConfigValidator, emailConfigSchema } from '../../config/index.js';
|
||||
|
||||
|
||||
/**
|
||||
* Options for sending an email
|
||||
* @see ISendEmailOptions in MtaConnector
|
||||
*/
|
||||
export type ISendEmailOptions = import('../delivery/classes.connector.mta.js').ISendEmailOptions;
|
||||
export interface ISendEmailOptions {
|
||||
/** Email sender override */
|
||||
from?: string;
|
||||
/** Optional reply-to address */
|
||||
replyTo?: string;
|
||||
/** CC recipients */
|
||||
cc?: string | string[];
|
||||
/** BCC recipients */
|
||||
bcc?: string | string[];
|
||||
/** Priority level */
|
||||
priority?: 'high' | 'normal' | 'low';
|
||||
/** Custom email headers */
|
||||
headers?: Record<string, string>;
|
||||
/** Whether to track opens */
|
||||
trackOpens?: boolean;
|
||||
/** Whether to track clicks */
|
||||
trackClicks?: boolean;
|
||||
/** Whether to skip suppression list check */
|
||||
skipSuppressionCheck?: boolean;
|
||||
/** Specific IP to use for sending */
|
||||
ipAddress?: string;
|
||||
/** Whether this is a transactional email */
|
||||
isTransactional?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template context data for email templates
|
||||
@ -121,17 +144,17 @@ export interface IEmailServiceStats {
|
||||
* Email service with MTA support
|
||||
*/
|
||||
export class EmailService {
|
||||
public platformServiceRef: SzPlatformService;
|
||||
public platformServiceRef: any; // Reference to platform service
|
||||
|
||||
// typedrouter
|
||||
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||||
|
||||
// connectors
|
||||
public mtaConnector: MtaConnector;
|
||||
// environment
|
||||
public qenv = new plugins.qenv.Qenv('./', '.nogit/');
|
||||
|
||||
// MTA service
|
||||
public mtaService: MtaService;
|
||||
// unified email server
|
||||
public unifiedEmailServer: UnifiedEmailServer;
|
||||
public domainRouter: DomainRouter;
|
||||
|
||||
// services
|
||||
public apiManager: ApiManager;
|
||||
@ -143,7 +166,7 @@ export class EmailService {
|
||||
// configuration
|
||||
private config: IEmailConfig;
|
||||
|
||||
constructor(platformServiceRefArg: SzPlatformService, options: IEmailConfig = {}) {
|
||||
constructor(platformServiceRefArg: any, options: IEmailConfig = {}) {
|
||||
this.platformServiceRef = platformServiceRefArg;
|
||||
this.platformServiceRef.typedrouter.addTypedRouter(this.typedrouter);
|
||||
|
||||
@ -166,22 +189,45 @@ export class EmailService {
|
||||
// Initialize template manager
|
||||
this.templateManager = new TemplateManager(this.config.templateConfig);
|
||||
|
||||
if (this.config.useMta) {
|
||||
// Initialize MTA service
|
||||
this.mtaService = new MtaService(platformServiceRefArg, this.config.mtaConfig);
|
||||
// Initialize MTA connector
|
||||
this.mtaConnector = new MtaConnector(this);
|
||||
if (this.config.useEmail) {
|
||||
// Initialize domain router for pattern matching
|
||||
this.domainRouter = new DomainRouter({
|
||||
domainRules: this.config.domainRules || [],
|
||||
defaultMode: this.config.defaultMode || 'mta',
|
||||
defaultServer: this.config.defaultServer,
|
||||
defaultPort: this.config.defaultPort,
|
||||
defaultTls: this.config.defaultTls
|
||||
});
|
||||
|
||||
// Initialize UnifiedEmailServer
|
||||
const useInternalPorts = this.config.behindSmartProxy || false;
|
||||
const emailPorts = useInternalPorts ?
|
||||
this.config.ports.map(p => p + 10000) : // Use internal ports (10025, etc.)
|
||||
this.config.ports; // Use standard ports (25, etc.)
|
||||
|
||||
this.unifiedEmailServer = new UnifiedEmailServer({
|
||||
ports: emailPorts,
|
||||
hostname: this.config.hostname || 'localhost',
|
||||
auth: this.config.auth,
|
||||
tls: this.config.tls,
|
||||
maxMessageSize: this.config.maxMessageSize,
|
||||
domainRules: this.config.domainRules || [],
|
||||
defaultMode: this.config.defaultMode || 'mta',
|
||||
defaultServer: this.config.defaultServer,
|
||||
defaultPort: this.config.defaultPort,
|
||||
defaultTls: this.config.defaultTls
|
||||
});
|
||||
|
||||
// Handle processed emails
|
||||
this.unifiedEmailServer.on('emailProcessed', (email, mode, rule) => {
|
||||
// Process email as needed (e.g., save to database, trigger notifications)
|
||||
logger.log('info', `Email processed: ${email.subject}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize API manager and rule manager
|
||||
this.apiManager = new ApiManager(this);
|
||||
this.ruleManager = new RuleManager(this);
|
||||
|
||||
// Set up MTA SMTP server webhook if using MTA
|
||||
if (this.config.useMta) {
|
||||
// The MTA SMTP server will handle incoming emails directly
|
||||
// through its SMTP protocol. No additional webhook needed.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,10 +246,10 @@ export class EmailService {
|
||||
}
|
||||
}
|
||||
|
||||
// Start MTA service if enabled
|
||||
if (this.config.useMta && this.mtaService) {
|
||||
await this.mtaService.start();
|
||||
logger.log('success', 'Started MTA service');
|
||||
// Start UnifiedEmailServer if enabled
|
||||
if (this.config.useEmail && this.unifiedEmailServer) {
|
||||
await this.unifiedEmailServer.start();
|
||||
logger.log('success', 'Started UnifiedEmailServer');
|
||||
}
|
||||
|
||||
logger.log('success', `Started email service`);
|
||||
@ -213,17 +259,17 @@ export class EmailService {
|
||||
* Stop the email service
|
||||
*/
|
||||
public async stop() {
|
||||
// Stop MTA service if it's running
|
||||
if (this.config.useMta && this.mtaService) {
|
||||
await this.mtaService.stop();
|
||||
logger.log('info', 'Stopped MTA service');
|
||||
// Stop UnifiedEmailServer if it's running
|
||||
if (this.config.useEmail && this.unifiedEmailServer) {
|
||||
await this.unifiedEmailServer.stop();
|
||||
logger.log('info', 'Stopped UnifiedEmailServer');
|
||||
}
|
||||
|
||||
logger.log('info', 'Stopped email service');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email using the MTA
|
||||
* Send an email using the UnifiedEmailServer
|
||||
* @param email The email to send
|
||||
* @param to Recipient(s)
|
||||
* @param options Additional options
|
||||
@ -233,11 +279,41 @@ export class EmailService {
|
||||
to: string | string[],
|
||||
options: ISendEmailOptions = {}
|
||||
): Promise<string> {
|
||||
// Determine which connector to use
|
||||
if (this.config.useMta && this.mtaConnector) {
|
||||
return this.mtaConnector.sendEmail(email, to, options);
|
||||
if (this.config.useEmail && this.unifiedEmailServer) {
|
||||
// Convert Smartmail to Email format
|
||||
const recipients = Array.isArray(to) ? to : [to];
|
||||
|
||||
// Access Smartmail properties using any type to bypass TypeScript checking
|
||||
const emailAny = email as any;
|
||||
|
||||
const emailObj = new Email({
|
||||
from: emailAny.from,
|
||||
to: recipients,
|
||||
subject: emailAny.subject,
|
||||
text: emailAny.body || emailAny.text,
|
||||
html: emailAny.htmlBody || emailAny.html,
|
||||
attachments: emailAny.attachments ? emailAny.attachments.map((att: any) => ({
|
||||
filename: att.filename,
|
||||
content: att.contents || att.content,
|
||||
contentType: att.contentType
|
||||
})) : []
|
||||
});
|
||||
|
||||
// Determine the domain for routing
|
||||
let matchedRule;
|
||||
const recipientDomain = recipients[0].split('@')[1];
|
||||
if (recipientDomain && this.domainRouter) {
|
||||
matchedRule = this.domainRouter.matchRule(recipients[0]);
|
||||
}
|
||||
|
||||
// Send through UnifiedEmailServer
|
||||
return this.unifiedEmailServer.sendEmail(
|
||||
emailObj,
|
||||
matchedRule?.mode || 'mta',
|
||||
matchedRule
|
||||
);
|
||||
} else {
|
||||
throw new Error('MTA not configured');
|
||||
throw new Error('Email server not configured');
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,7 +334,7 @@ export class EmailService {
|
||||
// Get email from template
|
||||
const smartmail = await this.templateManager.prepareEmail(templateId, context);
|
||||
|
||||
// Send the email
|
||||
// Send the email through UnifiedEmailServer
|
||||
return this.sendEmail(smartmail, to, options);
|
||||
} catch (error) {
|
||||
logger.log('error', `Failed to send template email: ${error.message}`, {
|
||||
@ -287,19 +363,28 @@ export class EmailService {
|
||||
* Get email service statistics
|
||||
* @returns Service statistics in the format expected by the API
|
||||
*/
|
||||
public getStats(): plugins.servezoneInterfaces.platformservice.mta.IReq_GetEMailStats['response'] {
|
||||
public getStats(): any {
|
||||
// First generate detailed internal stats
|
||||
const detailedStats: IEmailServiceStats = {
|
||||
activeProviders: []
|
||||
};
|
||||
|
||||
if (this.config.useMta) {
|
||||
detailedStats.activeProviders.push('mta');
|
||||
detailedStats.mta = this.mtaService.getStats();
|
||||
if (this.config.useEmail && this.unifiedEmailServer) {
|
||||
detailedStats.activeProviders.push('unifiedEmail');
|
||||
const serverStats = this.unifiedEmailServer.getStats();
|
||||
|
||||
detailedStats.mta = {
|
||||
startTime: serverStats.startTime,
|
||||
emailsReceived: serverStats.messages.processed,
|
||||
emailsSent: serverStats.messages.delivered,
|
||||
emailsFailed: serverStats.messages.failed,
|
||||
activeConnections: serverStats.connections.current,
|
||||
queueSize: 0 // Would need to be updated from deliveryQueue
|
||||
};
|
||||
}
|
||||
|
||||
// Convert detailed stats to the format expected by the API
|
||||
const apiStats: plugins.servezoneInterfaces.platformservice.mta.IReq_GetEMailStats['response'] = {
|
||||
const apiStats: any = {
|
||||
totalEmailsSent: detailedStats.mta?.emailsSent || 0,
|
||||
totalEmailsDelivered: detailedStats.mta?.emailsSent || 0, // Default to emails sent if we don't track delivery separately
|
||||
totalEmailsBounced: detailedStats.mta?.emailsFailed || 0,
|
||||
|
Reference in New Issue
Block a user