From cbffa6d3dcadb937b9303a42fbe2603fd1668fb8 Mon Sep 17 00:00:00 2001 From: Andris Reinman Date: Fri, 2 Feb 2024 10:50:48 +0200 Subject: [PATCH] fix(loop): reject messages with too many Received headers --- config/default.js | 8 ++++++++ plugins/core/delivery-loop.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 plugins/core/delivery-loop.js diff --git a/config/default.js b/config/default.js index 6f07c13..ce86f4f 100644 --- a/config/default.js +++ b/config/default.js @@ -197,6 +197,14 @@ module.exports = { addSignatureTimestamp: false, // Time validity of the signature given in seconds, for default value see below signatureExpireIn: 0 + }, + + // Make sure messages have all required headers like Date or Message-ID + 'core/delivery-loop': { + enabled: ['receiver', 'main'], + + // Reject messages with higher Received count + maxHops: 35 } }, diff --git a/plugins/core/delivery-loop.js b/plugins/core/delivery-loop.js new file mode 100644 index 0000000..957ec93 --- /dev/null +++ b/plugins/core/delivery-loop.js @@ -0,0 +1,28 @@ +'use strict'; + +// Set module title +module.exports.title = 'DeliveryLoop'; + +// Initialize the module +module.exports.init = (app, done) => { + const MAX_HOPS = app.config.maxHops || 25; + + app.addHook('message:headers', (envelope, messageInfo, next) => { + let receivedLength = envelope.headers.get('Received').length; + + if (receivedLength > MAX_HOPS) { + // too many hops + app.logger.info('DeliveryLoop', 'Too many hops (%s)! Delivery loop detected for %s, rejecting message', receivedLength, envelope.id); + let err = new Error(`A delivery loop was detected which causes this email which caused the email to be undeliverable (${receivedLength})`); + err.name = 'SMTPResponse'; + err.responseCode = 500; + return next(err); + } + + // allow the message to pass + return next(); + }); + + // all set up regarding this plugin + done(); +};