mirror of
https://github.com/mailscope/kumomta.git
synced 2026-09-04 01:48:18 +00:00
113 lines
3.5 KiB
Lua
113 lines
3.5 KiB
Lua
-- This config acts as a sink that will discard all received mail
|
|
local kumo = require 'kumo'
|
|
package.path = 'assets/?.lua;' .. package.path
|
|
local utils = require 'policy-extras.policy_utils'
|
|
|
|
local SINK_DATA_FILE = os.getenv 'SINK_DATA'
|
|
or '/opt/kumomta/etc/policy/responses.toml'
|
|
|
|
-- Resolve our hostname, then derive the docker network from that.
|
|
-- This assumes that the network is a /24 and that HOSTNAME is
|
|
-- injected by docker and resolves to the container IP on that network
|
|
local function resolve_docker_network()
|
|
local MY_IPS = kumo.dns.lookup_addr(os.getenv 'HOSTNAME' or 'localhost')
|
|
local DOCKER_NETWORK = string.match(MY_IPS[1], '^(.*)%.%d+$') .. '.0/24'
|
|
return DOCKER_NETWORK
|
|
end
|
|
|
|
kumo.on('init', function()
|
|
kumo.configure_accounting_db_path(os.tmpname())
|
|
kumo.set_config_monitor_globs { SINK_DATA_FILE }
|
|
local DOCKER_NETWORK = resolve_docker_network()
|
|
local SINK_PORT = os.getenv 'SINK_PORT' or '25'
|
|
kumo.start_esmtp_listener {
|
|
listen = '0:' .. SINK_PORT,
|
|
-- Explicitly an open relay, because we want to sink everything
|
|
relay_hosts = { '0.0.0.0/0' },
|
|
banner = 'This system will sink and discard all mail',
|
|
}
|
|
|
|
local SINK_HTTP = os.getenv 'SINK_HTTP' or '8000'
|
|
kumo.start_http_listener {
|
|
listen = '0.0.0.0:' .. SINK_HTTP,
|
|
trusted_hosts = { '127.0.0.1', '::1', DOCKER_NETWORK },
|
|
}
|
|
|
|
-- Define spool locations
|
|
-- This is unused by this config, but we are required to
|
|
-- define a default spool location.
|
|
|
|
local spool_dir = os.getenv 'SINK_SPOOL' or '/var/spool/kumomta'
|
|
|
|
for _, name in ipairs { 'data', 'meta' } do
|
|
kumo.define_spool {
|
|
name = name,
|
|
path = spool_dir .. '/' .. name,
|
|
}
|
|
end
|
|
|
|
-- No logs are configured: we don't need them
|
|
end)
|
|
|
|
-- Load and parse the responses.toml data and resolve the configuration
|
|
-- for a given domain
|
|
local function load_data_for_domain(domain)
|
|
local data = kumo.toml_load(SINK_DATA_FILE)
|
|
local config = data.domain[domain] or data.default
|
|
config.bounces = data.bounce[domain] or { { code = 550, msg = 'boing!' } }
|
|
config.defers = data.defer[domain] or { { code = 451, msg = 'later!' } }
|
|
return config
|
|
end
|
|
|
|
-- Cache the result of a load_data_for_domain call
|
|
local resolve_domain = kumo.memoize(load_data_for_domain, {
|
|
name = 'response-data-cache',
|
|
ttl = '1 hour',
|
|
capacity = 100,
|
|
})
|
|
|
|
kumo.on('smtp_server_message_received', function(msg)
|
|
local recipient = msg:recipient()
|
|
|
|
-- Do any special responses requested by the client
|
|
if string.find(recipient.user, 'tempfail') then
|
|
kumo.reject(400, 'tempfail requested')
|
|
end
|
|
if string.find(recipient.user, 'permfail') then
|
|
kumo.reject(500, 'permfail requested')
|
|
end
|
|
if utils.starts_with(recipient.user, '450-') then
|
|
kumo.reject(450, 'you said ' .. recipient.user)
|
|
end
|
|
if utils.starts_with(recipient.user, '250-') then
|
|
msg:set_meta('queue', 'null')
|
|
return
|
|
end
|
|
|
|
-- Now any general bounce responses based on the toml file
|
|
local domain = recipient.domain
|
|
local config = resolve_domain(domain)
|
|
|
|
local d100 = math.random(100)
|
|
local selection = nil
|
|
if d100 < config.bounce then
|
|
selection = config.bounces
|
|
elseif d100 < config.bounce + config.defer then
|
|
selection = config.defers
|
|
end
|
|
|
|
if selection then
|
|
local choice = selection[math.random(#selection)]
|
|
kumo.reject(choice.code, choice.msg)
|
|
end
|
|
|
|
-- Finally, accept and discard any messages that haven't
|
|
-- been rejected already
|
|
msg:set_meta('queue', 'null')
|
|
end)
|
|
|
|
kumo.on('http_message_generated', function(msg)
|
|
-- Accept and discard all messages
|
|
msg:set_meta('queue', 'null')
|
|
end)
|