diff --git a/.eslintrc b/.eslintrc
index 06e364c0..7ca59e93 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,3 +1,6 @@
{
+ "rules": {
+ "indent": 0
+ },
"extends": "nodemailer"
}
diff --git a/config/sender.toml b/config/sender.toml
index fe8c35b4..47a8a582 100644
--- a/config/sender.toml
+++ b/config/sender.toml
@@ -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"
diff --git a/lib/api/addresses.js b/lib/api/addresses.js
index 5e501bdb..d3b4f7fc 100644
--- a/lib/api/addresses.js
+++ b/lib/api/addresses.js
@@ -1002,7 +1002,7 @@ module.exports = (db, server) => {
* @apiParam {Number} [forwards] Daily allowed forwarding count for this address
* @apiParam {Boolean} [allowWildcard=false] If true
then address value can be in the form of *@example.com
, 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
});
diff --git a/lib/autoreply.js b/lib/autoreply.js
index 28f53f4a..f2b338ba 100644
--- a/lib/autoreply.js
+++ b/lib/autoreply.js
@@ -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));
}
);
diff --git a/lib/filter-handler.js b/lib/filter-handler.js
index 075c8438..0d845fcf 100644
--- a/lib/filter-handler.js
+++ b/lib/filter-handler.js
@@ -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);
diff --git a/lib/maildrop.js b/lib/maildrop.js
index 1173cf28..b6c1c5d1 100644
--- a/lib/maildrop.js
+++ b/lib/maildrop.js
@@ -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
diff --git a/lib/user-handler.js b/lib/user-handler.js
index bc1bcb96..2f0b4411 100644
--- a/lib/user-handler.js
+++ b/lib/user-handler.js
@@ -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(
{
diff --git a/package.json b/package.json
index f329bbb2..5fe47d23 100644
--- a/package.json
+++ b/package.json
@@ -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",