mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-09-20 15:26:03 +08:00
v1.0.14
This commit is contained in:
parent
dcc3181891
commit
90550226c0
|
@ -38,8 +38,13 @@ class MessageHandler {
|
|||
query._id = options.mailbox;
|
||||
} else {
|
||||
query.user = options.user;
|
||||
query.path = options.path;
|
||||
if (options.specialUse) {
|
||||
query.specialUse = options.specialUse;
|
||||
} else {
|
||||
query.path = options.path;
|
||||
}
|
||||
}
|
||||
|
||||
this.database.collection('mailboxes').findOne(query, (err, mailbox) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
|
@ -55,6 +60,8 @@ class MessageHandler {
|
|||
});
|
||||
}
|
||||
|
||||
// Monster method for inserting new messages to a mailbox
|
||||
// TODO: Refactor into smaller pieces
|
||||
add(options, callback) {
|
||||
|
||||
let id = new ObjectID();
|
||||
|
@ -113,7 +120,7 @@ class MessageHandler {
|
|||
return callback(err);
|
||||
}
|
||||
|
||||
// if a similar message already exists then delete the existing one
|
||||
// if a similar message already exists then update existing one
|
||||
let checkExisting = next => {
|
||||
this.database.collection('messages').findOne({
|
||||
mailbox: mailbox._id,
|
||||
|
@ -125,7 +132,7 @@ class MessageHandler {
|
|||
}
|
||||
|
||||
if (!existing) {
|
||||
// nothing to do here
|
||||
// nothing to do here, continue adding message
|
||||
return next();
|
||||
}
|
||||
|
||||
|
@ -134,18 +141,99 @@ class MessageHandler {
|
|||
return callback(null, false);
|
||||
}
|
||||
|
||||
// delete existing message
|
||||
this.del({
|
||||
query: {
|
||||
_id: existing._id
|
||||
},
|
||||
mailbox,
|
||||
session: options.session
|
||||
}, err => {
|
||||
// As duplicate message was found, update UID, MODSEQ and FLAGS
|
||||
|
||||
// Ensure sequential UID by locking mailbox
|
||||
this.redlock.waitAcquireLock(mailbox._id.toString(), 30 * 1000, 10 * 1000, (err, lock) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
next();
|
||||
|
||||
if (!lock || !lock.success) {
|
||||
// did not get a insert lock in 10 seconds
|
||||
return callback(new Error('Failed to acquire lock'));
|
||||
}
|
||||
|
||||
// acquire new UID+MODSEQ
|
||||
this.database.collection('mailboxes').findOneAndUpdate({
|
||||
_id: mailbox._id
|
||||
}, {
|
||||
$inc: {
|
||||
// allocate bot UID and MODSEQ values so when journal is later sorted by
|
||||
// modseq then UIDs are always in ascending order
|
||||
uidNext: 1,
|
||||
modifyIndex: 1
|
||||
}
|
||||
}, {
|
||||
returnOriginal: true
|
||||
}, (err, item) => {
|
||||
if (err) {
|
||||
return this.redlock.releaseLock(lock, () => callback(err));
|
||||
}
|
||||
|
||||
if (!item || !item.value) {
|
||||
// was not able to acquire a lock
|
||||
let err = new Error('Mailbox is missing');
|
||||
err.imapResponse = 'TRYCREATE';
|
||||
return this.redlock.releaseLock(lock, () => callback(err));
|
||||
}
|
||||
|
||||
let mailbox = item.value;
|
||||
let uid = mailbox.uidNext;
|
||||
let modseq = mailbox.modifyIndex + 1;
|
||||
|
||||
this.database.collection('messages').findOneAndUpdate({
|
||||
_id: existing._id
|
||||
}, {
|
||||
$set: {
|
||||
uid,
|
||||
modseq,
|
||||
flags
|
||||
}
|
||||
}, {
|
||||
returnOriginal: false
|
||||
}, (err, item) => {
|
||||
if (err) {
|
||||
return this.redlock.releaseLock(lock, () => callback(err));
|
||||
}
|
||||
|
||||
if (!item || !item.value) {
|
||||
// message was not found for whatever reason
|
||||
return this.redlock.releaseLock(lock, next);
|
||||
}
|
||||
|
||||
let updated = item.value;
|
||||
|
||||
if (options.session && options.session.selected && options.session.selected.mailbox === mailbox.path) {
|
||||
options.session.writeStream.write(options.session.formatResponse('EXPUNGE', existing.uid));
|
||||
}
|
||||
|
||||
if (options.session && options.session.selected && options.session.selected.mailbox === mailbox.path) {
|
||||
options.session.writeStream.write(options.session.formatResponse('EXISTS', updated.uid));
|
||||
}
|
||||
this.notifier.addEntries(mailbox, false, {
|
||||
command: 'EXPUNGE',
|
||||
ignore: options.session && options.session.id,
|
||||
uid: existing.uid,
|
||||
message: existing._id
|
||||
}, () => {
|
||||
|
||||
this.notifier.addEntries(mailbox, false, {
|
||||
command: 'EXISTS',
|
||||
uid: updated.uid,
|
||||
ignore: options.session && options.session.id,
|
||||
message: updated._id,
|
||||
modseq: updated.modseq
|
||||
}, () => {
|
||||
this.notifier.fire(mailbox.user, mailbox.path);
|
||||
return this.redlock.releaseLock(lock, () => callback(null, true, {
|
||||
uidValidity: mailbox.uidValidity,
|
||||
uid
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "wildduck",
|
||||
"version": "1.0.13",
|
||||
"version": "1.0.14",
|
||||
"description": "IMAP server built with Node.js and MongoDB",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
|
Loading…
Reference in a new issue