Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
msimerson committed Jan 24, 2017
1 parent 091047d commit 7c8639b
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 13 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ Increase the reputation of domains you send email to.

# How it works

When you[r users] send emails, this plugin will increment counters for each recipient domain.
When emails later arrive from domains your users have sent email to, reputation engines like
This plugin looks at outgoing emails that have been successfully queued. Outgoing messages are determined by inspecting the `relaying` property of the connection. If `relaying=true`, then the connection has (via AUTH credentials or IP ACLs) been extended a form of trust.

In those outbound emails, the sender domain and recipient domains are parsed out and a redis entry is inserted/updated. Later when emails arrive from domains your users have sent email to, reputation engines like
[karma](https://github.com/haraka/haraka-plugin-karma) can observe this and boost their deliverability.


Expand Down
92 changes: 82 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,76 @@ var tlds = require('haraka-tld');
exports.register = function () {
var plugin = this;

plugin.register_hook('queue_ok', 'after_queue');
plugin.register_hook('mail', 'check_sender');
plugin.register_hook('rcpt_ok', 'check_recipient');
plugin.register_hook('queue_ok', 'update_sender');
}

exports.after_queue = function (next, connection, params) {
exports.check_sender = function (next, connection, params) {
var plugin = this;

if (connection.relaying) return next();

var sender_od = plugin.get_sender_domain(connection.transaction);

if (plugin.has_fcrdns_match(sender_od, connection)) return next();
if (plugin.has_spf_match(sender_od, connection)) return next();

// no other auth mechanisms to test
return next();
}

exports.check_recipient = function (next, connection, rcpt) {
var plugin = this;
// a plugin has vouched that the rcpt is for a domain we accept mail for

function errNext (err) {
plugin.logerror(err);
next();
}

// if no validated sender domain, there's nothing to do here
if (!plugin.validated_sender_od) return errNext('no valid sender od');

if (!rcpt.host) return errNext('rcpt.host unset?');

var rcpt_od = tlds.get_organizational_domain(rcpt.host);
if (!rcpt_od) return errNext('no rcpt od');

// DO THE CHECK

return next();
}

exports.update_sender = function (next, connection, params) {
var plugin = this;
// queue_ok arguments: next, connection, msg
// ok 1390590369 qp 634 (F82E2DD5-9238-41DC-BC95-9C3A02716AD2.1)

function errNext (err) {
plugin.logerror(err);
next();
}

plugin.loginfo(plugin, params);
if (!connection) return next();
if (!connection.transaction) return next();
if (!connection) return errNext('no connection');
if (!connection.transaction) return errNext('no transaction');
if (!connection.relaying) return errNext('not relaying');
var txn = connection.transaction;

var sender_od = plugin.get_sender_domain(txn);
if (!sender_od) return next();
var rcpt_domains = plugin.get_recipient_domains(txn);
if (rcpt_domains.length === 0) return next();

if (!sender_od) return errNext('no sender domain');
plugin.loginfo('sender domain: ' + sender_od);
plugin.loginfo('recip domains: ' + rcpt_domains.join(','));

next();
var rcpt_domains = plugin.get_recipient_domains(txn);
if (rcpt_domains.length === 0) {
plugin.logerror('no recipient domains');
}
else {
plugin.loginfo('recip domains: ' + rcpt_domains.join(','));
}

next(undefined, sender_od, rcpt_domains);
}

exports.get_recipient_domains = function (txn) {
Expand All @@ -40,6 +88,7 @@ exports.get_recipient_domains = function (txn) {
plugin.loginfo('rcpt: ' + txn.rcpt_to[i].host + ' -> ' + rcpt_od);
}
if (rcpt_domains.indexOf(rcpt_od) === -1) {
// not a duplicate, add to the list
rcpt_domains.push(rcpt_od);
}
}
Expand All @@ -56,4 +105,27 @@ exports.get_sender_domain = function (txn) {
plugin.loginfo('sender: ' + txn.mail_from.host + ' -> ' + sender_od);
}
return sender_od;
}

exports.has_fcrdns_match = function (sender_od, connection) {
var plugin = this;
var fcrdns = connection.results.get('fcrdns');
if (!fcrdns) return false;
if (!fcrdns.fcrdns) return false;

var fcrdns_od = tlds.get_organizational_domain(fcrdns.fcrdns);
if (fcrdns_od !== sender_od) return false;

plugin.validated_sender_od = sender_od;
return true;
}

exports.has_spf_match = function (sender_od, connection) {
var plugin = this;

var spf = connection.results.get('spf');
if (!spf) return false;

plugin.loginfo(spf);
return false;
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "Increase the reputation of domains you send email to.",
"main": "index.js",
"scripts": {
"lint": "./node_modules/.bin/eslint *.js test/*.js",
"test": "mocha"
},
"repository": {
Expand All @@ -24,7 +25,9 @@
},
"homepage": "https://github.com/haraka/haraka-plugin-domain-counters#readme",
"devDependencies": {
"haraka-test-fixtures": "^1.0.13"
"address-rfc2821": "*",
"eslint": "^3",
"haraka-test-fixtures": "*"
},
"dependencies": {
"haraka-tld": "^1.0.12"
Expand Down
56 changes: 56 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

var assert = require('assert');

var Address = require('address-rfc2821').Address;
var fixtures = require('haraka-test-fixtures');



describe('after_queue', function () {

var plugin = fixtures.plugin('index');
var connection;

beforeEach(function (done) {
connection = fixtures.connection.createConnection();
connection.relaying = true;
connection.transaction = fixtures.transaction.createTransaction();
done();
});

it('gets the sender domain', function (done) {
connection.transaction.mail_from = new Address('<johndoe@example.com>');

plugin.after_queue(function (undefined, sender_dom, rcpt_doms) {
assert.equal(sender_dom, 'example.com');
assert.deepEqual(rcpt_doms, [])
done();
},
connection);
});

it('gets the recipient domain', function (done) {
connection.transaction.mail_from = new Address('<johndoe@example.com>');
connection.transaction.rcpt_to.push(new Address('<jane@test1.com>'));

plugin.after_queue(function (undefined, sender_dom, rcpt_doms) {
assert.equal(sender_dom, 'example.com');
assert.deepEqual(rcpt_doms, ['test1.com']);
done();
},
connection);
});

it('gets the recipient domains', function (done) {
connection.transaction.mail_from = new Address('<johndoe@example.com>');
connection.transaction.rcpt_to.push(new Address('<jane@test1.com>'));
connection.transaction.rcpt_to.push(new Address('<jane@test2.com>'));

plugin.after_queue(function (undefined, sender_dom, rcpt_doms) {
assert.equal(sender_dom, 'example.com');
assert.deepEqual(rcpt_doms, ['test1.com', 'test2.com']);
done();
},
connection);
});
});

0 comments on commit 7c8639b

Please sign in to comment.