Permalink
Browse files

bounce: initial authoring

  • Loading branch information...
1 parent da4f19d commit 1bdc895daa2c690b0bb50feadfcc538cbc116934 @msimerson msimerson committed Jan 19, 2014
Showing with 95 additions and 1 deletion.
  1. +1 −1 TODO
  2. +5 −0 config/bounce.ini
  3. +23 −0 docs/plugins/bounces.md
  4. +59 −0 plugins/bounce.js
  5. +7 −0 plugins/mail_from.nobounces.js
View
2 TODO
@@ -3,7 +3,6 @@
- Create a config file for each of the core shipping configs, so people have something as a baseline
- IMAP server (long shot for now)
- Plugins to copy from Qpsmtpd:
- - bogus_bounce (checks bounces have one recipient and no return-path)
- dspam
- greylisting
- virus/*
@@ -23,6 +22,7 @@ Remove the following deprecated plugins
- data.noreceived
- data.rfc5322_header_checks
- daemonize
+ - mail_from.nobounces
Rename the following plugins
- toobusy -> connect.toobusy
View
@@ -0,0 +1,5 @@
+; reject all bounce messages (generally not a good idea)
+reject_all=0
+
+; reject bounces that are not RFC compliant (likely faked)
+reject_invalid=1
View
@@ -0,0 +1,23 @@
+bounce
+===================
+This plugin provides options for bounce processing.
+
+
+Configuration
+-------------------
+
+- reject_all
+
+Blocks all bounce messages using the simple rule of checking
+for `MAIL FROM:<>`.
+
+This is useful to enable if you have a mail server that gets spoofed too
+much but very few legitimate users. It is potentially bad to block all
+bounce messages, but unfortunately for some hosts, sometimes necessary.
+
+
+- reject_invalid
+--------------------
+This option tries to assure the message really is a bounce. It makes
+sure the message has a single recipient and that the return path is
+empty.
View
@@ -0,0 +1,59 @@
+// bounce tests
+
+exports.register = function () {
+ var plugin = this;
+
+ this.register_hook('mail', 'bounce_mail');
+ // this.register_hook('rcpt', 'bounce_rcpt');
+ // this.register_hook('data', 'bounce_data');
+ this.register_hook('data_post', 'bounce_data_post');
+};
+
+exports.bounce_mail = function (next, connection, params) {
+ var mail_from = params[0];
+ if (!mail_from.isNull()) return next(); // not a bounce
+ var cfg = this.config.get('bounce.ini');
+ if (cfg.reject_all)
+ return next(DENY, "No bounces accepted here");
+ return next();
+}
+
+exports.bounce_data_post = function(next, connection) {
+ var plugin = connection;
+
+ if (!has_null_sender(connection)) return next(); // not a bounce.
+
+ var cfg = this.config.get('bounce.ini');
+ var rej = cfg.reject_invalid;
+
+ // Valid bounces have a single recipient
+ var err = has_single_recipient(connection, plugin);
+ if (err && rej) return next(DENY, err);
+
+ // validate that Return-Path is empty, RFC 3834
+ err = has_empty_return_path(connection, plugin);
+ if (err && rej) return next(DENY, err);
+
+ return next();
+};
+
+function has_empty_return_path(connection, plugin) {
+ var rp = connection.transaction.header.get('Return-Path');
+ if (!rp) return;
+ if (rp === '<>') return;
+ connection.loginfo(plugin, "bounce messages must not have a Return-Path");
+ return "a bounce return path must be empty (RFC 3834)";
+};
+
+function has_single_recipient(connection, plugin) {
+ if (connection.transaction.rcpt_to.length === 1) return;
+
+ connection.loginfo(plugin, "bogus bounce to: " +
+ connection.transaction.rcpt_to.join(','));
+
+ return "this bounce message does not have 1 recipient";
+};
+
+function has_null_sender(connection) {
+ return connection.transaction.mail_from.isNull() ? true : false;
+};
@@ -1,6 +1,13 @@
// I don't allow MAIL FROM:<> on my server, because it's all crap and I send
// so little mail anyway that I rarely get real bounces
+// this plugin is deprecated. Use the 'bounce' plugin instead, and set
+// config/bounce.ini reject_all=1
+
+exports.register = function () {
+ this.logwarn("NOTICE: plugin deprecated, use 'bounce' instead!");
+}
+
exports.hook_mail = function (next, connection, params) {
var mail_from = params[0];
if (mail_from.isNull()) {

0 comments on commit 1bdc895

Please sign in to comment.