diff --git a/lib/filter-handler.js b/lib/filter-handler.js index 23ce2255..d1e4d971 100644 --- a/lib/filter-handler.js +++ b/lib/filter-handler.js @@ -338,7 +338,30 @@ class FilterHandler { } // never forward messages marked as spam - if (!forwardTargets.size || filterActions.get('spam')) { + if (!forwardTargets.size) { + return false; + } + + const targets = Array.from(forwardTargets).map(row => ({ + type: row[1].type, + value: row[1].value, + recipient + })); + + const logdata = { + _user: userData._id.toString(), + _mail_action: 'forward', + _sender: sender, + _recipient: recipient, + _target_address: (targets || []).map(target => ((target && target.value) || target).toString().replace(/\?.*$/, '')).join('\n'), + _message_id: prepared.mimeTree.parsedHeader['message-id'] + }; + + if (filterActions.get('spam')) { + logdata.short_message = '[FRWRDFAIL] Skipped forwarding due to spam'; + logdata._error = 'Skipped forwarding due to spam'; + logdata._code = 'ESPAM'; + this.loggelf(logdata); return; } @@ -352,40 +375,57 @@ class FilterHandler { ); if (!counterResult.success) { log.silly('Filter', 'FRWRDFAIL key=%s error=%s', 'wdf:' + userData._id.toString(), 'Precondition failed'); + + logdata.short_message = '[FRWRDFAIL] Skipped forwarding due to rate limiting'; + logdata._error = 'Skipped forwarding due to rate limiting'; + logdata._code = 'ERATELIMIT'; + this.loggelf(logdata); return false; } } catch (err) { // failed checks, ignore - log.error('Filter', 'FRWRDFAIL key=%s error=%s', 'wdf:' + userData._id.toString(), err.message); + log.info('Filter', 'FRWRDFAIL key=%s error=%s', 'wdf:' + userData._id.toString(), err.message); + + logdata.short_message = '[FRWRDFAIL] Skipped forwarding due to database error'; + logdata._error = err.message; + logdata._code = err.code; + this.loggelf(logdata); } if (userData.encryptForwarded && userData.pubKey) { await encryptMessage(); } - let forwardResponse = await this.forward({ - db: this.db, - maildrop: this.maildrop, + try { + let forwardResponse = await this.forward({ + db: this.db, + maildrop: this.maildrop, - parentId: prepared.id, - userData, - sender, - recipient, + parentId: prepared.id, + userData, + sender, + recipient, - targets: - (forwardTargets.size && - Array.from(forwardTargets).map(row => ({ - type: row[1].type, - value: row[1].value, - recipient - }))) || - false, + targets, - chunks, - chunklen - }); + chunks, + chunklen + }); - return forwardResponse; + if (forwardResponse) { + logdata.short_message = '[FRWRDOK] Scheduled forwarding'; + logdata._forwarded = 'yes'; + logdata._target_queue_id = forwardResponse; + this.loggelf(logdata); + } + + return forwardResponse; + } catch (err) { + logdata.short_message = '[FRWRDFAIL] Skipped forwarding due to queueing error'; + logdata._error = err.message; + logdata._code = err.code; + this.loggelf(logdata); + } }; let sendAutoreply = async () => { diff --git a/lib/maildropper.js b/lib/maildropper.js index a872eced..052b4483 100644 --- a/lib/maildropper.js +++ b/lib/maildropper.js @@ -29,7 +29,16 @@ class Maildropper { } checkLoop(envelope, deliveries) { - if (envelope.reason !== 'forward' || !this.options.loopSecret) { + if (envelope.reason !== 'forward') { + return false; + } + + if (envelope.headers.get('Received').length >= 30) { + envelope.looped = true; + return true; + } + + if (!this.options.loopSecret) { return false; } diff --git a/package.json b/package.json index ee34a1ef..3a6b999d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wildduck", - "version": "1.27.3", + "version": "1.27.4", "description": "IMAP/POP3 server built with Node.js and MongoDB", "main": "server.js", "scripts": {