mirror of
https://github.com/nodemailer/wildduck.git
synced 2025-09-05 20:54:36 +08:00
allow configure autoexpunge
This commit is contained in:
parent
6c406c11f5
commit
97d004bd53
10 changed files with 566 additions and 536 deletions
|
@ -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"
|
||||
|
|
|
@ -9,3 +9,6 @@
|
|||
redis="redis://127.0.0.1:6379/13"
|
||||
|
||||
dbname="wildduck-test"
|
||||
|
||||
[imap]
|
||||
autoExpunge=false
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) => {
|
|||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue