| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| README.md | 2026-04-08 | 4.8 kB | |
| v1.4.0 source code.tar.gz | 2026-04-08 | 677.0 kB | |
| v1.4.0 source code.zip | 2026-04-08 | 1.0 MB | |
| Totals: 3 Items | 1.7 MB | 0 | |
- Added new blocklist feature that allows you to block senders by their email address or entire domain
- Added List-Unsubscribe behaviour setting
- Added quick option to add sender to blocklist from failed deliveries page
Breaking Changes
- The new blocklist feature requires an update to Rspamd config in order to work.
You must create a new file named addy_blocklist.lua at /etc/rspamd/lua.local.d/addy_blocklist.lua, in this file enter the following contents (making sure to change blocklist_api_url and blocklist_secret to your own values):
:::lua
--[[
Rspamd Lua script: user blocklist check via Laravel HTTP API.
Deploy this on each mail server that runs Rspamd. Point blocklist_api_url
at your Laravel app.
Required: rspamd_http (built-in). Symbol BLOCKLIST_USER is set when the
API returns block=true; map this symbol to an action (reject/discard) in
your Rspamd actions config.
--]]
local blocklist_api_url = 'https://your-addy-instance.com/api/blocklist-check'
local blocklist_secret = '' -- same as BLOCKLIST_API_SECRET in .env, or leave '' if unset
-- Simple percent-encode for query parameter values (rspamd_http has no escape)
local function url_encode(s)
if s == nil or s == '' then return '' end
s = tostring(s)
return (s:gsub('[^%w%-_.~ ]', function(c)
return string.format('%%%02X', string.byte(c))
end):gsub(' ', '%%20'))
end
local logger = require "rspamd_logger"
local rspamd_http = require 'rspamd_http'
rspamd_config:register_symbol({
name = 'BLOCKLIST_USER',
callback = function(task)
local rcpts = task:get_recipients('smtp')
local from_env = task:get_from('smtp')
if not rcpts or #rcpts == 0 then
logger.infox('blocklist: skip - missing recipient')
return false
end
local recipient = (rcpts[1].addr and rcpts[1].addr:lower()) or ''
local sender = ''
if from_env and from_env.addr then
sender = from_env.addr:lower()
end
local from_email = ''
local from_hdr = task:get_header('From')
if from_hdr then
local raw = (type(from_hdr) == 'table') and (from_hdr[1] or from_hdr) or from_hdr
raw = tostring(raw)
from_email = raw:match('<([^>]+)>') or raw:match('%S+@%S+') or ''
from_email = from_email:lower()
end
if from_email == '' then
from_email = sender
end
if recipient == '' or (sender == '' and from_email == '') then
logger.infox('blocklist: skip - missing recipient or from (recipient=%1, sender=%2, from_email=%3)', recipient, sender, from_email)
return false
end
local url = blocklist_api_url
.. '?recipient=' .. url_encode(recipient)
.. '&from_email=' .. url_encode(from_email)
local req_headers = {}
if blocklist_secret ~= '' then
req_headers['X-Blocklist-Secret'] = blocklist_secret
end
rspamd_http.request({
url = url,
headers = req_headers,
timeout = 2.0,
task = task,
callback = function(err_message, code, body, _headers)
if err_message then
logger.warnx('blocklist: HTTP error - %1', err_message)
return
end
if code == 200 and body and body:match('"block"%s*:%s*true') then
task:set_pre_result('reject', '550 5.1.1 Address not found')
task:insert_result(true, 'BLOCKLIST_USER', 1000.0, '550 5.1.1 Address not found')
logger.infox('blocklist: BLOCKLIST_USER set for recipient=%1 from_email=%2', recipient, from_email)
end
end,
})
return false -- do not match symbol here; only HTTP callback may add it via insert_result
end,
score = 1000.0,
})
You also need to update your .env file with the following new values:
# Blocklist API (Rspamd): comma-separated IPs allowed to call /api/blocklist-check; optional shared secret
BLOCKLIST_API_ALLOWED_IPS=127.0.0.1
BLOCKLIST_API_SECRET=
Make sure to add your own server's IP to the list above. If you have chosen to set a shared secret then make sure BLOCKLIST_API_SECRET is the same value as whatever you've chosen above in addy_blocklist.lua.
- Upgrade to Vite [8](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#800 may require you to update your node version to
20.19+.