Skip to content

Instantly share code, notes, and snippets.

@sriccio

sriccio/index.js Secret

Last active November 16, 2023 14:19
Show Gist options
  • Save sriccio/fd79e3040bc38c514fbb404d38628af7 to your computer and use it in GitHub Desktop.
Save sriccio/fd79e3040bc38c514fbb404d38628af7 to your computer and use it in GitHub Desktop.
address verification attempt
'use strict'
// TODO: Replace absolute path
const smtp_client_module = require('/usr/lib/node_modules/Haraka/smtp_client.js');
exports.register = function () {
this.inherits('haraka-plugin-redis');
this.load_config();
// Skip if explicitly disabled
if (!this.cfg.main.enabled) {
this.loginfo("Module is explicitly disabled!");
return;
}
this.merge_redis_ini();
this.register_hook('init_master', 'init_redis_plugin');
this.register_hook('init_child', 'init_redis_plugin');
this.register_hook('rcpt', 'rcpt_hook');
}
exports.load_config = function () {
const plugin = this
plugin.cfg = plugin.config.get('recipient-routes-probe.ini', {
booleans: [
'+enabled',
]
},
() => {
plugin.load_config();
}
);
// set default cache ttl
plugin.cfg.cache.ttl = this.cfg.cache.ttl || 14400;
plugin.cfg.cache.negative_ttl = this.cfg.cache.negative_ttl || 120;
// TODO: Remove debug
this.loginfo("cache.ttl: " + plugin.cfg.cache.ttl);
this.loginfo("cache.negative_ttl: " + plugin.cfg.cache.negative_ttl);
}
exports.get_rcpt_address = function (rcpt) {
if (!rcpt.host) return [ rcpt.address().toLowerCase() ];
return [ rcpt.address().toLowerCase(), rcpt.host.toLowerCase() ];
}
exports.probe_recipient = function(connection, cfg, address) {
const plugin = this;
const txn = connection?.transaction;
let success = false;
// this.loginfo("Connection: " + JSON.stringify(connection));
// this.loginfo("Plugin: " + JSON.stringify(plugin));
// this.loginfo("Target server: " + JSON.stringify(cfg));
// Probe target MX
smtp_client_module.get_client_plugin(plugin, connection, cfg, (err, smtp_client) => {
// smtp_client.next = next;
function get_rs () {
if (txn) return txn.results;
return connection.results;
}
function dead_sender () {
if (smtp_client.is_dead_sender(plugin, connection)) {
get_rs().add(plugin, { err: 'dead sender' });
return true;
}
return false;
}
smtp_client.on('rcpt', () => {
// Recipient accepted
success = true;
smtp_client.release();
});
smtp_client.on('mail', () => {
// Send RCPT
smtp_client.send_command('RCPT', `TO: ${address}`);
});
smtp_client.on('rset', () => {
// Send FROM
smtp_client.send_command('MAIL', `FROM: <probe@mx1-ng.swisscenter.com>`);
});
smtp_client.on('bad_code', () => {
// Something went wrong
smtp_client.release();
});
});
return success;
}
exports.shutdown = function () {
if (this.db) this.db.quit();
}
exports.rcpt_hook = async function (next, connection, params) {
const txn = connection.transaction;
// Skip if no transaction available
if (!txn) return next();
// Skip if no domain is found in RCPT address
const [address, domain] = this.get_rcpt_address(params[0]);
if (!domain) {
txn.results.add(this, {fail: 'rcpt!domain'});
return next();
}
// All fine until now
this.loginfo("Recipient address: " + address);
this.loginfo("Recipient domain: " + domain);
let target_mx = { host: 'mail01.swisscenter.com', 'port': 22 };
// Check if recipient is accepted by target MX
if (this.probe_recipient(connection, target_mx, address)) {
this.loginfo("Recipient " + address + " ACCEPTED by target MX " + target_mx['host'] + ':' + target_mx['port']);
} else {
this.loginfo("Recipient " + address + " REJECTED by target MX " + target_mx['host'] + ':' + target_mx['port']);
}
// Fire next hook
next();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment