with import <stockholm/lib>; { config, pkgs, lib, ... }: let cfg = config.krebs.exim-retiolum; # Due to improvements to the JSON notation, braces around top-level objects # are not necessary^Wsupported by rspamd's parser when including files: # https://github.com/rspamd/rspamd/issues/2674 toMostlyJSON = value: assert typeOf value == "set"; (s: substring 1 (stringLength s - 2) s) (toJSON value); to-lsearch = concatMapStrings ({ from, to, ... }: "${from}: ${to}\n"); lsearch = mapAttrs (name: set: toFile name (to-lsearch set)) ({ inherit (cfg) system-aliases; }); in { options.krebs.exim-retiolum = { enable = mkEnableOption "krebs.exim-retiolum"; local_domains = mkOption { type = with types; listOf hostname; default = ["localhost"] ++ config.krebs.build.host.nets.retiolum.aliases; }; primary_hostname = mkOption { type = types.str; default = let x = "${config.krebs.build.host.name}.r"; in assert elem x config.krebs.build.host.nets.retiolum.aliases; x; }; relay_to_domains = mkOption { # TODO hostname with wildcards type = with types; listOf str; default = [ "*.r" ]; }; rspamd = { enable = mkEnableOption "krebs.exim-retiolum.rspamd" // { default = false; }; locals = { logging = { level = mkOption { type = types.enum [ "error" "warning" "notice" "info" "debug" "silent" ]; default = "notice"; }; }; options = { local_networks = mkOption { type = types.listOf types.cidr; default = [ config.krebs.build.host.nets.retiolum.ip4.prefix config.krebs.build.host.nets.retiolum.ip6.prefix ]; }; }; }; }; system-aliases = mkOption { type = types.listOf (types.submodule ({ options = { from = mkOption { type = types.str; # TODO e-mail address }; to = mkOption { type = types.str; # TODO e-mail address / TODO listOf }; }; })); default = []; }; }; imports = [ { config = lib.mkIf cfg.rspamd.enable { services.rspamd.enable = true; services.rspamd.locals = mapAttrs' (name: value: nameValuePair "${name}.inc" { text = toMostlyJSON value; }) cfg.rspamd.locals; users.users.${config.krebs.exim.user.name}.extraGroups = [ config.services.rspamd.group ]; }; } ]; config = lib.mkIf cfg.enable { krebs.exim = { enable = true; config = # This configuration makes only sense for retiolum-enabled hosts. # TODO modular configuration assert config.krebs.tinc.retiolum.enable; /* exim */ '' keep_environment = primary_hostname = ${cfg.primary_hostname} domainlist local_domains = ${concatStringsSep ":" cfg.local_domains} domainlist relay_to_domains = ${concatStringsSep ":" cfg.relay_to_domains} ${optionalString cfg.rspamd.enable /* exim */ '' spamd_address = /run/rspamd/rspamd.sock variant=rspamd ''} acl_smtp_rcpt = acl_check_rcpt acl_smtp_data = acl_check_data host_lookup = * rfc1413_hosts = * rfc1413_query_timeout = 5s log_file_path = syslog syslog_timestamp = false syslog_duplication = false tls_advertise_hosts = begin acl acl_check_rcpt: deny local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ message = restricted characters in address accept domains = +local_domains : +relay_to_domains deny message = relay not permitted acl_check_data: ${optionalString cfg.rspamd.enable /* exim */ '' accept condition = ''${if eq{$interface_port}{587}} warn remove_header = ${concatStringsSep " : " [ "x-spam" "x-spam-report" "x-spam-score" ]} warn spam = nobody:true warn condition = ''${if !eq{$spam_action}{no action}} add_header = X-Spam: Yes add_header = X-Spam-Report: $spam_report add_header = X-Spam-Score: $spam_score ''} accept begin routers system_aliases: debug_print = "R: system_aliases for $local_part@$domain" driver = redirect data = ''${lookup{$local_part}lsearch{${lsearch.system-aliases}}} local: driver = accept domains = +local_domains check_local_user # local_part_suffix = +* # local_part_suffix_optional transport = home_maildir remote: driver = manualroute domains = +relay_to_domains transport = remote_smtp route_list = ^.* $0 byname begin transports remote_smtp: driver = smtp home_maildir: driver = appendfile maildir_format directory = $home/Maildir directory_mode = 0700 delivery_date_add envelope_to_add return_path_add # group = mail # mode = 0660 begin retry ${concatMapStringsSep "\n" (k: "${k} * F,42d,1m") cfg.relay_to_domains} * * F,2h,15m; G,16h,1h,1.5; F,4d,6h begin rewrite begin authenticators ''; }; }; }