<commit_before>// bounce tests

exports.register = function () {
    this.register_hook('mail',         'bounce_mail');
    this.register_hook('data',         'bounce_data');
};

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.main.reject_all)
        return next(DENY, "No bounces accepted here");
    return next();
}

exports.bounce_data = 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.main.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.transaction.notes.bounce='invalid';
    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;
<commit_msg>bounce: removed return-path header check<commit_after>// bounce tests

exports.register = function () {
    this.register_hook('mail',         'bounce_mail');
    this.register_hook('data',         'bounce_data');
};

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.main.reject_all) return next(DENY, "No bounces accepted here");
    return next();
}

exports.bounce_data = 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.main.reject_invalid;

    var err = has_single_recipient(connection, plugin);
    if (err && rej) return next(DENY, err);

    return next();
};

function has_single_recipient(connection, plugin) {
    if (connection.transaction.rcpt_to.length === 1) return;

    // Valid bounces have a single recipient
{'fraction_non_alphanumeric': 0.1363813989839781, 'fraction_numerical': 0.004689331770222743, 'mean_word_length': 3.547069271758437, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2924101', 'n_tokens_mistral': 823, 'n_tokens_neox': 783, 'n_words': 213}