commit a5ed3fe: [Feature] Adopt emails module to use lua_maps

Vsevolod Stakhov vsevolod at highsecure.ru
Tue May 21 16:49:06 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-05-21 17:42:45 +0100
URL: https://github.com/rspamd/rspamd/commit/a5ed3fe51ec10f98a718b59db4ecab8e81aa2462 (HEAD -> master)

[Feature] Adopt emails module to use lua_maps

---
 src/plugins/lua/emails.lua | 210 +++++++++++++++++++++++----------------------
 1 file changed, 109 insertions(+), 101 deletions(-)

diff --git a/src/plugins/lua/emails.lua b/src/plugins/lua/emails.lua
index 778654a3b..aca72cb0a 100644
--- a/src/plugins/lua/emails.lua
+++ b/src/plugins/lua/emails.lua
@@ -28,134 +28,142 @@ local logger = require "rspamd_logger"
 local hash = require "rspamd_cryptobox_hash"
 local rspamd_lua_utils = require "lua_util"
 local util = require "rspamd_util"
+local lua_maps = require "lua_maps"
+local lua_maps_expressions = require "lua_maps_expressions"
 local N = "emails"
 
 -- Check rule for a single email
 local function check_email_rule(task, rule, addr)
   if rule['whitelist'] then
     if rule['whitelist']:get_key(addr.addr)
-      or rule['whitelist']:get_key(addr.domain) then
-        logger.debugm(N, task, "whitelisted address: %s", addr.addr)
-        return
+        or rule['whitelist']:get_key(addr.domain) then
+      logger.debugm(N, task, "whitelisted address: %s", addr.addr)
+      return
+    end
+  elseif rule.whitelist_expr then
+    if rule['whitelist']:process(task) then
+      logger.debugm(N, task, "whitelisted emails processing: %s", addr.addr)
+      return
     end
   end
+
   if rule['dnsbl'] then
-    local email
-    local to_resolve
+      local email
+      local to_resolve
 
-    if rule['domain_only'] then
-      email = addr.domain
-    else
-      email = string.format('%s%s%s', addr.user, rule.delimiter, addr.domain)
-    end
+      if rule['domain_only'] then
+        email = addr.domain
+      else
+        email = string.format('%s%s%s', addr.user, rule.delimiter, addr.domain)
+      end
 
-    email = email:lower()
-
-    local function emails_dns_cb(_, _, results, err)
-      if err and (err ~= 'requested record is not found'
-          and err ~= 'no records with this name') then
-        logger.errx(task, 'Error querying DNS(%s.%s): %s', to_resolve,
-            rule['dnsbl'], err)
-      elseif results then
-        local expected_found = false
-        local symbol = rule['symbol']
-
-        local function check_ip(ip)
-          for _,result in ipairs(results) do
-            local ipstr = result:to_string()
-            if ipstr == ip then
-              return true
+      email = email:lower()
+
+      local function emails_dns_cb(_, _, results, err)
+        if err and (err ~= 'requested record is not found'
+            and err ~= 'no records with this name') then
+          logger.errx(task, 'Error querying DNS(%s.%s): %s', to_resolve,
+              rule['dnsbl'], err)
+        elseif results then
+          local expected_found = false
+          local symbol = rule['symbol']
+
+          local function check_ip(ip)
+            for _,result in ipairs(results) do
+              local ipstr = result:to_string()
+              if ipstr == ip then
+                return true
+              end
             end
-          end
 
-          return false
-        end
+            return false
+          end
 
-        if rule['expect_ip'] then
-          if check_ip(rule['expect_ip']) then
-            expected_found = true
+          if rule['expect_ip'] then
+            if check_ip(rule['expect_ip']) then
+              expected_found = true
+            end
+          else
+            expected_found = true -- Accept any result
           end
-        else
-          expected_found = true -- Accept any result
-        end
 
-        if rule['returncodes'] then
-          for k,codes in pairs(rule['returncodes']) do
-            if type(codes) == 'table' then
-              for _,code in ipairs(codes) do
-                if check_ip(code) then
+          if rule['returncodes'] then
+            for k,codes in pairs(rule['returncodes']) do
+              if type(codes) == 'table' then
+                for _,code in ipairs(codes) do
+                  if check_ip(code) then
+                    expected_found = true
+                    symbol = k
+                    break
+                  end
+                end
+              else
+                if check_ip(codes) then
                   expected_found = true
                   symbol = k
                   break
                 end
               end
-            else
-              if check_ip(codes) then
-                expected_found = true
-                symbol = k
-                break
-              end
             end
           end
-        end
 
-        if expected_found then
-          if rule['hash'] then
-            task:insert_result(symbol, 1.0, {email, to_resolve})
-          else
-            task:insert_result(symbol, 1.0, email)
+          if expected_found then
+            if rule['hash'] then
+              task:insert_result(symbol, 1.0, {email, to_resolve})
+            else
+              task:insert_result(symbol, 1.0, email)
+            end
           end
-        end
 
+        end
       end
-    end
 
-    logger.debugm(N, task, "check %s on %s", email, rule['dnsbl'])
+      logger.debugm(N, task, "check %s on %s", email, rule['dnsbl'])
 
-    if rule['hash'] then
-      local hkey = hash.create_specific(rule['hash'], email)
+      if rule['hash'] then
+        local hkey = hash.create_specific(rule['hash'], email)
 
-      if rule['encoding'] == 'base32' then
-        to_resolve = hkey:base32()
-      else
-        to_resolve = hkey:hex()
-      end
+        if rule['encoding'] == 'base32' then
+          to_resolve = hkey:base32()
+        else
+          to_resolve = hkey:hex()
+        end
 
-      if rule['hashlen'] and type(rule['hashlen']) == 'number' then
-        if #to_resolve > rule['hashlen'] then
-          to_resolve = string.sub(to_resolve, 1, rule['hashlen'])
+        if rule['hashlen'] and type(rule['hashlen']) == 'number' then
+          if #to_resolve > rule['hashlen'] then
+            to_resolve = string.sub(to_resolve, 1, rule['hashlen'])
+          end
         end
+      else
+        to_resolve = email
       end
-    else
-      to_resolve = email
-    end
 
-    local dns_arg = string.format('%s.%s', to_resolve, rule['dnsbl'])
-
-    logger.debugm(N, task, "query %s", dns_arg)
-
-    task:get_resolver():resolve_a({
-      task=task,
-      name = dns_arg,
-      callback = emails_dns_cb})
-  elseif rule['map'] then
-    if rule['domain_only'] then
-      local key = addr.domain
-      if rule['map']:get_key(key) then
-        task:insert_result(rule['symbol'], 1)
-        logger.infox(task, '<%1> email: \'%2\' is found in list: %3',
-          task:get_message_id(), key, rule['symbol'])
-      end
-    else
-      local key = string.format('%s%s%s', addr.user, rule.delimiter, addr.domain)
-      if rule['map']:get_key(key) then
-        task:insert_result(rule['symbol'], 1)
-        logger.infox(task, '<%1> email: \'%2\' is found in list: %3',
-          task:get_message_id(), key, rule['symbol'])
+      local dns_arg = string.format('%s.%s', to_resolve, rule['dnsbl'])
+
+      logger.debugm(N, task, "query %s", dns_arg)
+
+      task:get_resolver():resolve_a({
+        task=task,
+        name = dns_arg,
+        callback = emails_dns_cb})
+    elseif rule['map'] then
+      if rule['domain_only'] then
+        local key = addr.domain
+        if rule['map']:get_key(key) then
+          task:insert_result(rule['symbol'], 1)
+          logger.infox(task, '<%1> email: \'%2\' is found in list: %3',
+              task:get_message_id(), key, rule['symbol'])
+        end
+      else
+        local key = string.format('%s%s%s', addr.user, rule.delimiter, addr.domain)
+        if rule['map']:get_key(key) then
+          task:insert_result(rule['symbol'], 1)
+          logger.infox(task, '<%1> email: \'%2\' is found in list: %3',
+              task:get_message_id(), key, rule['symbol'])
+        end
       end
     end
   end
-end
 
 -- Check email
 local function gen_check_emails(rule)
@@ -216,20 +224,20 @@ if opts and type(opts) == 'table' then
     end
 
     if rule['whitelist'] then
-      rule['whitelist'] = rspamd_config:add_map({
-        url = rule['whitelist'],
-        description = string.format('Emails rule %s whitelist', rule['symbol']),
-        type = 'set'
-      })
+      if type(rule['whitelist']) == 'string' then
+        rule['whitelist'] = lua_maps.map_add_from_ucl(rule.whitelist,
+            'set', 'Emails rule %s whitelist', rule['symbol'])
+      else
+        rule.whitelist_expr = lua_maps_expressions.create(rspamd_config,
+            rule.whitelist, N)
+        rule.whitelist = nil
+      end
     end
 
     if rule['map'] then
       rule['name'] = rule['map']
-      rule['map'] = rspamd_config:add_map({
-        url = rule['name'],
-        description = string.format('Emails rule %s', rule['symbol']),
-        type = 'regexp'
-      })
+      rule.map = lua_maps.map_add_from_ucl(rule.whitelist,
+          'regexp', 'Emails rule %s whitelist', rule['symbol'])
     end
     if not rule['symbol'] or (not rule['map'] and not rule['dnsbl']) then
       logger.errx(rspamd_config, 'incomplete rule: %s', rule)


More information about the Commits mailing list