local settings = {
expire = 86400, -- 1 day by default
timeout = 300, -- 5 minutes by default
- key_prefix = 'grey.', -- default hash name
+ key_prefix = 'rg', -- default hash name
max_data_len = 10240, -- default data limit to hash
message = 'Try again later', -- default greylisted message
symbol = 'GREYLIST',
local h = hash.create()
h:update(body, len)
- local b32 = settings['key_prefix'] .. h:base32()
+ local b32 = settings['key_prefix'] .. 'b' .. h:base32():sub(1, 20)
task:get_mempool():set_variable("grey_bodyhash", b32)
return b32
end
end
h:update(addr)
-
local rcpt = task:get_recipients('smtp')
if rcpt then
table.sort(rcpt, function(r1, r2)
h:update(s)
end
- local b32 = settings['key_prefix'] .. h:base32()
+ local b32 = settings['key_prefix'] .. 'm' .. h:base32():sub(1, 20)
task:get_mempool():set_variable("grey_metahash", b32)
return b32
end
+-- Returns pair of booleans: found,greylisted
local function check_time(task, tm, type)
local t = tonumber(tm)
if not t then
rspamd_logger.infox(task, 'not a valid number: %s', tm)
- return false
+ return false,false
end
local now = rspamd_util.get_time()
if now - t < settings['timeout'] then
- local end_time = rspamd_util.time_to_string(t + settings['timeout'])
- rspamd_logger.infox(task, 'greylisted till "%s" using %s key',
- end_time, type)
- task:set_pre_result('soft reject', settings['message'])
- task:get_mempool():set_variable("grey_greylisted", end_time)
-
- return true
+ return true,true
else
-- We just set variable to pass when in post-filter stage
task:get_mempool():set_variable("grey_whitelisted", type)
- return true
+ return true,false
end
- return false
+ return false,false
end
local function greylist_check(task)
local addr = upstream:get_addr()
local function redis_get_cb(task, err, data)
- local ret = false
+ local ret_body = false
+ local greylisted_body = false
+ local ret_meta = false
+ local greylisted_meta = false
+ local time
+ local greylist_type
+
if data then
if data[1] and type(data[1]) ~= 'userdata' then
- ret = check_time(task, data[1], 'body')
+ ret_body,greylisted_body = check_time(task, data[1], 'body')
+ if greylisted_body then
+ local end_time = rspamd_util.time_to_string(rspamd_util.get_time()
+ + settings['timeout'])
+ task:get_mempool():set_variable("grey_greylisted_body", end_time)
+ end
end
- if not ret and type(data[2]) ~= 'userdata' then
- ret = check_time(task, data[2], 'meta')
+ if data[2] and type(data[2]) ~= 'userdata' then
+ if not ret_body or greylisted_body then
+ ret_meta,greylisted_meta = check_time(task, data[2], 'meta')
+
+ if greylisted_meta then
+ local end_time = rspamd_util.time_to_string(rspamd_util.get_time()
+ + settings['timeout'])
+ task:get_mempool():set_variable("grey_greylisted_meta", end_time)
+ end
+ end
end
upstream:ok()
- if not ret then
- rspamd_logger.infox(task, 'greylisted till "%s", new record',
- rspamd_util.time_to_string(rspamd_util.get_time() + settings['timeout']),
- type)
+ if not ret_body and not ret_meta then
+ local t = tostring(math.floor(rspamd_util.get_time()))
+ local end_time = rspamd_util.time_to_string(t + settings['timeout'])
+ rspamd_logger.infox(task, 'greylisted till "%s", new record', end_time)
+ task:insert_result(settings['symbol'], 0.0, 'greylisted', end_time,
+ 'new record')
task:set_pre_result('soft reject', settings['message'])
-- Create new record
if addr then
host = addr
})
- local t = tostring(math.floor(rspamd_util.get_time()))
if conn then
conn:add_cmd('SETEX', {
body_key, tostring(settings['expire']), t
conn:add_cmd('SETEX', {
meta_key, tostring(settings['expire']), t
})
+ local end_time = rspamd_util.time_to_string(rspamd_util.get_time()
+ + settings['timeout'])
+ task:get_mempool():set_variable("grey_greylisted", end_time)
else
rspamd_logger.infox(task, 'got error while connecting to redis: %1', addr)
upstream:fail()
end
+ elseif greylisted_body and greylisted_meta then
+ local end_time = rspamd_util.time_to_string(time + settings['timeout'])
+ rspamd_logger.infox(task, 'greylisted till "%s" using %s key',
+ end_time, type)
+ task:insert_result(settings['symbol'], 0.0, 'greylisted', end_time,
+ greylist_type)
+ task:set_pre_result('soft reject', settings['message'])
+ task:get_mempool():set_variable("grey_greylisted", end_time)
end
end
elseif err then
end
if addr then
- rspamd_redis.make_request(task, addr, redis_get_cb, 'MGET',
- {body_key, meta_key})
+ if not rspamd_redis.make_request(task, addr, redis_get_cb, 'MGET',
+ {body_key, meta_key}) then
+ rspamd_logger.errx(task, 'cannot make redis request to check results')
+ end
end
end
local function greylist_set(task)
local is_whitelisted = task:get_mempool():get_variable("grey_whitelisted")
- local is_greylisted = task:get_mempool():get_variable("grey_greylisted")
+
local action = task:get_metric_action('default')
local body_key = data_key(task)
local meta_key = envelope_key(task)
local upstream = upstreams:get_upstream_by_hash(body_key .. meta_key)
local addr = upstream:get_addr()
- if is_greylisted then
- task:insert_result(settings['symbol'], 0.0, 'delayed', is_greylisted)
- rspamd_logger.infox(task, 'greylisting delayed till %s',
- is_greylisted)
-
- return
- end
if is_whitelisted then
if action == 'greylist' then
-- We are going to accept message
end
else
if action ~= 'no action' then
- -- We need to delay message, hence set a temporary result
- task:insert_result(settings['symbol'], 0.0, 'greylisted', 'delayed')
+ local grey_res = task:get_mempool():get_variable("grey_greylisted_body")
+
+ if grey_res then
+ -- We need to delay message, hence set a temporary result
+ task:insert_result(settings['symbol'], 0.0, grey_res, 'body')
+ rspamd_logger.infox(task, 'greylisting delayed till "%s": body', grey_res)
+ else
+ grey_res = task:get_mempool():get_variable("grey_greylisted_meta")
+
+ if grey_res then
+ task:insert_result(settings['symbol'], 0.0, grey_res, 'meta')
+ rspamd_logger.infox(task, 'greylisting delayed till "%s": meta', grey_res)
+ else
+ task:insert_result(settings['symbol'], 0.0, 'unknown')
+ rspamd_logger.infox(task, 'greylisting delayed: unknown, internal error')
+ end
+ end
task:set_metric_action('default', 'soft reject')
task:set_pre_result('soft reject', settings['message'])
else