import * as plugins from '../plugins.js'; import { EmailService } from './classes.emailservice.js'; import { logger } from '../logger.js'; export class RuleManager { public emailRef: EmailService; public smartruleInstance = new plugins.smartrule.SmartRule< plugins.smartmail.Smartmail >(); constructor(emailRefArg: EmailService) { this.emailRef = emailRefArg; // Register MTA handler for incoming emails if MTA is enabled if (this.emailRef.mtaService) { this.setupMtaIncomingHandler(); } } /** * Set up handler for incoming emails via MTA's SMTP server */ private setupMtaIncomingHandler() { // The original MtaService doesn't have a direct callback for incoming emails, // but we can modify this approach based on how you prefer to integrate. // One option would be to extend the MtaService to add an event emitter. // For now, we'll use a directory watcher as an example // This would watch the directory where MTA saves incoming emails const incomingDir = this.emailRef.mtaService['receivedEmailsDir'] || './received'; // Simple file watcher (in real implementation, use proper file watching) // This is just conceptual - would need modification to work with your specific setup this.watchIncomingEmails(incomingDir); } /** * Watch directory for incoming emails (conceptual implementation) */ private watchIncomingEmails(directory: string) { console.log(`Watching for incoming emails in: ${directory}`); // Conceptual - in a real implementation, set up proper file watching // or modify the MTA to emit events when emails are received /* // Example using a file watcher: const watcher = plugins.fs.watch(directory, async (eventType, filename) => { if (eventType === 'rename' && filename.endsWith('.eml')) { const filePath = plugins.path.join(directory, filename); await this.handleMtaIncomingEmail(filePath); } }); */ } /** * Handle incoming email received via MTA */ public async handleMtaIncomingEmail(emailPath: string) { try { // Process the email file const fetchedSmartmail = await this.emailRef.mtaConnector.receiveEmail(emailPath); console.log('======================='); console.log('Received a mail via MTA:'); console.log(`From: ${fetchedSmartmail.options.creationObjectRef.From}`); console.log(`To: ${fetchedSmartmail.options.creationObjectRef.To}`); console.log(`Subject: ${fetchedSmartmail.options.creationObjectRef.Subject}`); console.log('^^^^^^^^^^^^^^^^^^^^^^^'); logger.log( 'info', `email from ${fetchedSmartmail.options.creationObjectRef.From} to ${fetchedSmartmail.options.creationObjectRef.To} with subject '${fetchedSmartmail.options.creationObjectRef.Subject}'`, { eventType: 'receivedEmail', provider: 'mta', email: { from: fetchedSmartmail.options.creationObjectRef.From, to: fetchedSmartmail.options.creationObjectRef.To, subject: fetchedSmartmail.options.creationObjectRef.Subject, }, } ); // Process with rules this.smartruleInstance.makeDecision(fetchedSmartmail); } catch (error) { logger.log('error', `Failed to process incoming MTA email: ${error.message}`, { eventType: 'emailError', provider: 'mta', error: error.message }); } } public async init() { // Setup email rules await this.createForwards(); } /** * creates the default forwards */ public async createForwards() { const forwards: { originalToAddress: string[]; forwardedToAddress: string[] }[] = []; console.log(`${forwards.length} forward rules configured:`); for (const forward of forwards) { console.log(forward); } for (const forward of forwards) { this.smartruleInstance.createRule( 10, async (smartmailArg) => { const matched = forward.originalToAddress.reduce((prevValue, currentValue) => { return smartmailArg.options.creationObjectRef.To.includes(currentValue) || prevValue; }, false); if (matched) { console.log('Forward rule matched'); console.log(forward); return 'apply-continue'; } else { return 'continue'; } }, async (smartmailArg: plugins.smartmail.Smartmail) => { forward.forwardedToAddress.map(async (toArg) => { const forwardedSmartMail = new plugins.smartmail.Smartmail({ body: `
Original Sender:
${smartmailArg.options.creationObjectRef.From}
Original Recipient:
${smartmailArg.options.creationObjectRef.To}
Forwarded to:
${forward.forwardedToAddress.reduce((pVal, cVal) => { return `${pVal ? pVal + ', ' : ''}${cVal}`; }, null)}
Subject:
${smartmailArg.getSubject()}
The original body can be found below.
` + smartmailArg.getBody(), from: 'forwarder@mail.lossless.one', subject: `Forwarded mail for '${smartmailArg.options.creationObjectRef.To}'`, }); for (const attachment of smartmailArg.attachments) { forwardedSmartMail.addAttachment(attachment); } // Use the EmailService's sendEmail method to send with the appropriate provider await this.emailRef.sendEmail(forwardedSmartMail, toArg); console.log(`forwarded mail to ${toArg}`); logger.log( 'info', `email from ${ smartmailArg.options.creationObjectRef.From } to ${toArg} with subject '${smartmailArg.getSubject()}'`, { eventType: 'forwardedEmail', email: { from: smartmailArg.options.creationObjectRef.From, to: smartmailArg.options.creationObjectRef.To, forwardedTo: toArg, subject: smartmailArg.options.creationObjectRef.Subject, }, } ); }); } ); } } }