allow configure autoexpunge

This commit is contained in:
Andris Reinman 2017-12-15 11:02:47 +02:00
parent 6c406c11f5
commit 97d004bd53
10 changed files with 566 additions and 536 deletions

View file

@ -49,6 +49,9 @@ ignoredHosts=[]
#secure=false
#ignoreSTARTTLS=true
# If true then EXPUNGE is called after a message gets a \Deleted flag set
autoExpunge=true
[setup]
# Public configuration for IMAP
hostname="localhost"

View file

@ -9,3 +9,6 @@
redis="redis://127.0.0.1:6379/13"
dbname="wildduck-test"
[imap]
autoExpunge=false

View file

@ -477,11 +477,11 @@ class IMAPConnection extends EventEmitter {
conn._listenerData.lock = true;
conn._server.notifier.getUpdates(selectedMailbox, conn.selected.modifyIndex, (err, updates) => {
conn._listenerData.lock = false;
if (conn._listenerData.cleared) {
if (!conn._listenerData || conn._listenerData.cleared) {
// already logged out
return;
}
conn._listenerData.lock = false;
if (err) {
conn.logger.info(

View file

@ -1089,8 +1089,8 @@ describe('IMAP Protocol integration tests', function() {
describe('EXPUNGE', function() {
// EXPUNGE is a NO OP with autoexpunge
it.skip('should automatically expunge messages', function(done) {
let cmds = ['T1 LOGIN testuser pass', 'T2 SELECT INBOX', 'T3 STORE 2:* +FLAGS (\\Deleted)', 'SLEEP', 'T4 EXPUNGE', 'T6 LOGOUT'];
it('should expunge all deleted messages', function(done) {
let cmds = ['T1 LOGIN testuser pass', 'T2 SELECT INBOX', 'T3 STORE 2:* +FLAGS (\\Deleted)', 'T4 EXPUNGE', 'T6 LOGOUT'];
testClient(
{
@ -1100,7 +1100,6 @@ describe('IMAP Protocol integration tests', function() {
},
function(resp) {
resp = resp.toString();
console.log(resp);
expect(resp.match(/^\* \d+ EXPUNGE/gm).length).to.equal(5);
expect(/^T4 OK/m.test(resp)).to.be.true;
done();
@ -1111,8 +1110,8 @@ describe('IMAP Protocol integration tests', function() {
describe('UID EXPUNGE', function() {
// UID EXPUNGE is a NO OP with autoexpunge
it.skip('should automatically expunge messages', function(done) {
let cmds = ['T1 LOGIN testuser pass', 'T2 SELECT INBOX', 'T3 STORE 1:* +FLAGS (\\Deleted)', 'SLEEP', 'T4 UID EXPUNGE 50', 'T5 LOGOUT'];
it('should expunge specific messages', function(done) {
let cmds = ['T1 LOGIN testuser pass', 'T2 SELECT INBOX', 'T3 STORE 1:* +FLAGS (\\Deleted)', 'T4 UID EXPUNGE 103,105', 'T5 LOGOUT'];
testClient(
{
@ -1122,8 +1121,9 @@ describe('IMAP Protocol integration tests', function() {
},
function(resp) {
resp = resp.toString();
expect(resp.match(/^\* \d+ EXPUNGE/gm).length).to.equal(1);
expect(resp.match(/^\* \d+ EXPUNGE/gm).length).to.equal(2);
expect(resp.match(/^\* 3 EXPUNGE/gm).length).to.equal(1);
expect(resp.match(/^\* 4 EXPUNGE/gm).length).to.equal(1);
expect(/^T4 OK/m.test(resp)).to.be.true;
done();
}

View file

@ -28,7 +28,8 @@ module.exports = (db, server, messageHandler) => {
function sendMessage(options, callback) {
let user = options.user;
db.users.collection('users').findOne({ _id: user },
db.users.collection('users').findOne(
{ _id: user },
{
fields: {
username: true,
@ -84,7 +85,8 @@ module.exports = (db, server, messageHandler) => {
return done(null, false);
}
query.user = user;
db.users.collection('messages').findOne(query,
db.users.collection('messages').findOne(
query,
{
fields: {
'mimeTree.parsedHeader': true,
@ -178,7 +180,8 @@ module.exports = (db, server, messageHandler) => {
subject,
thread: messageData.thread
});
});
}
);
};
getReferencedMessage((err, referenceData) => {
@ -291,7 +294,9 @@ module.exports = (db, server, messageHandler) => {
if (!success) {
log.info('API', 'RCPTDENY denied sent=%s allowed=%s expires=%ss.', sent, userData.recipients, ttl);
let err = new Error('You reached a daily sending limit for your account' + (ttl ? '. Limit expires in ' + ttlHuman : ''));
let err = new Error(
'You reached a daily sending limit for your account' + (ttl ? '. Limit expires in ' + ttlHuman : '')
);
err.code = 'ERRSENDINGLIMIT';
return setImmediate(() => callback(err));
}
@ -397,7 +402,8 @@ module.exports = (db, server, messageHandler) => {
);
});
});
});
}
);
}
/**

View file

@ -13,7 +13,8 @@ module.exports = (options, callback) => {
}
let curtime = new Date();
db.database.collection('autoreplies').findOne({
db.database.collection('autoreplies').findOne(
{
user: options.userData._id,
start: {
$lte: curtime
@ -127,7 +128,8 @@ module.exports = (options, callback) => {
}
return callback(err, ...args);
}
db.database.collection('messagelog').insertOne({
db.database.collection('messagelog').insertOne(
{
id: args[0].id,
messageId: args[0].messageId,
parentId: options.parentId,
@ -136,7 +138,8 @@ module.exports = (options, callback) => {
to: options.sender,
created: new Date()
},
() => callback(err, args && args[0].id));
() => callback(err, args && args[0].id)
);
}
);
@ -169,5 +172,6 @@ module.exports = (options, callback) => {
};
setImmediate(writeNextChunk);
});
});
}
);
};

View file

@ -28,7 +28,8 @@ module.exports = (options, callback) => {
}
return callback(err, ...args);
}
db.database.collection('messagelog').insertOne({
db.database.collection('messagelog').insertOne(
{
id: args[0].id,
messageId: args[0].messageId,
action: 'FORWARD',
@ -38,7 +39,8 @@ module.exports = (options, callback) => {
targets: options.targets,
created: new Date()
},
() => callback(err, args && args[0] && args[0].id));
() => callback(err, args && args[0] && args[0].id)
);
});
if (message) {
if (options.stream) {

View file

@ -1,6 +1,7 @@
'use strict';
const db = require('../db');
const tools = require('../tools');
// EXPUNGE deletes all messages in selected mailbox marked with \Delete
module.exports = (server, messageHandler) => (mailbox, update, session, callback) => {
@ -25,18 +26,24 @@ module.exports = (server, messageHandler) => (mailbox, update, session, callback
return callback(null, 'NONEXISTENT');
}
let cursor = db.database
.collection('messages')
.find({
let query = {
user: session.user.id,
mailbox: mailboxData._id,
undeleted: false,
// uid is part of the sharding key so we need it somehow represented in the query
uid: {
$gt: 0,
$lt: mailboxData.uidNext
uid: {}
};
if (update.isUid) {
query.uid = tools.checkRangeQuery(update.messages);
} else {
query.uid.$gt = 0;
query.uid.$lt = mailboxData.uidNext;
}
})
let cursor = db.database
.collection('messages')
.find(query)
.sort([['uid', 1]]);
let deletedMessages = 0;

View file

@ -1,5 +1,6 @@
'use strict';
const config = require('wild-config');
const imapTools = require('../../imap-core/lib/imap-tools');
const db = require('../db');
const tools = require('../tools');
@ -114,7 +115,7 @@ module.exports = server => (mailbox, update, session, callback) => {
// first argument is an error
return callback(...args);
} else {
if (shouldExpunge) {
if (config.imap.autoExpunge && shouldExpunge) {
// shcedule EXPUNGE command for current folder
let expungeOptions = {
// create new temporary session so it would not mix with the active one

View file

@ -279,7 +279,8 @@ module.exports = (options, callback) => {
documents.push(delivery);
}
db.senderDb.collection(config.sender.collection).insertMany(documents,
db.senderDb.collection(config.sender.collection).insertMany(
documents,
{
w: 1,
ordered: false
@ -290,7 +291,8 @@ module.exports = (options, callback) => {
}
callback(null, envelope);
});
}
);
});
});
});
@ -352,7 +354,8 @@ function removeMessage(id, callback) {
}
function setMeta(id, data, callback) {
db.senderDb.collection(config.sender.gfs + '.files').findOneAndUpdate({
db.senderDb.collection(config.sender.gfs + '.files').findOneAndUpdate(
{
filename: 'message ' + id
},
{
@ -366,5 +369,6 @@ function setMeta(id, data, callback) {
return callback(err);
}
return callback();
});
}
);
}