summaryrefslogtreecommitdiffstats
path: root/src/plugins/lua/spamtrap.lua
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 21:30:40 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 21:30:40 +0000
commit133a45c109da5310add55824db21af5239951f93 (patch)
treeba6ac4c0a950a0dda56451944315d66409923918 /src/plugins/lua/spamtrap.lua
parentInitial commit. (diff)
downloadrspamd-upstream.tar.xz
rspamd-upstream.zip
Adding upstream version 3.8.1.upstream/3.8.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/plugins/lua/spamtrap.lua200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/plugins/lua/spamtrap.lua b/src/plugins/lua/spamtrap.lua
new file mode 100644
index 0000000..cd3b296
--- /dev/null
+++ b/src/plugins/lua/spamtrap.lua
@@ -0,0 +1,200 @@
+--[[
+Copyright (c) 2022, Vsevolod Stakhov <vsevolod@rspamd.com>
+Copyright (c) 2016, Andrew Lewis <nerf@judo.za.org>
+
+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.
+]]--
+
+-- A plugin that triggers, if a spam trapped email address was detected
+
+local rspamd_logger = require "rspamd_logger"
+local redis_params
+local use_redis = false;
+local M = 'spamtrap'
+local lua_util = require "lua_util"
+local fun = require "fun"
+
+local settings = {
+ symbol = 'SPAMTRAP',
+ score = 0.0,
+ learn_fuzzy = false,
+ learn_spam = false,
+ fuzzy_flag = 1,
+ fuzzy_weight = 10.0,
+ key_prefix = 'sptr_',
+ allow_multiple_rcpts = false,
+}
+
+local check_authed = true
+local check_local = true
+
+local function spamtrap_cb(task)
+ local rcpts = task:get_recipients('smtp')
+ local authed_user = task:get_user()
+ local ip_addr = task:get_ip()
+ local called_for_domain = false
+
+ if ((not check_authed and authed_user) or
+ (not check_local and ip_addr and ip_addr:is_local())) then
+ rspamd_logger.infox(task, "skip spamtrap checks for local networks or authenticated user");
+ return
+ end
+
+ local function do_action(rcpt)
+ if settings['learn_fuzzy'] then
+ rspamd_plugins.fuzzy_check.learn(task,
+ settings['fuzzy_flag'],
+ settings['fuzzy_weight'])
+ end
+ local act_flags = ''
+ if settings['learn_spam'] then
+ task:set_flag("learn_spam")
+ -- Allow processing as we still need to learn and do other stuff
+ act_flags = 'process_all'
+ end
+ task:insert_result(settings['symbol'], 1, rcpt)
+
+ if settings.action then
+ rspamd_logger.infox(task, 'spamtrap found: <%s>', rcpt)
+ local smtp_message
+ if settings.smtp_message then
+ smtp_message = lua_util.template(settings.smtp_message, { rcpt = rcpt })
+ else
+ smtp_message = 'unknown error'
+ if settings.action == 'no action' then
+ smtp_message = 'message accepted'
+ elseif settings.action == 'reject' then
+ smtp_message = 'message rejected'
+ end
+ end
+ task:set_pre_result { action = settings.action,
+ message = smtp_message,
+ module = 'spamtrap',
+ flags = act_flags }
+ end
+
+ return true
+ end
+
+ local function gen_redis_spamtrap_cb(target)
+ return function(err, data)
+ if err ~= nil then
+ rspamd_logger.errx(task, 'redis_spamtrap_cb received error: %1', err)
+ return
+ end
+
+ if data and type(data) ~= 'userdata' then
+ do_action(target)
+ else
+ if not called_for_domain then
+ -- Recurse for @catchall domain
+ target = rcpts[1]['domain']:lower()
+ local key = settings['key_prefix'] .. '@' .. target
+ local ret = rspamd_redis_make_request(task,
+ redis_params, -- connect params
+ key, -- hash key
+ false, -- is write
+ gen_redis_spamtrap_cb(target), -- callback
+ 'GET', -- command
+ { key } -- arguments
+ )
+ if not ret then
+ rspamd_logger.errx(task, "redis request wasn't scheduled")
+ end
+ called_for_domain = true
+ else
+ lua_util.debugm(M, task, 'skip spamtrap for %s', target)
+ end
+ end
+ end
+ end
+
+ -- Do not risk a FP by checking for more than one recipient
+ if rcpts and (#rcpts == 1 or (#rcpts > 0 and settings.allow_multiple_rcpts)) then
+ local targets = fun.map(function(r)
+ return r['addr']:lower()
+ end, rcpts)
+ if use_redis then
+ fun.each(function(target)
+ local key = settings['key_prefix'] .. target
+ local ret = rspamd_redis_make_request(task,
+ redis_params, -- connect params
+ key, -- hash key
+ false, -- is write
+ gen_redis_spamtrap_cb(target), -- callback
+ 'GET', -- command
+ { key } -- arguments
+ )
+ if not ret then
+ rspamd_logger.errx(task, "redis request wasn't scheduled")
+ end
+ end, targets)
+
+ elseif settings['map'] then
+ local function check_map_functor(target)
+ if settings['map']:get_key(target) then
+ return do_action(target)
+ end
+ end
+ if not fun.any(check_map_functor, targets) then
+ lua_util.debugm(M, task, 'skip spamtrap')
+ end
+ end
+ end
+end
+
+-- Module setup
+
+local opts = rspamd_config:get_all_opt('spamtrap')
+if not (opts and type(opts) == 'table') then
+ rspamd_logger.infox(rspamd_config, 'module is unconfigured')
+ return
+end
+
+local auth_and_local_conf = lua_util.config_check_local_or_authed(rspamd_config, 'spamtrap',
+ false, false)
+check_local = auth_and_local_conf[1]
+check_authed = auth_and_local_conf[2]
+
+if opts then
+ for k, v in pairs(opts) do
+ settings[k] = v
+ end
+ if settings['map'] then
+ settings['map'] = rspamd_config:add_map {
+ url = settings['map'],
+ description = string.format("Spamtrap map for %s", settings['symbol']),
+ type = "regexp"
+ }
+ else
+ redis_params = rspamd_parse_redis_server('spamtrap')
+ if not redis_params then
+ rspamd_logger.errx(
+ rspamd_config, 'no redis servers are specified, disabling module')
+ return
+ end
+ use_redis = true;
+ end
+
+ local id = rspamd_config:register_symbol({
+ name = "SPAMTRAP_CHECK",
+ type = "callback,postfilter",
+ callback = spamtrap_cb
+ })
+ rspamd_config:register_symbol({
+ name = settings['symbol'],
+ parent = id,
+ type = 'virtual',
+ score = settings.score
+ })
+end