177 lines
6.5 KiB
TypeScript
177 lines
6.5 KiB
TypeScript
import * as plugins from '../plugins.js';
|
|
import { EmailService } from './email.classes.emailservice.js';
|
|
import { logger } from '../logger.js';
|
|
|
|
export class RuleManager {
|
|
public emailRef: EmailService;
|
|
public smartruleInstance = new plugins.smartrule.SmartRule<
|
|
plugins.smartmail.Smartmail<any>
|
|
>();
|
|
|
|
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<boolean>((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<any>) => {
|
|
forward.forwardedToAddress.map(async (toArg) => {
|
|
const forwardedSmartMail = new plugins.smartmail.Smartmail({
|
|
body:
|
|
`
|
|
<div style="background: #CCC; padding: 10px; border-radius: 3px;">
|
|
<div><b>Original Sender:</b></div>
|
|
<div>${smartmailArg.options.creationObjectRef.From}</div>
|
|
<div><b>Original Recipient:</b></div>
|
|
<div>${smartmailArg.options.creationObjectRef.To}</div>
|
|
<div><b>Forwarded to:</b></div>
|
|
<div>${forward.forwardedToAddress.reduce<string>((pVal, cVal) => {
|
|
return `${pVal ? pVal + ', ' : ''}${cVal}`;
|
|
}, null)}</div>
|
|
<div><b>Subject:</b></div>
|
|
<div>${smartmailArg.getSubject()}</div>
|
|
<div><b>The original body can be found below.</b></div>
|
|
</div>
|
|
` + 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,
|
|
},
|
|
}
|
|
);
|
|
});
|
|
}
|
|
);
|
|
}
|
|
}
|
|
} |