Skip to content

Commit

Permalink
message-handler refactoring + optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
NickOvt committed Feb 3, 2025
1 parent d08eaed commit 9bd2e2f
Showing 1 changed file with 96 additions and 94 deletions.
190 changes: 96 additions & 94 deletions lib/message-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,11 @@ class MessageHandler {
}

// get target mailbox data
let mailboxData = await this.getMailboxAsync(options);
// get target user data
let [mailboxData, userData] = await Promise.all([this.getMailboxAsync(options), this.users.collection('users').findOne({ _id: options.user })]);

options.targetMailboxEncrypted = !!mailboxData.encryptMessages;

// get target user data
const userData = await this.users.collection('users').findOne({ _id: options.user });

let prepared = options.prepared; // might be undefined

// check if already encrypted
Expand Down Expand Up @@ -308,10 +306,11 @@ class MessageHandler {
// with err, with attachments
try {
await this.attachmentStorage.deleteMany(attachmentIds, maildata.magic);
throw err;
} catch (ignore) {
} catch {
// throw original error
throw err;
}
throw err;
};

try {
Expand Down Expand Up @@ -474,9 +473,9 @@ class MessageHandler {
}

let rollback = async rollbackError => {
let args;
let r;
try {
args = await this.users.collection('users').findOneAndUpdate(
r = await this.users.collection('users').findOneAndUpdate(
{
_id: mailboxData.user
},
Expand All @@ -492,12 +491,11 @@ class MessageHandler {
}
}
);
} catch (ignore) {
// ignore
} catch {
// some error, clean up immediately
return cleanup(rollbackError);
}

let r = args && args[1];

if (r && r.value) {
this.loggelf({
short_message: '[QUOTA] -',
Expand Down Expand Up @@ -598,63 +596,7 @@ class MessageHandler {
let uidValidity = mailboxData.uidValidity;
let uid = messageData.uid;

if (
options.session &&
options.session.selected &&
options.session.selected.mailbox &&
options.session.selected.mailbox.toString() === mailboxData._id.toString()
) {
options.session.writeStream.write(options.session.formatResponse('EXISTS', messageData.uid));
}

let updateAddressRegister = async finishFunc => {
let addresses = [];

if (messageData.junk || flags.includes('\\Draft')) {
// skip junk and draft messages
return finishFunc();
}

let parsed = messageData.mimeTree && messageData.mimeTree.parsedHeader;

if (parsed) {
let keyList = mailboxData.specialUse === '\\Sent' ? ['to', 'cc', 'bcc'] : ['from'];

for (const disallowedHeader of DISALLOWED_HEADERS_FOR_ADDRESS_REGISTER) {
// if email contains headers that we do not want,
// don't add any emails to address register
if (parsed[disallowedHeader]) {
return finishFunc();
}
}

for (let key of keyList) {
if (parsed[key] && parsed[key].length) {
for (let addr of parsed[key]) {
if (/no-?reply/i.test(addr.address)) {
continue;
}
if (!addresses.some(a => a.address === addr.address)) {
addresses.push(addr);
}
}
}
}
}

if (!addresses.length) {
return finishFunc();
}

try {
await this.updateAddressRegister(mailboxData.user, addresses);
return finishFunc();
} catch (err) {
return finishFunc(err);
}
};

return updateAddressRegister(
const finishFunc = // finishFunc:
async () =>
new Promise(resolve => {
this.notifier.addEntries(
Expand All @@ -681,45 +623,105 @@ class MessageHandler {
.toArray();

let now = new Date();
const auditPromises = [];

for (let auditData of audits) {
if ((auditData.start && auditData.start > now) || (auditData.end && auditData.end < now)) {
// audit not active
continue;
}
await this.auditHandler.store(auditData._id, raw, {
date: messageData.idate,
msgid: messageData.msgid,
header: messageData.mimeTree && messageData.mimeTree.parsedHeader,
ha: messageData.ha,
mailbox: mailboxData._id,
mailboxPath: mailboxData.path,
info: Object.assign({ queueId: messageData.outbound }, messageData.meta)
});

auditPromises.push(
this.auditHandler.store(auditData._id, raw, {
date: messageData.idate,
msgid: messageData.msgid,
header: messageData.mimeTree && messageData.mimeTree.parsedHeader,
ha: messageData.ha,
mailbox: mailboxData._id,
mailboxPath: mailboxData.path,
info: Object.assign({ queueId: messageData.outbound }, messageData.meta)
})
);
}

await Promise.all(auditPromises);
};

let next = () =>
cleanup(null, true, {
uidValidity,
uid,
id: messageData._id.toString(),
mailbox: mailboxData._id.toString(),
mailboxPath: mailboxData.path,
size,
status: 'new'
});
// can safely cleanup, no err given. Returns pending promise, which is fine
const cleanupRes = cleanup(null, true, {
uidValidity,
uid,
id: messageData._id.toString(),
mailbox: mailboxData._id.toString(),
mailboxPath: mailboxData.path,
size,
status: 'new'
});

// do not use more suitable .finally() as it is not supported in Node v8
// do not use more suitable finally as it is not supported in Node v8
try {
await processAudits();
resolve(next());
} catch (ignore) {
resolve(next());
resolve(cleanupRes);
} catch {
resolve(cleanupRes);
}
}
);
})
);
});

if (
options.session &&
options.session.selected &&
options.session.selected.mailbox &&
options.session.selected.mailbox.toString() === mailboxData._id.toString()
) {
options.session.writeStream.write(options.session.formatResponse('EXISTS', messageData.uid));
}

let addresses = [];

if (messageData.junk || flags.includes('\\Draft')) {
// skip junk and draft messages
return finishFunc();
}

let parsed = messageData.mimeTree && messageData.mimeTree.parsedHeader;

if (parsed) {
let keyList = mailboxData.specialUse === '\\Sent' ? ['to', 'cc', 'bcc'] : ['from'];

for (const disallowedHeader of DISALLOWED_HEADERS_FOR_ADDRESS_REGISTER) {
// if email contains headers that we do not want,
// don't add any emails to address register
if (parsed[disallowedHeader]) {
return finishFunc();
}
}

for (let key of keyList) {
if (parsed[key] && parsed[key].length) {
for (let addr of parsed[key]) {
if (/no-?reply/i.test(addr.address)) {
continue;
}
if (!addresses.some(a => a.address === addr.address)) {
addresses.push(addr);
}
}
}
}
}

if (!addresses.length) {
return finishFunc();
}

try {
await this.updateAddressRegister(mailboxData.user, addresses);
return finishFunc();
} catch (err) {
return finishFunc(err);
}
}

async updateQuotaAsync(user, inc, options) {
Expand Down

0 comments on commit 9bd2e2f

Please sign in to comment.