cat init.lua -- This require statement is needed in any script passed to KumoMTA. -- Includes from this policy script will not need this declared again. local kumo = require 'kumo' local utils = require 'policy-extras.policy_utils' -- Load the policy helpers to simplify common configuration use cases local shaping = require 'policy-extras.shaping' local queue_module = require 'policy-extras.queue' local listener_domains = require 'policy-extras.listener_domains' local sources = require 'policy-extras.sources' local dkim_sign = require 'policy-extras.dkim_sign' local log_hooks = require 'policy-extras.log_hooks' sources:setup { '/opt/kumomta/etc/policy/sources.toml' } local dkim_signer = dkim_sign:setup { '/opt/kumomta/etc/policy/dkim_data.toml' } -- Load Traffic Shaping Automation Helper local shaper = shaping:setup_with_automation { publish = { 'http://127.0.0.1:8008' }, subscribe = { 'http://127.0.0.1:8008' }, extra_files = { '/opt/kumomta/etc/policy/shaping.toml' }, } local queue_helper = queue_module:setup { '/opt/kumomta/etc/policy/queues.toml' } -- END SETUP -- NDR (bounce-back email) generator kumo.on('should_enqueue_log_record', function(msg) local bounce_class = msg:get_meta 'bounce_classification' -- Only generate NDR for hard bounces if bounce_class and bounce_class ~= 'Uncategorized' then local sender = msg:get_meta 'sender' -- Don't generate NDR for empty sender (already a bounce) if sender and sender ~= '' then local params = { include_original_message = 'HeadersOnly', enable_bounce = true, enable_expiration = true, reporting_mta = { mta_type = 'dns', name = 'my.domain.com', }, } local bounce_msg = kumo.generate_rfc3464_message(params, msg) if bounce_msg then local ok, err = pcall(kumo.inject_message, bounce_msg) if not ok then kumo.log_error('failed to inject NDR: ' .. tostring(err)) end end end end return true end) --START EVENT HANDLERS --------------------------------------------------------------------- -- ALLOWED IPs (MailWizz + Localhost) --------------------------------------------------------------------- --local allowed = { -- ["127.0.0.1"] = true, -- ["3.80.56.201"] = true --} --------------------------------------------------------------------- -- INIT PHASE --------------------------------------------------------------------- kumo.on('init', function() -- SMTP Port 25 kumo.start_esmtp_listener { listen = "0.0.0.0:25", -- override the default set of relay hosts -- relay_hosts = { '127.0.0.1', '192.168.1.0/24', '3.80.56.201', '34.229.87.103', '12.0.4.214' }, } -- Submission Port 587 kumo.start_esmtp_listener { listen = "0.0.0.0:587", } -- HTTP Admin Port 8080 kumo.start_http_listener { listen = "0.0.0.0:8080", } -- Spool storage kumo.define_spool { name = "data", path = "/var/spool/kumomta/data", } kumo.define_spool { name = "meta", path = "/var/spool/kumomta/meta", } -- Configure publishing of TSA logs to automation daemon shaper.setup_publish() -- Logging kumo.configure_local_logs { log_dir = "/var/log/kumomta", max_segment_duration = "10s", } kumo.configure_bounce_classifier { files = { '/opt/kumomta/share/bounce_classifier/iana.toml', }, } end) kumo.on('get_listener_domain', function(domain, listener, conn_meta) if conn_meta:get_meta 'authz_id' then -- We're authenticated as someone. -- Allow relaying return kumo.make_listener_domain { relay_to = true, } end end) local signer = kumo.dkim.rsa_sha256_signer { domain = 'domain.com', selector = 'k1', headers = { 'From', 'To', 'Subject' }, key = '/opt/kumomta/etc/dkim/domain.com/k1.key' } -- Use this to lookup and confirm a user/password credential kumo.on('smtp_server_auth_plain', function(authz, authc, password, conn_meta) local password_database = { ['pass'] = 'pass', } if password == '' then return false end return password_database[authc] == password end) kumo.on('smtp_server_message_received', function(msg) -- Protect against SMTP Smuggling (https://sec-consult.com/blog/detail/smtp-smuggling-spoofing-e-mails-worldwide/) local failed = msg:check_fix_conformance( -- check for and reject messages with these issues: 'NON_CANONICAL_LINE_ENDINGS', -- fix messages with these issues: '' ) if failed then kumo.reject(552, string.format('5.6.0 %s', failed)) end -- Call the queue helper to set up the queue for the message. queue_helper:apply(msg) -- SIGNING MUST COME LAST OR YOU COULD BREAK YOUR DKIM SIGNATURES msg:dkim_sign(signer) end) -- Processing of incoming messages via HTTP kumo.on('http_message_generated', function(msg) -- Call the queue helper to set up the queue for the message. queue_helper:apply(msg) -- SIGNING MUST COME LAST OR YOU COULD BREAK YOUR DKIM SIGNATURES dkim_signer(msg) end) --------------------------------------------------------------------- -- ROUTING --------------------------------------------------------------------- --------------------------------------------------------------------- -- ROUTING RULE (LeadXpression + others) --------------------------------------------------------------------- --[[ kumo.on('routing', function(msg) local from = msg:get_header("From") or "" local env_from = msg:get_envelope_from() or "" -- LeadXpression routing (CORE REQUIREMENT) if string.find(from, "@leadxpression.com") or string.find(env_from, "@leadxpression.com") then msg:set_meta("smtp_source", "34.229.87.103") return "default" end -- logtrks routing if string.find(from, "@logtrks.net") then msg:set_meta("smtp_source", "3.224.180.156") return "default" end -- listtrk routing if string.find(from, "@listtrk.net") then msg:set_meta("smtp_source", "3.232.172.184") return "default" end return "default" end) ]]