Haraka icon indicating copy to clipboard operation
Haraka copied to clipboard

Overwrite Return-Path for the outbound emails

Open wasifahmad opened this issue 3 years ago • 7 comments

There is no way I am able to overwrite the Return-Path! Below is my code for the custom plugin. Any help will be appreciated. So far, I love haraka.

exports.hook_data_post = function (next, connection) {
    var txn = connection.transaction;
    txn.remove_header('Return-Path');
    // Add a new one
    txn.add_header('Return-Path', '<[email protected]>');

    return next();
}

wasifahmad avatar May 15 '21 20:05 wasifahmad

I believe what I need here is, to add a header at the top of DATA. Otherwise, Return-Path will be duplicated!

wasifahmad avatar May 17 '21 01:05 wasifahmad

I believe what I need here is, to add a header at the top of DATA

Have you seen add_leading_header?

msimerson avatar May 17 '21 19:05 msimerson

Yes, it didn't work!

wasifahmad avatar May 20 '21 16:05 wasifahmad

On Thu, May 20, 2021 at 09:01:24-0700, Wasif Ahmad wrote:

Yes, it didn't work! Folks, the return-path is not a classical header you can freely edit/add/remove. It's added by the receiving MTA and its contents is the value from the SMTP session MAIL FROM command.

You can't just add that header. You need to change your outbound RCPT FROM in a plugin you code.

It is located in connection.transaction.mail_from and is an Address object from the Haraka/address module.

HTH

-- Endre

endreszabo avatar May 20 '21 17:05 endreszabo

I am configuring/tweaking haraka to act as a middleware between my MTA server and the Application Server. So my app pushes the emails to haraka and goes through several checks, and then finally the packet is pushed to MTA. Now in my case, I have both headers sent to haraka i.e. Return-Path and From. In my case, both are different mostly. So I am setting up haraka to fetch the MailFrom and match across the whitelist file. If found then push as it is, if didn't find then change it to my set value so the SPF doesn't fail.

Also, I've noticed, haraka has rcpt and mail_from hooks that are excellent but it should also have a very important hook -> send_from. As return-path just becomes equal to the send_from email when there is no Return-Path value set by the actual sender. e.g, if I put the SMTP in my outlook, so my return-path will be my own email address by default. But when I use advanced applications, it allows us to set the return-path ourselves which is great. So here, haraka fails to distinguish between Return-Path and From emails. So to make things easy, we should have a hook that returns you send_from email address so we can deny incoming emails and return the correct reason.

For now, I did custom coding for it but it doesn't return the deny message to the user that I've set. It just logs the message

const haddr     = require('address-rfc2822');

exports.register = function () {
    const plugin = this;
    plugin.register_hook('data_post', 'send_from_access');
}

exports.init_config = function () {
    const plugin = this;

    plugin.cfg = {
        deny_msg: {
            send: 'The From email is unauthorized to relay emails',
        },
        white: {
            send: 'send_from.access.whitelist',
        },
     };
}

exports.send_from_access = function (next, connection) {
    const plugin = this;

    const sn_domain = plugin.get_sender_domain(connection);
	
    // address whitelist checks
    let file = plugin.cfg.white.send;
    connection.logdebug(plugin, `checking ${sn_domain} against ${file}`);
    if (!plugin.in_list('white', 'send', sn_domain)) {
        connection.transaction.results.add(plugin, {fail: file, emit: true});
        return next(DENY, `${sn_domain} is not authorized to relay emails`);
    }
    return next();
}

exports.in_list = function (type, phase, address) {
    const plugin = this;
    if (plugin.list[type][phase] === undefined) {
        console.log(`phase not defined: ${phase}`);
        return false;
    }
    if (!address) return false;
    if (plugin.list[type][phase][address.toLowerCase()]) return true;
    return false;
}

exports.get_sender_domain = function (connection) {
    const plugin = this;
    if (!connection.transaction) {
        connection.logerror(plugin, 'no transaction!')
        return;
    }

    const txn = connection.transaction;

    // fallback: use Envelope FROM when header parsing fails
    let domain;
    if (txn.mail_from.host) {
        try { domain = txn.mail_from.host.toLowerCase(); }
        catch (e) {
            connection.logerror(plugin, e);
        }
    }

    // In case of forwarding, only use the Envelope
    if (txn.notes.forward) return domain;
    if (!txn.header) return domain;

    // the DKIM signing key should be aligned with the domain in the From
    // header (see DMARC). Try to parse the domain from there.
    const from_hdr = txn.header.get_decoded('From');
    if (!from_hdr) return domain;

    // The From header can contain multiple addresses and should be
    // parsed as described in RFC 2822 3.6.2.
    let addrs;
    try {
        addrs = haddr.parse(from_hdr);
    }
    catch (e) {
        connection.logerror(plugin, `address-rfc2822 failed to parse From header: ${from_hdr}`)
        return domain;
    }
    if (!addrs || ! addrs.length) return domain;

    // If From has a single address, we're done
    if (addrs.length === 1 && addrs[0].host) {
        let fromHost = addrs[0].host();
        if (fromHost) {
            // don't attempt to lower a null or undefined value #1575
            fromHost = fromHost.toLowerCase();
        }
        return fromHost;
    }

    // If From has multiple-addresses, we must parse and
    // use the domain in the Sender header.
    const sender = txn.header.get_decoded('Sender');
    if (sender) {
        try {
            domain = (haddr.parse(sender))[0].host().toLowerCase();
        }
        catch (e) {
            connection.logerror(plugin, e);
        }
    }
    return domain;
}

wasifahmad avatar May 20 '21 17:05 wasifahmad

you can use smtp_forward plugin check this : https://gist.github.com/rogereiddir/c0ae7b029da213261e3f701fba73febb https://github.com/haraka/Haraka/issues/2882

rogereiddir avatar May 20 '21 20:05 rogereiddir

there is verp plugin do rewrite mail_from

exports.register = function() {
  var plugin = this;
  plugin.register_hook('data_post', 'set_verp_mail_from');
};

exports.set_verp_mail_from = function (next, connection) {
  connection.transaction.parse_body = true;
  var transaction = connection.transaction;
  var token = transaction.uuid.split("-")[0];
  var verp = ("bounces+" + token + "-" + transaction.rcpt_to[0].original).replace(/@/,"=").replace(/>/,"").replace(/</,"") + '@' + 'your-email-domain.com';
  transaction.mail_from = verp;
  next();
};

ajay-psd avatar Jun 29 '21 13:06 ajay-psd