-- KumoMTA configuration local kumo = require 'kumo' local utils = require 'policy-extras.policy_utils' -- Load authentication users directly in the code for simplicity local smtp_auth_users = { ['user1'] = 'password1', -- Add more users as needed } -- Load the policy helpers local shaping = require 'policy-extras.shaping' local queue_module = require 'policy-extras.queue' local sources = require 'policy-extras.sources' local dkim_sign = require 'policy-extras.dkim_sign' -- Configure sources and pools sources:setup { '/opt/kumomta/etc/policy/sources.toml' } -- Configure traffic shaping local shaper = shaping:setup { '/opt/kumomta/etc/policy/shaping.toml' } -- Configure queue management local queue_helper = queue_module:setup { '/opt/kumomta/etc/policy/queues.toml' } -- Configure DKIM signing local dkim_signer = dkim_sign:setup { '/opt/kumomta/etc/policy/dkim_data.toml' } -- SMTP Authentication handler with proper logging kumo.on('smtp_server_auth_plain', function(authz, authc, password, conn_meta) local password_database = { ['user1'] = 'password1', } kumo.log_debug("Auth attempt from:", conn_meta:get_meta('peer_address')) kumo.log_debug("Auth user:", authc or "nil") kumo.log_debug("Password length:", string.len(password or "")) if not authc or authc == "" then kumo.log_debug("Auth failed: empty username") return false end if not password or password == "" then kumo.log_debug("Auth failed: empty password") return false end local is_authorized = smtp_auth_users[authc] == password if is_authorized then kumo.log_debug("Auth successful for user:", authc) conn_meta:set_meta('authz_id', authc) conn_meta:set_meta('authenticated', true) else kumo.log_debug("Auth failed for user:", authc, "- invalid password") end return is_authorized end) -- HTTP Basic Auth validator kumo.on('http_server_validate_auth_basic', function(user, pass) return smtp_auth_users[user] == pass end) -- Called On Startup, handles initial configuration kumo.on('init', function() -- Set diagnostic log level to see our log messages kumo.set_diagnostic_log_filter 'kumod=debug' -- Define spools for message storage kumo.define_spool { name = 'data', path = '/var/spool/kumomta/data', kind = 'RocksDB', } kumo.define_spool { name = 'meta', path = '/var/spool/kumomta/meta', kind = 'RocksDB', } -- Configure logging kumo.configure_local_logs { log_dir = '/var/log/kumomta', max_segment_duration = '60 seconds', } -- Configure bounce classification kumo.configure_bounce_classifier { files = { '/opt/kumomta/share/bounce_classifier/iana.toml', }, } -- Configure HTTP listener for admin access kumo.start_http_listener { listen = '0.0.0.0:8000', trusted_hosts = { '127.0.0.1', '::1' }, } -- Configure SMTP listener for port 25 kumo.start_esmtp_listener { listen = '0.0.0.0:25', hostname = 'kumo.s-gii.com', relay_hosts = { '127.0.0.1'}, -- ONLY localhost can relay without auth -- tls_certificate = '/opt/kumomta/etc/certs/kumo.s-gii.com.crt', -- tls_private_key = '/opt/kumomta/etc/certs/kumo.s-gii.com.key', } -- Add submission port (587) for authenticated sending kumo.start_esmtp_listener { listen = '0.0.0.0:587', hostname = 'kumo.s-gii.com', relay_hosts = { '127.0.0.1' }, -- ONLY localhost can relay without auth -- tls_certificate = '/opt/kumomta/etc/certs/kumo.s-gii.com.crt', -- tls_private_key = '/opt/kumomta/etc/certs/kumo.s-gii.com.key', } end) -- Configure traffic shaping kumo.on('get_egress_path_config', shaper) -- Handle domain permissions for relay kumo.on('get_listener_domain', function(domain, listener, conn_meta) local authz_id = conn_meta:get_meta('authz_id') kumo.log_debug("Checking relay permissions for domain:", domain) kumo.log_debug("Connection authenticated as:", authz_id or "not authenticated") -- Allow authenticated users to relay to any domain if authz_id then kumo.log_debug("Allowing relay for authenticated user:", authz_id) return kumo.make_listener_domain { relay_to = true, } end kumo.log_debug("Denying relay permission for unauthenticated connection to:", domain) return nil end) -- Processing of incoming messages via SMTP kumo.on('smtp_server_message_received', function(msg, conn_meta) -- Protect against SMTP Smuggling local failed = msg:check_fix_conformance( 'NON_CANONICAL_LINE_ENDINGS', '' ) if failed then kumo.reject(552, string.format('5.6.0 %s', failed)) end -- If we're authenticated, set the tenant based on the authenticated user local authz_id = conn_meta:get_meta('authz_id') if authz_id then kumo.log_debug("Setting tenant to authenticated user:", authz_id) msg:set_meta('tenant', authz_id) end -- Call the queue helper to set up the queue for the message queue_helper:apply(msg) -- DKIM signing should come last dkim_signer(msg) end)