aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorAndrew Lewis <nerf@judo.za.org>2017-01-20 11:30:36 +0200
committerAndrew Lewis <nerf@judo.za.org>2017-01-20 11:30:36 +0200
commit5791ea36ec234aabcd4fb8d4c9bb0b7ddb08209d (patch)
tree705913f3fd6eb2cbe3afd1fd8d3429e0fd340c79 /src/plugins
parentf33a30cb3ebfc38245b0a1b5f77771d266a08d41 (diff)
downloadrspamd-5791ea36ec234aabcd4fb8d4c9bb0b7ddb08209d.tar.gz
rspamd-5791ea36ec234aabcd4fb8d4c9bb0b7ddb08209d.zip
[Minor] Rework rmilter headers internal functions
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/lua/rmilter_headers.lua427
1 files changed, 209 insertions, 218 deletions
diff --git a/src/plugins/lua/rmilter_headers.lua b/src/plugins/lua/rmilter_headers.lua
index d8083ea70..86acaf950 100644
--- a/src/plugins/lua/rmilter_headers.lua
+++ b/src/plugins/lua/rmilter_headers.lua
@@ -82,246 +82,236 @@ local settings = {
}
local active_routines = {}
-local routines = {}
+local custom_routines = {}
-routines['x-spamd-bar'] = function(task, common_meta)
- local common, add, remove = {}, {}, {}
- if not common_meta['metric_score'] then
- common['metric_score'] = task:get_metric_score('default')
- common_meta['metric_score'] = common['metric_score']
- end
- local score = common_meta['metric_score'][1]
- local spambar
- if score <= -1 then
- spambar = string.rep(settings.routines['x-spamd-bar'].negative, score*-1)
- elseif score >= 1 then
- spambar = string.rep(settings.routines['x-spamd-bar'].positive, score)
- else
- spambar = settings.routines['x-spamd-bar'].neutral
- end
- if settings.routines['x-spamd-bar'].remove then
- remove[settings.routines['x-spamd-bar'].header] = settings.routines['x-spamd-bar'].remove
- end
- if spambar ~= '' then
- add[settings.routines['x-spamd-bar'].header] = spambar
- end
- return nil, add, remove, common
-end
+local function rmilter_headers(task)
-routines['x-spam-level'] = function(task, common_meta)
- local common, add, remove = {}, {}, {}
- if not common_meta['metric_score'] then
- common['metric_score'] = task:get_metric_score('default')
- common_meta['metric_score'] = common['metric_score']
- end
- local score = common_meta['metric_score'][1]
- if score < 1 then
- return nil, {}, {}, common
- end
- if settings.routines['x-spam-level'].remove then
- remove[settings.routines['x-spam-level'].header] = settings.routines['x-spam-level'].remove
- end
- add[settings.routines['x-spam-level'].header] = string.rep(settings.routines['x-spam-level'].char, score)
- return nil, add, remove, common
-end
+ local routines, common, add, remove = {}, {}, {}, {}
-routines['spam-header'] = function(task, common_meta)
- local common, add, remove = {}, {}, {}
- if not common_meta['metric_action'] then
- common['metric_action'] = task:get_metric_action('default')
- common_meta['metric_action'] = common['metric_action']
- end
- if settings.routines['spam-header'].remove then
- remove[settings.routines['spam-header'].header] = settings.routines['spam-header'].remove
- end
- local action = common_meta['metric_action']
- if action ~= 'no action' and action ~= 'greylist' then
- add[settings.routines['spam-header'].header] = settings.routines['spam-header'].value
+ routines['x-spamd-bar'] = function()
+ if not common['metric_score'] then
+ common['metric_score'] = task:get_metric_score('default')
+ end
+ local score = common['metric_score'][1]
+ local spambar
+ if score <= -1 then
+ spambar = string.rep(settings.routines['x-spamd-bar'].negative, score*-1)
+ elseif score >= 1 then
+ spambar = string.rep(settings.routines['x-spamd-bar'].positive, score)
+ else
+ spambar = settings.routines['x-spamd-bar'].neutral
+ end
+ if settings.routines['x-spamd-bar'].remove then
+ remove[settings.routines['x-spamd-bar'].header] = settings.routines['x-spamd-bar'].remove
+ end
+ if spambar ~= '' then
+ add[settings.routines['x-spamd-bar'].header] = spambar
+ end
end
- return nil, add, remove, common
-end
-routines['x-virus'] = function(task, common_meta)
- local add, remove = {}, {}
- local common = {symbols = {}}
- if not common_meta.symbols then
- common_meta.symbols = {}
+ routines['x-spam-level'] = function()
+ if not common['metric_score'] then
+ common['metric_score'] = task:get_metric_score('default')
+ end
+ local score = common['metric_score'][1]
+ if score < 1 then
+ return nil, {}, {}
+ end
+ if settings.routines['x-spam-level'].remove then
+ remove[settings.routines['x-spam-level'].header] = settings.routines['x-spam-level'].remove
+ end
+ add[settings.routines['x-spam-level'].header] = string.rep(settings.routines['x-spam-level'].char, score)
end
- if settings.routines['x-virus'].remove then
- remove[settings.routines['x-virus'].header] = settings.routines['x-virus'].remove
+
+ routines['spam-header'] = function()
+ if not common['metric_action'] then
+ common['metric_action'] = task:get_metric_action('default')
+ end
+ if settings.routines['spam-header'].remove then
+ remove[settings.routines['spam-header'].header] = settings.routines['spam-header'].remove
+ end
+ local action = common['metric_action']
+ if action ~= 'no action' and action ~= 'greylist' then
+ add[settings.routines['spam-header'].header] = settings.routines['spam-header'].value
+ end
end
- local virii = {}
- for _, sym in ipairs(settings.routines['x-virus'].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[sym] = false
- else
- common_meta.symbols[sym] = s
- common[sym] = s
- if (((s or E)[1] or E).options or E)[1] then
- table.insert(virii, s[1].options[1])
- else
- table.insert(virii, 'unknown')
- end
+
+ routines['x-virus'] = function()
+ if not common.symbols then
+ common.symbols = {}
+ end
+ if settings.routines['x-virus'].remove then
+ remove[settings.routines['x-virus'].header] = settings.routines['x-virus'].remove
+ end
+ local virii = {}
+ for _, sym in ipairs(settings.routines['x-virus'].symbols) do
+ if not (common.symbols[sym] == false) then
+ local s = task:get_symbol(sym)
+ if not s then
+ common.symbols[sym] = false
+ else
+ common.symbols[sym] = s
+ if (((s or E)[1] or E).options or E)[1] then
+ table.insert(virii, s[1].options[1])
+ else
+ table.insert(virii, 'unknown')
+ end
+ end
end
end
+ if #virii > 0 then
+ add[settings.routines['x-virus'].header] = table.concat(virii, ',')
+ end
end
- if #virii > 0 then
- add[settings.routines['x-virus'].header] = table.concat(virii, ',')
- end
- return nil, add, remove, common
-end
-routines['x-spam-status'] = function(task, common_meta)
- local common, add, remove = {}, {}, {}
- if not common_meta['metric_score'] then
- common['metric_score'] = task:get_metric_score('default')
- common_meta['metric_score'] = common['metric_score']
- end
- if not common_meta['metric_action'] then
- common['metric_action'] = task:get_metric_action('default')
- common_meta['metric_action'] = common['metric_action']
- end
- local score = common_meta['metric_score'][1]
- local action = common_meta['metric_action']
- local is_spam
- local spamstatus
- if action ~= 'no action' and action ~= 'greylist' then
- is_spam = 'Yes'
- else
- is_spam = 'No'
- end
- spamstatus = is_spam .. ', score=' .. string.format('%.2f', score)
- if settings.routines['x-spam-status'].remove then
- remove[settings.routines['x-spam-status'].header] = settings.routines['x-spam-status'].remove
+ routines['x-spam-status'] = function()
+ if not common['metric_score'] then
+ common['metric_score'] = task:get_metric_score('default')
+ end
+ if not common['metric_action'] then
+ common['metric_action'] = task:get_metric_action('default')
+ end
+ local score = common['metric_score'][1]
+ local action = common['metric_action']
+ local is_spam
+ local spamstatus
+ if action ~= 'no action' and action ~= 'greylist' then
+ is_spam = 'Yes'
+ else
+ is_spam = 'No'
+ end
+ spamstatus = is_spam .. ', score=' .. string.format('%.2f', score)
+ if settings.routines['x-spam-status'].remove then
+ remove[settings.routines['x-spam-status'].header] = settings.routines['x-spam-status'].remove
+ end
+ add[settings.routines['x-spam-status'].header] = spamstatus
end
- add[settings.routines['x-spam-status'].header] = spamstatus
- 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
+ routines['authentication-results'] = function()
+ local auth_results, hdr_parts = {}, {}
+ if not common.symbols then
+ common.symbols = {}
+ end
+ local auth_types = {
+ dkim = settings.routines['authentication-results'].dkim_symbols,
+ dmarc = settings.routines['authentication-results'].dmarc_symbols,
+ spf = settings.routines['authentication-results'].spf_symbols,
+ }
+ for auth_type, symbols in pairs(auth_types) do
+ for key, sym in pairs(symbols) do
+ if not (common.symbols[sym] == false) then
+ local s = task:get_symbol(sym)
+ if not s then
+ common.symbols[sym] = false
+ else
+ 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.symbols[auth_types['dmarc'][key]][1]['options'][2]
+ hdr = hdr .. ' header.from=' .. common.symbols[auth_types['dmarc'][key]][1]['options'][1]
+ elseif key ~= 'none' then
+ local t = rspamd_str_split(common.symbols[auth_types['dmarc'][key]][1]['options'][1], ' : ')
+ local dom = t[1]
+ local rsn = t[2]
+ 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.symbols[auth_types['dkim'][key]][1] then
+ for _, v in ipairs(common.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
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 t = rspamd_str_split(common_meta.symbols[auth_types['dmarc'][key]][1]['options'][1], ' : ')
- local dom = t[1]
- local rsn = t[2]
- hdr = hdr .. ' reason="' .. rsn .. '"'
- hdr = hdr .. ' header.from=' .. dom
- if key == 'softfail' then
- hdr = hdr .. ' policy=none'
- else
- hdr = hdr .. ' policy=' .. key
- end
+
+ for _, n in ipairs(active_routines) do
+ local ok, err
+ if custom_routines[n] then
+ local to_add, to_remove, common_in
+ ok, err, to_add, to_remove, common_in = pcall(custom_routines[n], task, common)
+ if ok then
+ for k, v in pairs(to_add) do
+ add[k] = v
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
+ for k, v in pairs(to_remove) do
+ add[k] = v
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()
+ for k, v in pairs(common_in) do
+ if type(v) == 'table' then
+ if not common[k] then
+ common[k] = {}
+ end
+ for kk, vv in pairs(v) do
+ common[k][kk] = vv
+ end
+ else
+ common[k] = v
end
end
- table.insert(hdr_parts, hdr)
end
+ else
+ ok, err = pcall(routines[n])
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
- local ok, err, add, remove, common = pcall(routines[f], task, common_meta)
if not ok then
logger.errx(task, 'call to %s failed: %s', n, err)
- else
- for k, v in pairs(add) do
- to_add[k] = v
- end
- for k, v in pairs(remove) do
- to_remove[k] = v
- end
- for k, v in pairs(common) do
- if type(v) == 'table' then
- if not common_meta[k] then
- common_meta[k] = {}
- end
- for sk, sv in pairs(v) do
- common_meta[k][sk] = sv
- end
- else
- common_meta[k] = v
- end
- end
end
end
- if not next(to_add) then to_add = nil end
- if not next(to_remove) then to_remove = nil end
- if to_add or to_remove then
+
+ if not next(add) then add = nil end
+ if not next(remove) then remove = nil end
+ if add or remove then
task:set_rmilter_reply({
- add_headers = to_add,
- remove_headers = to_remove
+ add_headers = add,
+ remove_headers = remove
})
end
end
@@ -338,29 +328,30 @@ end
if type(opts['custom']) == 'table' then
for k, v in pairs(opts['custom']) do
local f, err = load(v)
- if err then
+ if not f then
logger.errx(rspamd_config, 'could not load "%s": %s', k, err)
else
- routines[k] = f
+ custom_routines[k] = f()
end
end
end
for _, s in ipairs(opts['use']) do
- if not routines[s] then
- logger.errx(rspamd_config, 'routine "%s" does not exist', s)
- else
+ if (opts.routines and opts.routines[s]) or custom_routines[s] then
table.insert(active_routines, s)
if (opts.routines and opts.routines[s]) then
for k, v in pairs(opts.routines[s]) do
settings.routines[s][k] = v
end
end
+ else
+ logger.errx(rspamd_config, 'routine "%s" does not exist', s)
end
end
if (#active_routines < 1) then
logger.errx(rspamd_config, 'no active routines')
return
end
+logger.infox(rspamd_config, 'active routines [%s]', table.concat(active_routines, ','))
rspamd_config:register_symbol({
name = 'RMILTER_HEADERS',
type = 'postfilter',