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(); +};