mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-12-26 18:01:01 +08:00
do not archive copied messages
This commit is contained in:
parent
5141248fb8
commit
f4db3ca1c3
4 changed files with 93 additions and 67 deletions
|
@ -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);
|
||||
});
|
||||
});
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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;
|
||||
|
|
2
tasks.js
2
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) {
|
||||
|
|
Loading…
Reference in a new issue