From f4db3ca1c3197ab1db5e85c7fe588fb0addc52b5 Mon Sep 17 00:00:00 2001 From: Andris Reinman Date: Mon, 3 Dec 2018 14:50:32 +0200 Subject: [PATCH] do not archive copied messages --- lib/handlers/on-copy.js | 148 +++++++++++++++++++++---------------- lib/handlers/on-expunge.js | 4 +- lib/message-handler.js | 6 +- tasks.js | 2 +- 4 files changed, 93 insertions(+), 67 deletions(-) diff --git a/lib/handlers/on-copy.js b/lib/handlers/on-copy.js index 03083ee1..5faa34d6 100644 --- a/lib/handlers/on-copy.js +++ b/lib/handlers/on-copy.js @@ -95,11 +95,12 @@ module.exports = (server, messageHandler) => (mailbox, update, session, callback let sourceUid = []; let destinationUid = []; let processNext = () => { - cursor.next((err, message) => { + cursor.next((err, messageData) => { if (err) { return updateQuota(() => callback(err)); } - if (!message) { + + if (!messageData) { return cursor.close(() => { updateQuota(() => { server.notifier.fire(session.user.id, targetData.path); @@ -112,8 +113,15 @@ module.exports = (server, messageHandler) => (mailbox, update, session, callback }); } + // this query points to current message + let existingQuery = { + mailbox: messageData.mailbox, + uid: messageData.uid, + _id: messageData._id + }; + // Copying is not done in bulk to minimize risk of going out of sync with incremental UIDs - sourceUid.unshift(message.uid); + sourceUid.unshift(messageData.uid); db.database.collection('mailboxes').findOneAndUpdate( { _id: targetData._id @@ -148,87 +156,101 @@ module.exports = (server, messageHandler) => (mailbox, update, session, callback let modifyIndex = item.value.modifyIndex; destinationUid.unshift(uidNext); - message._id = new ObjectID(); - message.mailbox = targetData._id; - message.uid = uidNext; + messageData._id = new ObjectID(); + messageData.mailbox = targetData._id; + messageData.uid = uidNext; // retention settings - message.exp = !!targetData.retention; - message.rdate = Date.now() + (targetData.retention || 0); - message.modseq = modifyIndex; // reset message modseq to whatever it is for the mailbox right now + messageData.exp = !!targetData.retention; + messageData.rdate = Date.now() + (targetData.retention || 0); + messageData.modseq = modifyIndex; // reset message modseq to whatever it is for the mailbox right now if (['\\Junk', '\\Trash'].includes(targetData.specialUse)) { - delete message.searchable; + delete messageData.searchable; } else { - message.searchable = true; + messageData.searchable = true; } let junk = false; - if (targetData.specialUse === '\\Junk' && !message.junk) { - message.junk = true; + if (targetData.specialUse === '\\Junk' && !messageData.junk) { + messageData.junk = true; junk = 1; - } else if (targetData.specialUse !== '\\Trash' && message.junk) { - delete message.junk; + } else if (targetData.specialUse !== '\\Trash' && messageData.junk) { + delete messageData.junk; junk = -1; } - if (!message.meta) { - message.meta = {}; + if (!messageData.meta) { + messageData.meta = {}; } - if (!message.meta.events) { - message.meta.events = []; + if (!messageData.meta.events) { + messageData.meta.events = []; } - message.meta.events.push({ + messageData.meta.events.push({ action: 'IMAPCOPY', time: new Date() }); - db.database.collection('messages').insertOne(message, { w: 'majority' }, (err, r) => { - if (err) { - return cursor.close(() => { - updateQuota(() => callback(err)); + db.database.collection('messages').updateOne( + existingQuery, + { + $set: { + // indicate that we do not need to archive this message when deleted + copied: true + } + }, + { w: 'majority' }, + () => { + db.database.collection('messages').insertOne(messageData, { w: 'majority' }, (err, r) => { + if (err) { + return cursor.close(() => { + updateQuota(() => callback(err)); + }); + } + + if (!r || !r.insertedCount) { + return processNext(); + } + + copiedMessages++; + copiedStorage += Number(messageData.size) || 0; + + let attachmentIds = Object.keys(messageData.mimeTree.attachmentMap || {}).map( + key => messageData.mimeTree.attachmentMap[key] + ); + + if (!attachmentIds.length) { + let entry = { + command: 'EXISTS', + uid: messageData.uid, + message: messageData._id, + unseen: messageData.unseen + }; + if (junk) { + entry.junk = junk; + } + return server.notifier.addEntries(targetData, entry, processNext); + } + + messageHandler.attachmentStorage.updateMany(attachmentIds, 1, messageData.magic, err => { + if (err) { + // should we care about this error? + } + let entry = { + command: 'EXISTS', + uid: messageData.uid, + message: messageData._id, + unseen: messageData.unseen + }; + if (junk) { + entry.junk = junk; + } + server.notifier.addEntries(targetData, entry, processNext); + }); }); } - - if (!r || !r.insertedCount) { - return processNext(); - } - - copiedMessages++; - copiedStorage += Number(message.size) || 0; - - let attachmentIds = Object.keys(message.mimeTree.attachmentMap || {}).map(key => message.mimeTree.attachmentMap[key]); - - if (!attachmentIds.length) { - let entry = { - command: 'EXISTS', - uid: message.uid, - message: message._id, - unseen: message.unseen - }; - if (junk) { - entry.junk = junk; - } - return server.notifier.addEntries(targetData, entry, processNext); - } - - messageHandler.attachmentStorage.updateMany(attachmentIds, 1, message.magic, err => { - if (err) { - // should we care about this error? - } - let entry = { - command: 'EXISTS', - uid: message.uid, - message: message._id, - unseen: message.unseen - }; - if (junk) { - entry.junk = junk; - } - server.notifier.addEntries(targetData, entry, processNext); - }); - }); + ); } ); }); diff --git a/lib/handlers/on-expunge.js b/lib/handlers/on-expunge.js index f76f9a1d..eea41419 100644 --- a/lib/handlers/on-expunge.js +++ b/lib/handlers/on-expunge.js @@ -108,8 +108,8 @@ module.exports = (server, messageHandler) => (mailbox, update, session, callback { messageData, session, - // do not archive drafts - archive: !messageData.flags.includes('\\Draft'), + // do not archive drafts nor copied messages + archive: !messageData.flags.includes('\\Draft') && !messageData.copied, delayNotifications: true }, (err, deleted) => { diff --git a/lib/message-handler.js b/lib/message-handler.js index 53acf750..f556c741 100644 --- a/lib/message-handler.js +++ b/lib/message-handler.js @@ -183,7 +183,10 @@ class MessageHandler { magic: maildata.magic, - subject + subject, + + // do not archive deleted messages that have been copied + copied: false }; if (options.outbound) { @@ -506,6 +509,7 @@ class MessageHandler { if (!options.archive) { return next(null, false); } + messageData.archived = curtime; messageData.exp = true; messageData.rdate = curtime.getTime() + consts.ARCHIVE_TIME; diff --git a/tasks.js b/tasks.js index c4ba0ca9..4bbb36f1 100644 --- a/tasks.js +++ b/tasks.js @@ -244,7 +244,7 @@ function clearExpiredMessages() { { messageData, // do not archive messages of deleted users - archive: !messageData.userDeleted + archive: !messageData.userDeleted && !messageData.copied }, err => { if (err) {