From 80cb19b3109c5893eef79ff1310f19c1ab34dde8 Mon Sep 17 00:00:00 2001 From: Andrew Lewis Date: Mon, 12 Dec 2016 14:08:08 +0200 Subject: [PATCH] [Feature] rmilter_headers: authentication-results (#78) --- src/plugins/lua/rmilter_headers.lua | 123 +++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/src/plugins/lua/rmilter_headers.lua b/src/plugins/lua/rmilter_headers.lua index 9e2f99ac1..98a778058 100644 --- a/src/plugins/lua/rmilter_headers.lua +++ b/src/plugins/lua/rmilter_headers.lua @@ -38,6 +38,35 @@ local settings = { header = 'X-Spam-Status', remove = 1, }, + ['authentication-results'] = { + header = 'Authentication-Results', + remove = 1, + spf_symbols = { + pass = 'R_SPF_ALLOW', + fail = 'R_SPF_FAIL', + softfail = 'R_SPF_SOFTFAIL', + neutral = 'R_SPF_NEUTRAL', + temperror = 'R_SPF_DNSFAIL', + none = 'R_SPF_NA', + permerror = 'R_SPF_PERMFAIL', + }, + dkim_symbols = { + pass = 'R_DKIM_ALLOW', + fail = 'R_DKIM_REJECT', + temperror = 'R_DKIM_TEMPFAIL', + none = 'R_DKIM_NA', + permerror = 'R_DKIM_PERMFAIL', + }, + dmarc_symbols = { + pass = 'DMARC_POLICY_ALLOW', + permerror = 'DMARC_BAD_POLICY', + temperror = 'DMARC_DNSFAIL', + none = 'DMARC_NA', + reject = 'DMARC_POLICY_REJECT', + softfail = 'DMARC_POLICY_SOFTFAIL', + quarantine = 'DMARC_POLICY_QUARANTINE', + }, + }, }, } @@ -112,6 +141,92 @@ routines['x-spam-status'] = function(task, common_meta) return nil, add, remove, common end +routines['authentication-results'] = function(task, common_meta) + local add, remove, auth_results, hdr_parts = {}, {}, {}, {} + local common = {symbols = {}} + local auth_types = { + dkim = settings.routines['authentication-results'].dkim_symbols, + dmarc = settings.routines['authentication-results'].dmarc_symbols, + spf = settings.routines['authentication-results'].spf_symbols, + } + if not common_meta.symbols then common_meta.symbols = {} end + for auth_type, symbols in pairs(auth_types) do + for key, sym in pairs(symbols) do + if not (common_meta.symbols[sym] == false) then + local s = task:get_symbol(sym) + if not s then + common_meta.symbols[sym] = false + common.symbols[sym] = false + else + common_meta.symbols[sym] = s + common.symbols[sym] = s + if not auth_results[auth_type] then + auth_results[auth_type] = {key} + else + table.insert(auth_results[auth_type], key) + end + if auth_type ~= 'dkim' then + break + end + end + end + end + end + if settings.routines['authentication-results'].remove then + remove[settings.routines['authentication-results'].header] = settings.routines['authentication-results'].remove + end + for auth_type, keys in pairs(auth_results) do + for _, key in ipairs(keys) do + local hdr = '' + if auth_type == 'dmarc' and key ~= 'none' then + hdr = hdr .. 'dmarc=' + if key == 'reject' or key == 'quarantine' or key == 'softfail' then + hdr = hdr .. 'fail' + else + hdr = hdr .. key + end + if key == 'pass' then + hdr = hdr .. ' policy=' .. common_meta.symbols[auth_types['dmarc'][key]][1]['options'][2] + hdr = hdr .. ' header.from=' .. common_meta.symbols[auth_types['dmarc'][key]][1]['options'][1] + elseif key ~= 'none' then + local dom, rsn = rspamd_str_split(common_meta.symbols[auth_types['dmarc'][key]][1]['options'][1], ' : ') + hdr = hdr .. ' reason="' .. rsn .. '"' + hdr = hdr .. ' header.from=' .. dom + if key == 'softfail' then + hdr = hdr .. ' policy=none' + else + hdr = hdr .. ' policy=' .. key + end + end + table.insert(hdr_parts, hdr) + elseif auth_type == 'dkim' and key ~= 'none' then + if common_meta.symbols[auth_types['dkim'][key]][1] then + for _, v in ipairs(common_meta.symbols[auth_types['dkim'][key]][1]['options']) do + hdr = hdr .. auth_type .. '=' .. key .. ' header.d=' .. v + table.insert(hdr_parts, hdr) + end + end + elseif auth_type == 'spf' and key ~= 'none' then + hdr = hdr .. auth_type .. '=' .. key + local smtp_from = task:get_from('smtp') + if smtp_from['addr'] ~= '' and smtp_from['addr'] ~= nil then + hdr = hdr .. ' smtp.mailfrom=' .. smtp_from['addr'] + else + local helo = task:get_helo() + if helo then + hdr = hdr .. ' smtp.helo=' .. task:get_helo() + end + end + table.insert(hdr_parts, hdr) + end + end + end + if #hdr_parts > 0 then + add[settings.routines['authentication-results'].header] = table.concat(hdr_parts, '; ') + end + return nil, add, remove, common +end + local function rmilter_headers(task) local common_meta, to_add, to_remove = {}, {}, {} for n, f in pairs(active_routines) do @@ -126,7 +241,13 @@ local function rmilter_headers(task) to_remove[k] = v end for k, v in pairs(common) do - common_meta[k] = v + if type(v) == 'table' then + for sk, sv in pairs(v) do + common_meta[k][sk] = sv + end + else + common_meta[k] = v + end end end end -- 2.39.5