mirror of
https://github.com/nodemailer/wildduck.git
synced 2025-11-10 00:11:06 +08:00
Allow setting default retention to all mailboxes
This commit is contained in:
parent
383bc4d4cb
commit
8d03e37ac7
5 changed files with 63 additions and 22 deletions
|
|
@ -179,6 +179,7 @@ Arguments
|
||||||
- **username** is the username of the user. This is not an email address but authentication username, use only letters and numbers
|
- **username** is the username of the user. This is not an email address but authentication username, use only letters and numbers
|
||||||
- **password** is the password for the user
|
- **password** is the password for the user
|
||||||
- **quota** (optional) is the maximum storage in bytes allowed for this user. If not set then the default value is used
|
- **quota** (optional) is the maximum storage in bytes allowed for this user. If not set then the default value is used
|
||||||
|
- **retention** (optional) is the default retention time in ms for mailboxes. Messages in Trash and Junk folders have a maximum retention time of 30 days.
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const os = require('os');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
log: {
|
log: {
|
||||||
level: 'silly'
|
level: 'silly'
|
||||||
|
|
@ -95,5 +97,7 @@ module.exports = {
|
||||||
maxRecipients: 2000,
|
maxRecipients: 2000,
|
||||||
|
|
||||||
// default forwarded messages for 24h (can be overriden per user)
|
// default forwarded messages for 24h (can be overriden per user)
|
||||||
maxForwards: 2000
|
maxForwards: 2000,
|
||||||
|
|
||||||
|
emailDomain: os.hostname()
|
||||||
};
|
};
|
||||||
|
|
|
||||||
44
imap.js
44
imap.js
|
|
@ -195,21 +195,34 @@ server.onCreate = function (path, session, callback) {
|
||||||
return callback(null, 'ALREADYEXISTS');
|
return callback(null, 'ALREADYEXISTS');
|
||||||
}
|
}
|
||||||
|
|
||||||
mailbox = {
|
db.database.collection('users').findOne({
|
||||||
user: session.user.id,
|
_id: session.user.id
|
||||||
path,
|
}, {
|
||||||
uidValidity: Math.floor(Date.now() / 1000),
|
fields: {
|
||||||
uidNext: 1,
|
retention: true
|
||||||
modifyIndex: 0,
|
}
|
||||||
subscribed: true,
|
}, (err, user) => {
|
||||||
flags: []
|
|
||||||
};
|
|
||||||
|
|
||||||
db.database.collection('mailboxes').insertOne(mailbox, err => {
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
return callback(null, true);
|
|
||||||
|
mailbox = {
|
||||||
|
user: session.user.id,
|
||||||
|
path,
|
||||||
|
uidValidity: Math.floor(Date.now() / 1000),
|
||||||
|
uidNext: 1,
|
||||||
|
modifyIndex: 0,
|
||||||
|
subscribed: true,
|
||||||
|
flags: [],
|
||||||
|
retention: user.retention
|
||||||
|
};
|
||||||
|
|
||||||
|
db.database.collection('mailboxes').insertOne(mailbox, err => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
return callback(null, true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -1005,8 +1018,9 @@ server.onCopy = function (path, update, session, callback) {
|
||||||
message.mailbox = target._id;
|
message.mailbox = target._id;
|
||||||
message.uid = uidNext;
|
message.uid = uidNext;
|
||||||
|
|
||||||
message.exp = ['\\Trash', '\\Junk'].includes(target.specialUse);
|
// retention settings
|
||||||
message.rdate = new Date();
|
message.exp = !!target.retention;
|
||||||
|
message.rdate = Date.now() + (target.retention || 0);
|
||||||
|
|
||||||
if (!message.meta) {
|
if (!message.meta) {
|
||||||
message.meta = {};
|
message.meta = {};
|
||||||
|
|
@ -1778,7 +1792,7 @@ function clearExpiredMessages() {
|
||||||
let cursor = db.database.collection('messages').find({
|
let cursor = db.database.collection('messages').find({
|
||||||
exp: true,
|
exp: true,
|
||||||
rdate: {
|
rdate: {
|
||||||
$lte: new Date(Date.now() - config.imap.retention * 24 * 3600 * 1000)
|
$lte: Date.now()
|
||||||
}
|
}
|
||||||
}).project({
|
}).project({
|
||||||
_id: true,
|
_id: true,
|
||||||
|
|
|
||||||
|
|
@ -246,9 +246,9 @@ class MessageHandler {
|
||||||
_id: id,
|
_id: id,
|
||||||
|
|
||||||
// if true then expirest after rdate + retention
|
// if true then expirest after rdate + retention
|
||||||
exp: ['\\Trash', '\\Junk'].includes(mailbox.specialUse),
|
exp: !!mailbox.retention,
|
||||||
|
rdate: Date.now() + (mailbox.retention || 0),
|
||||||
|
|
||||||
rdate: new Date(),
|
|
||||||
idate,
|
idate,
|
||||||
hdate,
|
hdate,
|
||||||
flags,
|
flags,
|
||||||
|
|
@ -630,9 +630,9 @@ class MessageHandler {
|
||||||
// this will be changed later by the notification system
|
// this will be changed later by the notification system
|
||||||
modseq: 0,
|
modseq: 0,
|
||||||
|
|
||||||
// if exp=true, then remove message after rdate + retention ploicy
|
// retention settings
|
||||||
exp: ['\\Trash', '\\Junk'].includes(target.specialUse),
|
exp: !!target.retention,
|
||||||
rdate: new Date()
|
rdate: Date.now() + (target.retention || 0)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ const base32 = require('base32.js');
|
||||||
const MAX_STORAGE = 1 * (1024 * 1024 * 1024);
|
const MAX_STORAGE = 1 * (1024 * 1024 * 1024);
|
||||||
const MAX_RECIPIENTS = 2000;
|
const MAX_RECIPIENTS = 2000;
|
||||||
const MAX_FORWARDS = 2000;
|
const MAX_FORWARDS = 2000;
|
||||||
|
const JUNK_RETENTION = 30 * 24 * 3600 * 1000;
|
||||||
|
|
||||||
const mailboxTranslations = {
|
const mailboxTranslations = {
|
||||||
en: {
|
en: {
|
||||||
|
|
@ -48,6 +49,11 @@ class UserHandler {
|
||||||
meta = {};
|
meta = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!password) {
|
||||||
|
// do not allow signing in without a password
|
||||||
|
return callback(null, false);
|
||||||
|
}
|
||||||
|
|
||||||
let checkAddress = next => {
|
let checkAddress = next => {
|
||||||
if (username.indexOf('@') < 0) {
|
if (username.indexOf('@') < 0) {
|
||||||
// assume regular username
|
// assume regular username
|
||||||
|
|
@ -206,8 +212,14 @@ class UserHandler {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let retention = Number(data.retention) || 0;
|
||||||
|
let junkRetention = JUNK_RETENTION;
|
||||||
|
if (retention < 0) {
|
||||||
|
retention = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Insert
|
// Insert
|
||||||
let hash = bcrypt.hashSync(data.password, 11);
|
let hash = data.password ? bcrypt.hashSync(data.password, 11) : '';
|
||||||
this.database.collection('users').insertOne({
|
this.database.collection('users').insertOne({
|
||||||
username: data.username,
|
username: data.username,
|
||||||
name: data.name,
|
name: data.name,
|
||||||
|
|
@ -230,6 +242,9 @@ class UserHandler {
|
||||||
|
|
||||||
filters: [],
|
filters: [],
|
||||||
|
|
||||||
|
// default retention for user mailboxes
|
||||||
|
retention,
|
||||||
|
|
||||||
created: new Date(),
|
created: new Date(),
|
||||||
|
|
||||||
// until setup value is not true, this account is not usable
|
// until setup value is not true, this account is not usable
|
||||||
|
|
@ -244,6 +259,13 @@ class UserHandler {
|
||||||
|
|
||||||
let mailboxes = this.getMailboxes(data.language).map(mailbox => {
|
let mailboxes = this.getMailboxes(data.language).map(mailbox => {
|
||||||
mailbox.user = user;
|
mailbox.user = user;
|
||||||
|
|
||||||
|
if (['\\Trash', '\\Junk'].includes(mailbox.specialUse)) {
|
||||||
|
mailbox.retention = retention ? Math.min(retention, junkRetention) : junkRetention;
|
||||||
|
} else {
|
||||||
|
mailbox.retention = retention;
|
||||||
|
}
|
||||||
|
|
||||||
return mailbox;
|
return mailbox;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue