This commit is contained in:
Andris Reinman 2018-01-09 13:50:29 +02:00
parent 2daaa8127d
commit 0efcf316a5
8 changed files with 102 additions and 115 deletions

View file

@ -1,3 +1,6 @@
{
"rules": {
"indent": 0
},
"extends": "nodemailer"
}

View file

@ -1,7 +1,3 @@
# Push messages to ZoneMTA queue for delivery
# if `false` then no messages are sent
enabled=true
# which ZoneMTA queue to use by default
zone="default"

View file

@ -1002,7 +1002,7 @@ module.exports = (db, server) => {
* @apiParam {Number} [forwards] Daily allowed forwarding count for this address
* @apiParam {Boolean} [allowWildcard=false] If <code>true</code> then address value can be in the form of <code>*@example.com</code>, otherwise using * is not allowed
* @apiParam {Object} [autoreply] Autoreply information
* @apiParam {Boolean} [autoreply.enabled] If true, then autoreply is enabled for this address
* @apiParam {Boolean} [autoreply.status] If true, then autoreply is enabled for this address
* @apiParam {String} [autoreply.start] Either a date string or boolean false to disable start time checks
* @apiParam {String} [autoreply.end] Either a date string or boolean false to disable end time checks
* @apiParam {String} [autoreply.subject] Autoreply subject line
@ -1062,7 +1062,7 @@ module.exports = (db, server) => {
.default(0),
allowWildcard: Joi.boolean().truthy(['Y', 'true', 'yes', 1]),
autoreply: Joi.object().keys({
enabled: Joi.boolean()
status: Joi.boolean()
.truthy(['Y', 'true', 'yes', 1])
.default(true),
start: Joi.date()
@ -1127,7 +1127,7 @@ module.exports = (db, server) => {
}
} else {
result.value.autoreply = {
enabled: false
status: false
};
}
@ -1299,7 +1299,7 @@ module.exports = (db, server) => {
* @apiParam {String[]} [targets] An array of forwarding targets. The value could either be an email address or a relay url to next MX server ("smtp://mx2.zone.eu:25"). If set then overwrites previous targets array
* @apiParam {Number} [forwards] Daily allowed forwarding count for this address
* @apiParam {Object} [autoreply] Autoreply information
* @apiParam {Boolean} [autoreply.enabled] If true, then autoreply is enabled for this address
* @apiParam {Boolean} [autoreply.status] If true, then autoreply is enabled for this address
* @apiParam {String} [autoreply.start] Either a date string or boolean false to disable start time checks
* @apiParam {String} [autoreply.end] Either a date string or boolean false to disable end time checks
* @apiParam {String} [autoreply.subject] Autoreply subject line
@ -1351,7 +1351,7 @@ module.exports = (db, server) => {
.min(1),
forwards: Joi.number().min(0),
autoreply: Joi.object().keys({
enabled: Joi.boolean().truthy(['Y', 'true', 'yes', 1]),
status: Joi.boolean().truthy(['Y', 'true', 'yes', 1]),
start: Joi.date()
.empty('')
.allow(false),
@ -1708,7 +1708,7 @@ module.exports = (db, server) => {
* @apiSuccess {Number} limits.forwards.used How many messages are forwarded during current 24 hour period
* @apiSuccess {Number} limits.forwards.ttl Time until the end of current 24 hour period
* @apiSuccess {Object} autoreply Autoreply information
* @apiSuccess {Boolean} autoreply.enabled If true, then autoreply is enabled for this address
* @apiSuccess {Boolean} autoreply.status If true, then autoreply is enabled for this address
* @apiSuccess {String} autoreply.subject Autoreply subject line
* @apiSuccess {String} autoreply.text Autoreply plaintext content
* @apiSuccess {String} autoreply.html Autoreply HTML content
@ -1818,7 +1818,7 @@ module.exports = (db, server) => {
ttl: forwardsTtl >= 0 ? forwardsTtl : false
}
},
autoreply: addressData.autoreply || { enabled: false },
autoreply: addressData.autoreply || { status: false },
created: addressData.created
});
@ -1851,7 +1851,7 @@ module.exports = (db, server) => {
* @apiSuccess {Number} limits.forwards.used How many messages are forwarded during current 24 hour period
* @apiSuccess {Number} limits.forwards.ttl Time until the end of current 24 hour period
* @apiSuccess {Object} autoreply Autoreply information
* @apiSuccess {Boolean} autoreply.enabled If true, then autoreply is enabled for this address
* @apiSuccess {Boolean} autoreply.status If true, then autoreply is enabled for this address
* @apiSuccess {String} autoreply.subject Autoreply subject line
* @apiSuccess {String} autoreply.text Autoreply plaintext content
* @apiSuccess {String} autoreply.html Autoreply HTML content
@ -1889,7 +1889,7 @@ module.exports = (db, server) => {
* }
* },
* "autoreply": {
* "enabled": false
* "status": false
* },
* "created": "2017-10-24T11:19:10.911Z"
* }
@ -1995,7 +1995,7 @@ module.exports = (db, server) => {
ttl: forwardsTtl >= 0 ? forwardsTtl : false
}
},
autoreply: addressData.autoreply || { enabled: false },
autoreply: addressData.autoreply || { status: false },
created: addressData.created
});

View file

@ -80,7 +80,7 @@ module.exports = (options, autoreplyData, callback) => {
},
headers: {
'Auto-Submitted': 'auto-replied',
'X-WD-Autoreply-For': (options.parentId || '').toString()
'X-WD-Autoreply-For': (options.parentId || options.queueId).toString()
},
inReplyTo: headers.getFirst('Message-ID'),
references: (headers.getFirst('Message-ID') + ' ' + headers.getFirst('References')).trim(),
@ -104,18 +104,24 @@ module.exports = (options, autoreplyData, callback) => {
}
return callback(err, ...args);
}
options.db.database.collection('messagelog').insertOne(
{
id: args[0].id,
messageId: args[0].messageId,
parentId: options.parentId,
action: 'AUTOREPLY',
from: '',
to: options.sender,
created: new Date()
},
() => callback(err, args && args[0].id)
);
let logentry = {
id: args[0].id,
messageId: args[0].messageId,
action: 'AUTOREPLY',
from: '',
to: options.sender,
sender: options.recipient,
created: new Date()
};
if (options.parentId) {
logentry.parentId = options.parentId;
}
if (options.queueId) {
logentry.queueId = options.queueId;
}
options.db.database.collection('messagelog').insertOne(logentry, () => callback(err, args && args[0].id));
}
);

View file

@ -42,7 +42,6 @@ class FilterHandler {
this.spamChecks = options.spamChecks || tools.prepareSpamChecks(defaultSpamHeaderKeys);
this.spamHeaderKeys = options.spamHeaderKeys || this.spamChecks.map(check => check.key);
this.senderEnabled = options.sender.enabled;
this.maildrop = new Maildropper({
db: this.db,
zone: options.sender.zone,
@ -329,10 +328,6 @@ class FilterHandler {
};
let forwardMessage = done => {
if (!this.senderEnabled) {
return setImmediate(done);
}
if (userData.forward && !filterActions.get('delete')) {
// forward to default recipient only if the message is not deleted
(Array.isArray(userData.forward) ? userData.forward : [].concat(userData.forward || [])).forEach(forward => {
@ -397,10 +392,6 @@ class FilterHandler {
};
let sendAutoreply = done => {
if (!this.senderEnabled) {
return setImmediate(done);
}
// never reply to messages marked as spam
if (!sender || !userData.autoreply || filterActions.get('spam')) {
return setImmediate(done);

View file

@ -7,16 +7,10 @@ const Maildropper = require('./maildropper');
let maildropper;
module.exports = (options, callback) => {
if (!config.sender.enabled) {
setImmediate(() => callback(null, false));
return false;
}
maildropper =
maildropper ||
new Maildropper({
db,
enabled: config.sender.enabled,
zone: config.sender.zone,
collection: config.sender.collection,
gfs: config.sender.gfs

View file

@ -48,16 +48,22 @@ class UserHandler {
let username = address.substr(0, address.indexOf('@')).replace(/\./g, '');
let domain = address.substr(address.indexOf('@') + 1);
let fields = {
user: true,
targets: true
};
Object.keys(options.fields || {}).forEach(key => {
fields[key] = true;
});
// try exact match
this.users.collection('addresses').findOne(
{
addrview: username + '@' + domain
},
{
fields: {
user: true,
targets: true
}
fields
},
(err, addressData) => {
if (err) {
@ -87,10 +93,7 @@ class UserHandler {
addrview: username + '@' + aliasDomain
},
{
fields: {
user: true,
targets: true
}
fields
},
done
);
@ -124,10 +127,7 @@ class UserHandler {
this.users.collection('addresses').findOne(
query,
{
fields: {
user: true,
targets: true
}
fields
},
(err, addressData) => {
if (err) {
@ -145,10 +145,7 @@ class UserHandler {
addrview: address.substr(0, address.indexOf('@')).replace(/\./g, '') + '@*'
},
{
fields: {
user: true,
targets: true
}
fields
},
(err, addressData) => {
if (err) {
@ -1246,15 +1243,15 @@ class UserHandler {
let update =
!userData.enabled2fa || typeof userData.enabled2fa === 'boolean'
? {
$set: {
enabled2fa: ['totp']
}
}
$set: {
enabled2fa: ['totp']
}
}
: {
$addToSet: {
enabled2fa: 'totp'
}
};
$addToSet: {
enabled2fa: 'totp'
}
};
// token was valid, update user settings
return this.users.collection('users').findOneAndUpdate(
@ -1328,19 +1325,19 @@ class UserHandler {
let update =
!userData.enabled2fa || typeof userData.enabled2fa === 'boolean'
? {
$set: {
enabled2fa: [],
seed: ''
}
}
$set: {
enabled2fa: [],
seed: ''
}
}
: {
$pull: {
enabled2fa: 'totp'
},
$set: {
seed: ''
}
};
$pull: {
enabled2fa: 'totp'
},
$set: {
seed: ''
}
};
return this.users.collection('users').findOneAndUpdate(
{
@ -1627,25 +1624,25 @@ class UserHandler {
let update =
!userData.enabled2fa || typeof userData.enabled2fa === 'boolean'
? {
$set: {
enabled2fa: ['u2f'],
u2fKeyHandle: result.keyHandle,
u2fPubKey: result.publicKey,
u2fCert: result.certificate,
u2fDate: curDate
}
}
$set: {
enabled2fa: ['u2f'],
u2fKeyHandle: result.keyHandle,
u2fPubKey: result.publicKey,
u2fCert: result.certificate,
u2fDate: curDate
}
}
: {
$addToSet: {
enabled2fa: 'u2f'
},
$set: {
u2fKeyHandle: result.keyHandle,
u2fPubKey: result.publicKey,
u2fCert: result.certificate,
u2fDate: curDate
}
};
$addToSet: {
enabled2fa: 'u2f'
},
$set: {
u2fKeyHandle: result.keyHandle,
u2fPubKey: result.publicKey,
u2fCert: result.certificate,
u2fDate: curDate
}
};
return this.users.collection('users').findOneAndUpdate(
{
@ -1719,23 +1716,23 @@ class UserHandler {
let update =
!userData.enabled2fa || typeof userData.enabled2fa === 'boolean'
? {
$set: {
enabled2fa: [],
u2fKeyHandle: '',
u2fPubKey: '',
u2fCert: ''
}
}
$set: {
enabled2fa: [],
u2fKeyHandle: '',
u2fPubKey: '',
u2fCert: ''
}
}
: {
$pull: {
enabled2fa: 'u2f'
},
$set: {
u2fKeyHandle: '',
u2fPubKey: '',
u2fCert: ''
}
};
$pull: {
enabled2fa: 'u2f'
},
$set: {
u2fKeyHandle: '',
u2fPubKey: '',
u2fCert: ''
}
};
return this.users.collection('users').findOneAndUpdate(
{

View file

@ -1,6 +1,6 @@
{
"name": "wildduck",
"version": "1.0.106",
"version": "1.0.107",
"description": "IMAP server built with Node.js and MongoDB",
"main": "server.js",
"scripts": {
@ -31,7 +31,7 @@
"dependencies": {
"addressparser": "1.0.1",
"bcryptjs": "2.4.3",
"bugsnag": "2.0.1",
"bugsnag": "2.1.1",
"generate-password": "1.3.0",
"he": "1.1.1",
"html-to-text": "3.3.0",
@ -40,7 +40,7 @@
"iconv-lite": "0.4.19",
"ioredfour": "1.0.2-ioredis",
"ioredis": "3.2.2",
"joi": "13.0.2",
"joi": "13.1.0",
"js-yaml": "3.10.0",
"key-fingerprint": "1.1.0",
"libbase64": "1.0.2",