]> source.dussan.org Git - rspamd.git/commitdiff
[Minor] More rework in renaming rmilter -> milter
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 2 Jun 2017 14:48:45 +0000 (15:48 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 2 Jun 2017 14:53:34 +0000 (15:53 +0100)
conf/modules.d/milter_headers.conf [new file with mode: 0644]
conf/modules.d/rmilter_headers.conf [deleted file]
src/plugins/lua/milter_headers.lua [new file with mode: 0644]
src/plugins/lua/rmilter_headers.lua [deleted file]

diff --git a/conf/modules.d/milter_headers.conf b/conf/modules.d/milter_headers.conf
new file mode 100644 (file)
index 0000000..49eef69
--- /dev/null
@@ -0,0 +1,30 @@
+# Please don't modify this file as your changes might be overwritten with
+# the next update.
+#
+# You can modify '$LOCAL_CONFDIR/rspamd.conf.local.override' to redefine
+# parameters defined on the top level
+#
+# You can modify '$LOCAL_CONFDIR/rspamd.conf.local' to add
+# parameters defined on the top level
+#
+# For specific modules or configuration you can also modify
+# '$LOCAL_CONFDIR/local.d/file.conf' - to add your options or rewrite defaults
+# '$LOCAL_CONFDIR/override.d/file.conf' - to override the defaults
+#
+# See https://rspamd.com/doc/tutorials/writing_rules.html for details
+
+rmilter_headers {
+
+  # Refer to https://rspamd.com/doc/modules/milter_headers.html for information on configuration
+
+  use = [];
+
+  # Compatibility
+  .include(try=true,priority=5) "${DBDIR}/dynamic/rmilter_headers.conf"
+  .include(try=true,priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/rmilter_headers.conf"
+  .include(try=true,priority=10) "$LOCAL_CONFDIR/override.d/rmilter_headers.conf"
+
+  .include(try=true,priority=5) "${DBDIR}/dynamic/milter_headers.conf"
+  .include(try=true,priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/milter_headers.conf"
+  .include(try=true,priority=10) "$LOCAL_CONFDIR/override.d/milter_headers.conf"
+}
diff --git a/conf/modules.d/rmilter_headers.conf b/conf/modules.d/rmilter_headers.conf
deleted file mode 100644 (file)
index 432057e..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-# Please don't modify this file as your changes might be overwritten with
-# the next update.
-#
-# You can modify '$LOCAL_CONFDIR/rspamd.conf.local.override' to redefine
-# parameters defined on the top level
-#
-# You can modify '$LOCAL_CONFDIR/rspamd.conf.local' to add
-# parameters defined on the top level
-#
-# For specific modules or configuration you can also modify
-# '$LOCAL_CONFDIR/local.d/file.conf' - to add your options or rewrite defaults
-# '$LOCAL_CONFDIR/override.d/file.conf' - to override the defaults
-#
-# See https://rspamd.com/doc/tutorials/writing_rules.html for details
-
-rmilter_headers {
-
-  # Refer to https://rspamd.com/doc/modules/rmilter_headers.html for information on configuration
-
-  use = [];
-
-  .include(try=true,priority=5) "${DBDIR}/dynamic/rmilter_headers.conf"
-  .include(try=true,priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/rmilter_headers.conf"
-  .include(try=true,priority=10) "$LOCAL_CONFDIR/override.d/rmilter_headers.conf"
-}
diff --git a/src/plugins/lua/milter_headers.lua b/src/plugins/lua/milter_headers.lua
new file mode 100644 (file)
index 0000000..7447cd2
--- /dev/null
@@ -0,0 +1,370 @@
+--[[
+Copyright (c) 2016, Andrew Lewis <nerf@judo.za.org>
+Copyright (c) 2016, Vsevolod Stakhov <vsevolod@highsecure.ru>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+]]--
+
+if confighelp then
+  return
+end
+
+-- A plugin that provides common header manipulations
+
+local logger = require "rspamd_logger"
+local util = require "rspamd_util"
+local N = 'milter_headers'
+local E = {}
+
+local HOSTNAME = util.get_hostname()
+
+local settings = {
+  routines = {
+    ['x-spamd-result'] = {
+      header = 'X-Spamd-Result',
+      remove = 1,
+    },
+    ['x-rspamd-server'] = {
+      header = 'X-Rspamd-Server',
+      remove = 1,
+    },
+    ['x-rspamd-queue-id'] = {
+      header = 'X-Rspamd-Queue-Id',
+      remove = 1,
+    },
+    ['spam-header'] = {
+      header = 'Deliver-To',
+      value = 'Junk',
+      remove = 1,
+    },
+    ['x-virus'] = {
+      header = 'X-Virus',
+      remove = 1,
+      symbols = {}, -- needs config
+    },
+    ['x-spamd-bar'] = {
+      header = 'X-Spamd-Bar',
+      positive = '+',
+      negative = '-',
+      neutral = '/',
+      remove = 1,
+    },
+    ['x-spam-level'] = {
+      header = 'X-Spam-Level',
+      char = '*',
+      remove = 1,
+    },
+    ['x-spam-status'] = {
+      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',
+      },
+    },
+  },
+}
+
+local active_routines = {}
+local custom_routines = {}
+
+local function milter_headers(task)
+
+  local routines, common, add, remove = {}, {}, {}, {}
+
+  routines['x-spamd-result'] = function()
+    if not common.symbols then
+      common.symbols = task:get_symbols_all()
+      common['metric_score'] = task:get_metric_score('default')
+      common['metric_action'] = task:get_metric_action('default')
+    end
+    if settings.routines['x-spamd-result'].remove then
+      remove[settings.routines['x-spamd-result'].header] = settings.routines['x-spamd-result'].remove
+    end
+    local buf = {}
+    table.insert(buf, table.concat({
+      'default: ', (common['metric_action'] == 'reject') and 'True' or 'False', ' [',
+      common['metric_score'][1], ' / ', common['metric_score'][2], ']'
+    }))
+    for _, s in ipairs(common.symbols) do
+      if not s.options then s.options = {} end
+      table.insert(buf, table.concat({
+        ' ', s.name, ' (', s.score, ') [', table.concat(s.options, ','), ']',
+      }))
+    end
+    add[settings.routines['x-spamd-result'].header] = table.concat(buf, '\n')
+  end
+
+  routines['x-rspamd-queue-id'] = function()
+    if common.queue_id ~= false then
+      common.queue_id = task:get_queue_id()
+      if not common.queue_id then
+        common.queue_id = false
+      end
+    end
+    if settings.routines['x-rspamd-queue-id'].remove then
+      remove[settings.routines['x-rspamd-queue-id'].header] = settings.routines['x-rspamd-queue-id'].remove
+    end
+    if common.queue_id then
+      add[settings.routines['x-rspamd-queue-id'].header] = common.queue_id
+    end
+  end
+
+  routines['x-rspamd-server'] = function()
+    if settings.routines['x-rspamd-server'].remove then
+      remove[settings.routines['x-rspamd-server'].header] = settings.routines['x-rspamd-server'].remove
+    end
+    add[settings.routines['x-rspamd-server'].header] = HOSTNAME
+  end
+
+  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
+
+  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
+
+  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
+
+  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
+
+  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
+
+  routines['authentication-results'] = function()
+    local ar = require "auth_results"
+
+    if settings.routines['authentication-results'].remove then
+      remove[settings.routines['authentication-results'].header] =
+          settings.routines['authentication-results'].remove
+    end
+
+    local res = ar.gen_auth_results(task,
+      settings.routines['authentication-results'])
+
+    if res then
+      add[settings.routines['authentication-results'].header] = res
+    end
+  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
+        for k, v in pairs(to_remove) do
+          add[k] = v
+        end
+        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
+      end
+    else
+      ok, err = pcall(routines[n])
+    end
+    if not ok then
+      logger.errx(task, 'call to %s failed: %s', n, err)
+    end
+  end
+
+  if not next(add) then add = nil end
+  if not next(remove) then remove = nil end
+  if add or remove then
+    task:set_milter_reply({
+      add_headers = add,
+      remove_headers = remove
+    })
+  end
+end
+
+local opts = rspamd_config:get_all_opt(N) or rspamd_config:get_all_opt('rmilter_headers')
+if not opts then return end
+
+if type(opts['use']) == 'string' then
+  opts['use'] = {opts['use']}
+elseif (type(opts['use']) == 'table' and not opts['use'][1]) then
+  logger.debugm(N, rspamd_config, 'no functions are enabled')
+  return
+end
+if type(opts['use']) ~= 'table' then
+  logger.errx(rspamd_config, 'unexpected type for "use" option: %s', type(opts['use']))
+  return
+end
+if type(opts['custom']) == 'table' then
+  for k, v in pairs(opts['custom']) do
+    local f, err = load(v)
+    if not f then
+      logger.errx(rspamd_config, 'could not load "%s": %s', k, err)
+    else
+      custom_routines[k] = f()
+    end
+  end
+end
+local have_routine = {}
+local function activate_routine(s)
+  if settings.routines[s] or custom_routines[s] then
+    have_routine[s] = true
+    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 opts['extended_spam_headers'] then
+  activate_routine('x-spamd-result')
+  activate_routine('x-rspamd-server')
+  activate_routine('x-rspamd-queue-id')
+end
+for _, s in ipairs(opts['use']) do
+  if not have_routine[s] then
+    activate_routine(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 = 'MILTER_HEADERS',
+  type = 'postfilter',
+  callback = milter_headers,
+  priority = 10
+})
diff --git a/src/plugins/lua/rmilter_headers.lua b/src/plugins/lua/rmilter_headers.lua
deleted file mode 100644 (file)
index 76002b7..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
---[[
-Copyright (c) 2016, Andrew Lewis <nerf@judo.za.org>
-Copyright (c) 2016, Vsevolod Stakhov <vsevolod@highsecure.ru>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-]]--
-
-if confighelp then
-  return
-end
-
--- A plugin that provides common header manipulations
-
-local logger = require "rspamd_logger"
-local util = require "rspamd_util"
-local N = 'rmilter_headers'
-local E = {}
-
-local HOSTNAME = util.get_hostname()
-
-local settings = {
-  routines = {
-    ['x-spamd-result'] = {
-      header = 'X-Spamd-Result',
-      remove = 1,
-    },
-    ['x-rspamd-server'] = {
-      header = 'X-Rspamd-Server',
-      remove = 1,
-    },
-    ['x-rspamd-queue-id'] = {
-      header = 'X-Rspamd-Queue-Id',
-      remove = 1,
-    },
-    ['spam-header'] = {
-      header = 'Deliver-To',
-      value = 'Junk',
-      remove = 1,
-    },
-    ['x-virus'] = {
-      header = 'X-Virus',
-      remove = 1,
-      symbols = {}, -- needs config
-    },
-    ['x-spamd-bar'] = {
-      header = 'X-Spamd-Bar',
-      positive = '+',
-      negative = '-',
-      neutral = '/',
-      remove = 1,
-    },
-    ['x-spam-level'] = {
-      header = 'X-Spam-Level',
-      char = '*',
-      remove = 1,
-    },
-    ['x-spam-status'] = {
-      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',
-      },
-    },
-  },
-}
-
-local active_routines = {}
-local custom_routines = {}
-
-local function rmilter_headers(task)
-
-  local routines, common, add, remove = {}, {}, {}, {}
-
-  routines['x-spamd-result'] = function()
-    if not common.symbols then
-      common.symbols = task:get_symbols_all()
-      common['metric_score'] = task:get_metric_score('default')
-      common['metric_action'] = task:get_metric_action('default')
-    end
-    if settings.routines['x-spamd-result'].remove then
-      remove[settings.routines['x-spamd-result'].header] = settings.routines['x-spamd-result'].remove
-    end
-    local buf = {}
-    table.insert(buf, table.concat({
-      'default: ', (common['metric_action'] == 'reject') and 'True' or 'False', ' [',
-      common['metric_score'][1], ' / ', common['metric_score'][2], ']'
-    }))
-    for _, s in ipairs(common.symbols) do
-      if not s.options then s.options = {} end
-      table.insert(buf, table.concat({
-        ' ', s.name, ' (', s.score, ') [', table.concat(s.options, ','), ']',
-      }))
-    end
-    add[settings.routines['x-spamd-result'].header] = table.concat(buf, '\n')
-  end
-
-  routines['x-rspamd-queue-id'] = function()
-    if common.queue_id ~= false then
-      common.queue_id = task:get_queue_id()
-      if not common.queue_id then
-        common.queue_id = false
-      end
-    end
-    if settings.routines['x-rspamd-queue-id'].remove then
-      remove[settings.routines['x-rspamd-queue-id'].header] = settings.routines['x-rspamd-queue-id'].remove
-    end
-    if common.queue_id then
-      add[settings.routines['x-rspamd-queue-id'].header] = common.queue_id
-    end
-  end
-
-  routines['x-rspamd-server'] = function()
-    if settings.routines['x-rspamd-server'].remove then
-      remove[settings.routines['x-rspamd-server'].header] = settings.routines['x-rspamd-server'].remove
-    end
-    add[settings.routines['x-rspamd-server'].header] = HOSTNAME
-  end
-
-  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
-
-  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
-
-  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
-
-  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
-
-  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
-
-  routines['authentication-results'] = function()
-    local ar = require "auth_results"
-
-    if settings.routines['authentication-results'].remove then
-      remove[settings.routines['authentication-results'].header] =
-          settings.routines['authentication-results'].remove
-    end
-
-    local res = ar.gen_auth_results(task,
-      settings.routines['authentication-results'])
-
-    if res then
-      add[settings.routines['authentication-results'].header] = res
-    end
-  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
-        for k, v in pairs(to_remove) do
-          add[k] = v
-        end
-        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
-      end
-    else
-      ok, err = pcall(routines[n])
-    end
-    if not ok then
-      logger.errx(task, 'call to %s failed: %s', n, err)
-    end
-  end
-
-  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 = add,
-      remove_headers = remove
-    })
-  end
-end
-
-local opts = rspamd_config:get_all_opt(N)
-if not opts then return end
-if type(opts['use']) == 'string' then
-  opts['use'] = {opts['use']}
-elseif (type(opts['use']) == 'table' and not opts['use'][1]) then
-  logger.debugm(N, rspamd_config, 'no functions are enabled')
-  return
-end
-if type(opts['use']) ~= 'table' then
-  logger.errx(rspamd_config, 'unexpected type for "use" option: %s', type(opts['use']))
-  return
-end
-if type(opts['custom']) == 'table' then
-  for k, v in pairs(opts['custom']) do
-    local f, err = load(v)
-    if not f then
-      logger.errx(rspamd_config, 'could not load "%s": %s', k, err)
-    else
-      custom_routines[k] = f()
-    end
-  end
-end
-local have_routine = {}
-local function activate_routine(s)
-  if settings.routines[s] or custom_routines[s] then
-    have_routine[s] = true
-    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 opts['extended_spam_headers'] then
-  activate_routine('x-spamd-result')
-  activate_routine('x-rspamd-server')
-  activate_routine('x-rspamd-queue-id')
-end
-for _, s in ipairs(opts['use']) do
-  if not have_routine[s] then
-    activate_routine(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',
-  callback = rmilter_headers,
-  priority = 10
-})