From 1a64deeb894dc95e2645a75771732c6cc53a79ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isma=C3=ABl=20Bouya?= Date: Wed, 4 Oct 2023 01:35:06 +0200 Subject: Squash changes containing private information There were a lot of changes since the previous commit, but a lot of them contained personnal information about users. All thos changes got stashed into a single commit (history is kept in a different place) and private information was moved in a separate private repository --- modules/private/mail/default.nix | 42 -- modules/private/mail/dovecot.nix | 292 ------------- modules/private/mail/filter-rewrite-from.py | 68 --- modules/private/mail/milters.nix | 88 ---- modules/private/mail/opensmtpd.nix | 57 --- modules/private/mail/postfix.nix | 471 --------------------- modules/private/mail/relay.nix | 235 ---------- modules/private/mail/rspamd.nix | 87 ---- modules/private/mail/scan_reported_mails | 21 - modules/private/mail/sieve_bin/imapsieve_copy | 8 - modules/private/mail/sieve_scripts/backup.sieve | 7 - .../private/mail/sieve_scripts/report_ham.sieve | 11 - .../private/mail/sieve_scripts/report_spam.sieve | 3 - modules/private/mail/sympa.nix | 213 ---------- modules/private/mail/verify_from.py | 60 --- 15 files changed, 1663 deletions(-) delete mode 100644 modules/private/mail/default.nix delete mode 100644 modules/private/mail/dovecot.nix delete mode 100755 modules/private/mail/filter-rewrite-from.py delete mode 100644 modules/private/mail/milters.nix delete mode 100644 modules/private/mail/opensmtpd.nix delete mode 100644 modules/private/mail/postfix.nix delete mode 100644 modules/private/mail/relay.nix delete mode 100644 modules/private/mail/rspamd.nix delete mode 100755 modules/private/mail/scan_reported_mails delete mode 100755 modules/private/mail/sieve_bin/imapsieve_copy delete mode 100644 modules/private/mail/sieve_scripts/backup.sieve delete mode 100644 modules/private/mail/sieve_scripts/report_ham.sieve delete mode 100644 modules/private/mail/sieve_scripts/report_spam.sieve delete mode 100644 modules/private/mail/sympa.nix delete mode 100755 modules/private/mail/verify_from.py (limited to 'modules/private/mail') diff --git a/modules/private/mail/default.nix b/modules/private/mail/default.nix deleted file mode 100644 index 2d405c6..0000000 --- a/modules/private/mail/default.nix +++ /dev/null @@ -1,42 +0,0 @@ -{ lib, pkgs, config, ... }: -{ - imports = [ - ./milters.nix - ./postfix.nix - ./dovecot.nix - ./relay.nix - ./rspamd.nix - ./opensmtpd.nix - ./sympa.nix - ]; - options.myServices.mail.enable = lib.mkEnableOption "enable Mail services"; - options.myServices.mailRelay.enable = lib.mkEnableOption "enable Mail relay services"; - options.myServices.mailBackup.enable = lib.mkEnableOption "enable MX backup services"; - - config = lib.mkIf config.myServices.mail.enable { - security.acme.certs."mail" = config.myServices.certificates.certConfig // { - domain = config.hostEnv.fqdn; - extraDomains = let - zonesWithMx = builtins.filter (zone: - lib.attrsets.hasAttr "withEmail" zone && lib.lists.length zone.withEmail > 0 - ) config.myEnv.dns.masterZones; - mxs = map (zone: "${config.hostEnv.mx.subdomain}.${zone.name}") zonesWithMx; - in builtins.listToAttrs (map (mx: lib.attrsets.nameValuePair mx null) mxs); - }; - # This is for clients that don’t support elliptic curves (e.g. - # printer) - security.acme.certs."mail-rsa" = config.myServices.certificates.certConfig // { - domain = config.hostEnv.fqdn; - keyType = "rsa4096"; - extraDomains = let - zonesWithMx = builtins.filter (zone: - lib.attrsets.hasAttr "withEmail" zone && lib.lists.length zone.withEmail > 0 - ) config.myEnv.dns.masterZones; - mxs = map (zone: "${config.hostEnv.mx.subdomain}.${zone.name}") zonesWithMx; - in builtins.listToAttrs (map (mx: lib.attrsets.nameValuePair mx null) mxs); - }; - systemd.slices.mail = { - description = "Mail slice"; - }; - }; -} diff --git a/modules/private/mail/dovecot.nix b/modules/private/mail/dovecot.nix deleted file mode 100644 index b6fdc02..0000000 --- a/modules/private/mail/dovecot.nix +++ /dev/null @@ -1,292 +0,0 @@ -{ lib, pkgs, config, ... }: -let - sieve_bin = pkgs.runCommand "sieve_bin" { - buildInputs = [ pkgs.makeWrapper ]; - } '' - cp -a ${./sieve_bin} $out - chmod -R u+w $out - patchShebangs $out - for i in $out/*; do - wrapProgram "$i" --prefix PATH : ${lib.makeBinPath [ pkgs.coreutils ]} - done - ''; -in -{ - config = lib.mkIf config.myServices.mail.enable { - systemd.services.dovecot2.serviceConfig.Slice = "mail.slice"; - secrets.keys."dovecot/ldap" = { - user = config.services.dovecot2.user; - group = config.services.dovecot2.group; - permissions = "0400"; - text = '' - hosts = ${config.myEnv.mail.dovecot.ldap.host} - tls = yes - - dn = ${config.myEnv.mail.dovecot.ldap.dn} - dnpass = ${config.myEnv.mail.dovecot.ldap.password} - - auth_bind = yes - - ldap_version = 3 - - base = ${config.myEnv.mail.dovecot.ldap.base} - scope = subtree - - pass_filter = ${config.myEnv.mail.dovecot.ldap.filter} - pass_attrs = ${config.myEnv.mail.dovecot.ldap.pass_attrs} - - user_attrs = ${config.myEnv.mail.dovecot.ldap.user_attrs} - user_filter = ${config.myEnv.mail.dovecot.ldap.filter} - iterate_attrs = ${config.myEnv.mail.dovecot.ldap.iterate_attrs} - iterate_filter = ${config.myEnv.mail.dovecot.ldap.iterate_filter} - ''; - }; - - users.users.vhost = { - group = "vhost"; - uid = config.ids.uids.vhost; - }; - users.groups.vhost.gid = config.ids.gids.vhost; - - # https://blog.zeninc.net/index.php?post/2018/04/01/Un-annuaire-pour-les-gouverner-tous....... - services.dovecot2 = { - enable = true; - enablePAM = false; - enablePop3 = true; - enableImap = true; - enableLmtp = true; - protocols = [ "sieve" ]; - modules = [ - pkgs.dovecot_pigeonhole - pkgs.dovecot_fts-xapian - ]; - mailUser = "vhost"; - mailGroup = "vhost"; - createMailUser = false; - mailboxes = { - Trash = { auto = "subscribe"; specialUse = "Trash"; }; - Junk = { auto = "subscribe"; specialUse = "Junk"; }; - Sent = { auto = "subscribe"; specialUse = "Sent"; }; - Drafts = { auto = "subscribe"; specialUse = "Drafts"; }; - }; - mailLocation = "mbox:~/Mail:INBOX=~/Mail/Inbox:INDEX=~/.imap"; - sslServerCert = "/var/lib/acme/mail/fullchain.pem"; - sslServerKey = "/var/lib/acme/mail/key.pem"; - sslCACert = "/var/lib/acme/mail/fullchain.pem"; - extraConfig = builtins.concatStringsSep "\n" [ - # For printer which doesn’t support elliptic curve - '' - ssl_alt_cert = &1 > /dev/null | grep -v "Mailbox doesn't exist:" | grep -v "Info: Opening DB" - ${pkgs.dovecot}/bin/doveadm expunge -A MAILBOX Junk SEEN NOT FLAGGED BEFORE 4w 2>&1 > /dev/null | grep -v "Mailbox doesn't exist:" | grep -v "Info: Opening DB" - ${pkgs.dovecot}/bin/doveadm expunge -A MAILBOX Trash NOT FLAGGED BEFORE 4w 2>&1 > /dev/null | grep -v "Mailbox doesn't exist:" | grep -v "Info: Opening DB" - ''; - in - [ - "0 2 * * * root ${cron_script}/bin/cleanup-imap-folders" - ]; - security.acme.certs."mail-rsa" = { - postRun = '' - systemctl restart dovecot2.service - ''; - extraDomains = { - "imap.immae.eu" = null; - "pop3.immae.eu" = null; - }; - }; - security.acme.certs."mail" = { - postRun = '' - systemctl restart dovecot2.service - ''; - extraDomains = { - "imap.immae.eu" = null; - "pop3.immae.eu" = null; - }; - }; - }; -} - diff --git a/modules/private/mail/filter-rewrite-from.py b/modules/private/mail/filter-rewrite-from.py deleted file mode 100755 index aad9c69..0000000 --- a/modules/private/mail/filter-rewrite-from.py +++ /dev/null @@ -1,68 +0,0 @@ -#! /usr/bin/env python3 -import sys - -sys.stdin.reconfigure(encoding='utf-8') -sys.stdout.reconfigure(encoding='utf-8') -stdin = sys.stdin -stdout = sys.stdout - -mailaddr = sys.argv[1] -inheader = {} - -# Change to actual file for logging -logfile = open("/dev/null", "a") - -def log(l, i): - logfile.write("{} {}\n".format(i, l)) - logfile.flush() - -def send(l): - log(l, ">") - stdout.write("{}\n".format(l)) - stdout.flush() - -def token_and_sid(version, sid, token): - if version < "0.5": - return "{}|{}".format(token, sid) - else: - return "{}|{}".format(sid, token) - -log("started", "l") -while True: - line = stdin.readline().strip() - log(line, "<") - if not line: - log("finished", "l") - break - splitted = line.split("|") - if line == "config|ready": - log("in config ready", "l") - send("register|filter|smtp-in|mail-from") - send("register|filter|smtp-in|data-line") - send("register|ready") - if splitted[0] != "filter": - continue - if len(splitted) < 7: - send("invalid filter command: expected >6 fields!") - sys.exit(1) - version = splitted[1] - action = splitted[4] - sid = splitted[5] - token = splitted[6] - token_sid = token_and_sid(version, sid, token) - rest = "|".join(splitted[7:]) - if action == "mail-from": - inheader[sid] = True - send("filter-result|{}|rewrite|<{}>".format(token_sid, mailaddr)) - continue - if action == "data-line": - if rest == "" and inheader.get(sid, False): - inheader[sid] = False - if rest == "." and not inheader.get(sid): - del(inheader[sid]) - if inheader.get(sid, False) and rest.upper().startswith("FROM:"): - send("filter-dataline|{}|From: {}".format(token_sid, mailaddr)) - else: - send("filter-dataline|{}|{}".format(token_sid, rest)) - continue - send("filter-result|{}|proceed".format(token_sid)) diff --git a/modules/private/mail/milters.nix b/modules/private/mail/milters.nix deleted file mode 100644 index 4b93a7a..0000000 --- a/modules/private/mail/milters.nix +++ /dev/null @@ -1,88 +0,0 @@ -{ lib, pkgs, config, name, ... }: -{ - imports = - builtins.attrValues (import ../../../lib/flake-compat.nix ../../../flakes/private/openarc).nixosModules - ++ builtins.attrValues (import ../../../lib/flake-compat.nix ../../../flakes/private/opendmarc).nixosModules; - - options.myServices.mail.milters.sockets = lib.mkOption { - type = lib.types.attrsOf lib.types.path; - default = { - opendkim = "/run/opendkim/opendkim.sock"; - opendmarc = config.services.opendmarc.socket; - openarc = config.services.openarc.socket; - }; - readOnly = true; - description = '' - milters sockets - ''; - }; - config = lib.mkIf (config.myServices.mail.enable || config.myServices.mailBackup.enable) { - secrets.keys = { - "opendkim" = { - isDir = true; - user = config.services.opendkim.user; - group = config.services.opendkim.group; - permissions = "0550"; - }; - "opendkim/eldiron.private" = { - user = config.services.opendkim.user; - group = config.services.opendkim.group; - permissions = "0400"; - text = config.myEnv.mail.dkim.eldiron.private; - }; - "opendkim/eldiron.txt" = { - user = config.services.opendkim.user; - group = config.services.opendkim.group; - permissions = "0444"; - text = '' - eldiron._domainkey IN TXT ${config.myEnv.mail.dkim.eldiron.public}''; - }; - }; - users.users."${config.services.opendkim.user}".extraGroups = [ "keys" ]; - services.opendkim = { - enable = true; - socket = "local:${config.myServices.mail.milters.sockets.opendkim}"; - domains = builtins.concatStringsSep "," (lib.flatten (map - (zone: map - (e: "${e.domain}${lib.optionalString (e.domain != "") "."}${zone.name}") - (zone.withEmail or []) - ) - config.myEnv.dns.masterZones - )); - keyPath = config.secrets.fullPaths."opendkim"; - selector = "eldiron"; - configFile = pkgs.writeText "opendkim.conf" '' - SubDomains yes - UMask 002 - AlwaysAddARHeader yes - ''; - group = config.services.postfix.group; - }; - systemd.services.opendkim.serviceConfig.Slice = "mail.slice"; - systemd.services.opendkim.preStart = lib.mkBefore '' - # Skip the prestart script as keys are handled in secrets - exit 0 - ''; - services.filesWatcher.opendkim = { - restart = true; - paths = [ - config.secrets.fullPaths."opendkim/eldiron.private" - ]; - }; - - systemd.services.milter_verify_from = { - description = "Verify from milter"; - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - Slice = "mail.slice"; - User = "postfix"; - Group = "postfix"; - ExecStart = let python = pkgs.python3.withPackages (p: [ p.pymilter ]); - in "${python}/bin/python ${./verify_from.py} -s /run/milter_verify_from/verify_from.sock"; - RuntimeDirectory = "milter_verify_from"; - }; - }; - }; -} diff --git a/modules/private/mail/opensmtpd.nix b/modules/private/mail/opensmtpd.nix deleted file mode 100644 index e05bba9..0000000 --- a/modules/private/mail/opensmtpd.nix +++ /dev/null @@ -1,57 +0,0 @@ -{ lib, pkgs, config, name, ... }: -{ - config = lib.mkIf config.myServices.mailRelay.enable { - secrets.keys."opensmtpd/creds" = { - user = "smtpd"; - group = "smtpd"; - permissions = "0400"; - text = '' - eldiron ${name}:${config.hostEnv.ldap.password} - ''; - }; - users.users.smtpd.extraGroups = [ "keys" ]; - services.opensmtpd = { - enable = true; - serverConfiguration = let - filter-rewrite-from = pkgs.runCommand "filter-rewrite-from.py" { - buildInputs = [ pkgs.python3 ]; - } '' - cp ${./filter-rewrite-from.py} $out - patchShebangs $out - ''; - in '' - table creds \ - "${config.secrets.fullPaths."opensmtpd/creds"}" - # FIXME: filtering requires 6.6, uncomment following lines when - # upgrading - # filter "fixfrom" \ - # proc-exec "${filter-rewrite-from} ${name}@immae.eu" - # listen on socket filter "fixfrom" - action "relay-rewrite-from" relay \ - helo ${config.hostEnv.fqdn} \ - host smtp+tls://eldiron@eldiron.immae.eu:587 \ - auth \ - mail-from ${name}@immae.eu - action "relay" relay \ - helo ${config.hostEnv.fqdn} \ - host smtp+tls://eldiron@eldiron.immae.eu:587 \ - auth - match for any !mail-from "@immae.eu" action "relay-rewrite-from" - match for any mail-from "@immae.eu" action "relay" - ''; - }; - environment.systemPackages = [ config.services.opensmtpd.package ]; - services.mail.sendmailSetuidWrapper = { - program = "sendmail"; - source = "${config.services.opensmtpd.package}/bin/smtpctl"; - setuid = false; - setgid = false; - }; - security.wrappers.mailq = { - program = "mailq"; - source = "${config.services.opensmtpd.package}/bin/smtpctl"; - setuid = false; - setgid = false; - }; - }; -} diff --git a/modules/private/mail/postfix.nix b/modules/private/mail/postfix.nix deleted file mode 100644 index ae98a8a..0000000 --- a/modules/private/mail/postfix.nix +++ /dev/null @@ -1,471 +0,0 @@ -{ lib, pkgs, config, nodes, ... }: -{ - config = lib.mkIf config.myServices.mail.enable { - secrets.keys = { - "postfix/mysql_alias_maps" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - # We need to specify that option to trigger ssl connection - tls_ciphers = TLSv1.2 - user = ${config.myEnv.mail.postfix.mysql.user} - password = ${config.myEnv.mail.postfix.mysql.password} - hosts = unix:${config.myEnv.mail.postfix.mysql.socket} - dbname = ${config.myEnv.mail.postfix.mysql.database} - query = SELECT DISTINCT destination - FROM forwardings - WHERE - ((regex = 1 AND '%s' REGEXP CONCAT('^',source,'$') ) OR (regex = 0 AND source = '%s')) - AND active = 1 - AND '%s' NOT IN - ( - SELECT source - FROM forwardings_blacklisted - WHERE source = '%s' - ) UNION - SELECT 'devnull@immae.eu' - FROM forwardings_blacklisted - WHERE source = '%s' - ''; - }; - "postfix/ldap_mailboxes" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - server_host = ldaps://${config.myEnv.mail.dovecot.ldap.host}:636 - search_base = ${config.myEnv.mail.dovecot.ldap.base} - query_filter = ${config.myEnv.mail.dovecot.ldap.postfix_mailbox_filter} - bind_dn = ${config.myEnv.mail.dovecot.ldap.dn} - bind_pw = ${config.myEnv.mail.dovecot.ldap.password} - result_attribute = immaePostfixAddress - result_format = dummy - version = 3 - ''; - }; - "postfix/mysql_sender_login_maps" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - # We need to specify that option to trigger ssl connection - tls_ciphers = TLSv1.2 - user = ${config.myEnv.mail.postfix.mysql.user} - password = ${config.myEnv.mail.postfix.mysql.password} - hosts = unix:${config.myEnv.mail.postfix.mysql.socket} - dbname = ${config.myEnv.mail.postfix.mysql.database} - query = SELECT DISTINCT destination - FROM forwardings - WHERE - ( - (regex = 1 AND CONCAT(SUBSTRING_INDEX('%u', '+', 1), '@%d') REGEXP CONCAT('^',source,'$') ) - OR - (regex = 0 AND source = CONCAT(SUBSTRING_INDEX('%u', '+', 1), '@%d')) - ) - AND active = 1 - UNION SELECT CONCAT(SUBSTRING_INDEX('%u', '+', 1), '@%d') AS destination - ''; - }; - "postfix/mysql_sender_relays_maps" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - # We need to specify that option to trigger ssl connection - tls_ciphers = TLSv1.2 - user = ${config.myEnv.mail.postfix.mysql.user} - password = ${config.myEnv.mail.postfix.mysql.password} - hosts = unix:${config.myEnv.mail.postfix.mysql.socket} - dbname = ${config.myEnv.mail.postfix.mysql.database} - # INSERT INTO sender_relays - # (`from`, owner, relay, login, password, regex, active) - # VALUES - # ( 'sender@otherhost.org' - # , 'me@mail.immae.eu' - # , '[otherhost.org]:587' - # , 'otherhostlogin' - # , AES_ENCRYPT('otherhostpassword', '${config.myEnv.mail.postfix.mysql.password_encrypt}') - # , '0' - # , '1'); - - query = SELECT DISTINCT `owner` - FROM sender_relays - WHERE - ((regex = 1 AND '%s' REGEXP CONCAT('^',`from`,'$') ) OR (regex = 0 AND `from` = '%s')) - AND active = 1 - ''; - }; - "postfix/mysql_sender_relays_hosts" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - # We need to specify that option to trigger ssl connection - tls_ciphers = TLSv1.2 - user = ${config.myEnv.mail.postfix.mysql.user} - password = ${config.myEnv.mail.postfix.mysql.password} - hosts = unix:${config.myEnv.mail.postfix.mysql.socket} - dbname = ${config.myEnv.mail.postfix.mysql.database} - - query = SELECT DISTINCT relay - FROM sender_relays - WHERE - ((regex = 1 AND '%s' REGEXP CONCAT('^',`from`,'$') ) OR (regex = 0 AND `from` = '%s')) - AND active = 1 - ''; - }; - "postfix/mysql_sender_relays_creds" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - # We need to specify that option to trigger ssl connection - tls_ciphers = TLSv1.2 - user = ${config.myEnv.mail.postfix.mysql.user} - password = ${config.myEnv.mail.postfix.mysql.password} - hosts = unix:${config.myEnv.mail.postfix.mysql.socket} - dbname = ${config.myEnv.mail.postfix.mysql.database} - - query = SELECT DISTINCT CONCAT(`login`, ':', AES_DECRYPT(`password`, '${config.myEnv.mail.postfix.mysql.password_encrypt}')) - FROM sender_relays - WHERE - ((regex = 1 AND '%s' REGEXP CONCAT('^',`from`,'$') ) OR (regex = 0 AND `from` = '%s')) - AND active = 1 - ''; - }; - "postfix/ldap_ejabberd_users_immae_fr" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - server_host = ldaps://${config.myEnv.jabber.ldap.host}:636 - search_base = ${config.myEnv.jabber.ldap.base} - query_filter = ${config.myEnv.jabber.postfix_user_filter} - domain = immae.fr - bind_dn = ${config.myEnv.jabber.ldap.dn} - bind_pw = ${config.myEnv.jabber.ldap.password} - result_attribute = immaeXmppUid - result_format = ejabberd@localhost - version = 3 - ''; - }; - } // lib.mapAttrs' (name: v: lib.nameValuePair "postfix/scripts/${name}-env" { - user = "postfixscripts"; - group = "root"; - permissions = "0400"; - text = builtins.toJSON v.env; - }) config.myEnv.mail.scripts; - - networking.firewall.allowedTCPPorts = [ 25 465 587 ]; - - users.users.postfixscripts = { - group = "keys"; - uid = config.ids.uids.postfixscripts; - description = "Postfix scripts user"; - }; - users.users."${config.services.postfix.user}".extraGroups = [ "keys" ]; - services.filesWatcher.postfix = { - restart = true; - paths = [ - config.secrets.fullPaths."postfix/mysql_alias_maps" - config.secrets.fullPaths."postfix/ldap_mailboxes" - config.secrets.fullPaths."postfix/mysql_sender_login_maps" - config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr" - ]; - }; - services.postfix = { - extraAliases = let - toScript = name: script: pkgs.writeScript name '' - #! ${pkgs.stdenv.shell} - mail=$(${pkgs.coreutils}/bin/cat -) - output=$(echo "$mail" | ${script} 2>&1) - ret=$? - - if [ "$ret" != "0" ]; then - echo "$mail" \ - | ${pkgs.procmail}/bin/formail -i "X-Return-Code: $ret" \ - | /run/wrappers/bin/sendmail -i scripts_error+${name}@mail.immae.eu - - messageId=$(echo "$mail" | ${pkgs.procmail}/bin/formail -x "Message-Id:") - repeat=$(echo "$mail" | ${pkgs.procmail}/bin/formail -X "From:" -X "Received:") - - ${pkgs.coreutils}/bin/cat <')" - ''; - }; - in builtins.concatStringsSep "\n" (lib.attrsets.mapAttrsToList (n: v: ''${n}: "|${v}"'') scripts); - mapFiles = let - recipient_maps = let - name = n: i: "relay_${n}_${toString i}"; - pair = n: i: m: lib.attrsets.nameValuePair (name n i) ( - if m.type == "hash" - then pkgs.writeText (name n i) m.content - else null - ); - pairs = n: v: lib.imap1 (i: m: pair n i m) v.recipient_maps; - in lib.attrsets.filterAttrs (k: v: v != null) ( - lib.attrsets.listToAttrs (lib.flatten ( - lib.attrsets.mapAttrsToList pairs config.myEnv.mail.postfix.backup_domains - )) - ); - relay_restrictions = lib.attrsets.filterAttrs (k: v: v != null) ( - lib.attrsets.mapAttrs' (n: v: - lib.attrsets.nameValuePair "recipient_access_${n}" ( - if lib.attrsets.hasAttr "relay_restrictions" v - then pkgs.writeText "recipient_access_${n}" v.relay_restrictions - else null - ) - ) config.myEnv.mail.postfix.backup_domains - ); - virtual_map = { - virtual = let - cfg = config.myEnv.monitoring.email_check.eldiron; - address = "${cfg.mail_address}@${cfg.mail_domain}"; - in pkgs.writeText "postfix-virtual" ( - builtins.concatStringsSep "\n" ( - ["${address} testmail@localhost"] ++ - lib.attrsets.mapAttrsToList ( - n: v: lib.optionalString v.external '' - script_${n}@mail.immae.eu ${n}@localhost, scripts@mail.immae.eu - '' - ) config.myEnv.mail.scripts - ) - ); - }; - sasl_access = { - host_sender_login = with lib.attrsets; let - addresses = zipAttrs (lib.flatten (mapAttrsToList - (n: v: (map (e: { "${e}" = "${n}@immae.eu"; }) v.emails)) config.myEnv.servers)); - joined = builtins.concatStringsSep ","; - in pkgs.writeText "host-sender-login" - (builtins.concatStringsSep "\n" (mapAttrsToList (n: v: "${n} ${joined v}") addresses)); - }; - in - recipient_maps // relay_restrictions // virtual_map // sasl_access; - config = { - ### postfix module overrides - readme_directory = "${pkgs.postfix}/share/postfix/doc"; - smtp_tls_CAfile = lib.mkForce ""; - smtp_tls_cert_file = lib.mkForce ""; - smtp_tls_key_file = lib.mkForce ""; - - message_size_limit = "1073741824"; # Don't put 0 here, it's not equivalent to "unlimited" - mailbox_size_limit = "1073741825"; # Workaround, local delivered mails should all go through scripts - alias_database = "\$alias_maps"; - - ### Aliases scripts user - default_privs = "postfixscripts"; - - ### Virtual mailboxes config - virtual_alias_maps = [ - "hash:/etc/postfix/virtual" - "mysql:${config.secrets.fullPaths."postfix/mysql_alias_maps"}" - "ldap:${config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"}" - ]; - virtual_mailbox_domains = config.myEnv.mail.postfix.additional_mailbox_domains - ++ lib.remove null (lib.flatten (map - (zone: map - (e: if e.receive - then "${e.domain}${lib.optionalString (e.domain != "") "."}${zone.name}" - else null - ) - (zone.withEmail or []) - ) - config.myEnv.dns.masterZones - )); - virtual_mailbox_maps = [ - "ldap:${config.secrets.fullPaths."postfix/ldap_mailboxes"}" - ]; - dovecot_destination_recipient_limit = "1"; - virtual_transport = "dovecot"; - - ### Relay domains - relay_domains = lib.flatten (lib.attrsets.mapAttrsToList (n: v: v.domains or []) config.myEnv.mail.postfix.backup_domains); - relay_recipient_maps = lib.flatten (lib.attrsets.mapAttrsToList (n: v: - lib.imap1 (i: m: "${m.type}:/etc/postfix/relay_${n}_${toString i}") v.recipient_maps - ) config.myEnv.mail.postfix.backup_domains); - smtpd_relay_restrictions = [ - "defer_unauth_destination" - ] ++ lib.flatten (lib.attrsets.mapAttrsToList (n: v: - if lib.attrsets.hasAttr "relay_restrictions" v - then [ "check_recipient_access hash:/etc/postfix/recipient_access_${n}" ] - else [] - ) config.myEnv.mail.postfix.backup_domains); - - ### Additional smtpd configuration - smtpd_tls_received_header = "yes"; - smtpd_tls_loglevel = "1"; - - ### Email sending configuration - smtp_tls_security_level = "may"; - smtp_tls_loglevel = "1"; - - ### Force ip bind for smtp - smtp_bind_address = config.hostEnv.ips.main.ip4; - smtp_bind_address6 = builtins.head config.hostEnv.ips.main.ip6; - - # Use some relays when authorized senders are not myself - smtp_sasl_mechanism_filter = "plain,login"; # GSSAPI Not correctly supported by postfix - smtp_sasl_auth_enable = "yes"; - smtp_sasl_password_maps = - "mysql:${config.secrets.fullPaths."postfix/mysql_sender_relays_creds"}"; - smtp_sasl_security_options = "noanonymous"; - smtp_sender_dependent_authentication = "yes"; - sender_dependent_relayhost_maps = - "mysql:${config.secrets.fullPaths."postfix/mysql_sender_relays_hosts"}"; - - ### opendkim, opendmarc, openarc milters - non_smtpd_milters = [ - "unix:${config.myServices.mail.milters.sockets.opendkim}" - ]; - smtpd_milters = [ - "unix:${config.myServices.mail.milters.sockets.opendkim}" - "unix:${config.myServices.mail.milters.sockets.openarc}" - "unix:${config.myServices.mail.milters.sockets.opendmarc}" - ]; - - smtp_use_tls = true; - smtpd_use_tls = true; - smtpd_tls_chain_files = builtins.concatStringsSep "," [ "/var/lib/acme/mail/full.pem" "/var/lib/acme/mail-rsa/full.pem" ]; - - maximal_queue_lifetime = "6w"; - bounce_queue_lifetime = "6w"; - }; - enable = true; - enableSmtp = true; - enableSubmission = true; - submissionOptions = { - # Don’t use "long form", only commas (cf - # http://www.postfix.org/master.5.html long form is not handled - # well by the submission function) - smtpd_tls_security_level = "encrypt"; - smtpd_sasl_auth_enable = "yes"; - smtpd_tls_auth_only = "yes"; - smtpd_sasl_tls_security_options = "noanonymous"; - smtpd_sasl_type = "dovecot"; - smtpd_sasl_path = "private/auth"; - smtpd_reject_unlisted_recipient = "no"; - smtpd_client_restrictions = "permit_sasl_authenticated,reject"; - smtpd_relay_restrictions = "permit_sasl_authenticated,reject"; - # Refuse to send e-mails with a From that is not handled - smtpd_sender_restrictions = - "reject_sender_login_mismatch,reject_unlisted_sender,permit_sasl_authenticated,reject"; - smtpd_sender_login_maps = builtins.concatStringsSep "," [ - "hash:/etc/postfix/host_sender_login" - "mysql:${config.secrets.fullPaths."postfix/mysql_sender_relays_maps"}" - "mysql:${config.secrets.fullPaths."postfix/mysql_sender_login_maps"}" - ]; - smtpd_recipient_restrictions = "permit_sasl_authenticated,reject"; - milter_macro_daemon_name = "ORIGINATING"; - smtpd_milters = builtins.concatStringsSep "," [ - # FIXME: put it back when opensmtpd is upgraded and able to - # rewrite the from header - #"unix:/run/milter_verify_from/verify_from.sock" - "unix:${config.myServices.mail.milters.sockets.opendkim}" - ]; - }; - destination = ["localhost"]; - # This needs to reverse DNS - hostname = config.hostEnv.fqdn; - setSendmail = true; - recipientDelimiter = "+"; - masterConfig = { - submissions = { - type = "inet"; - private = false; - command = "smtpd"; - args = ["-o" "smtpd_tls_wrappermode=yes" ] ++ (let - mkKeyVal = opt: val: [ "-o" (opt + "=" + val) ]; - in lib.concatLists (lib.mapAttrsToList mkKeyVal config.services.postfix.submissionOptions) - ); - }; - dovecot = { - type = "unix"; - privileged = true; - chroot = false; - command = "pipe"; - args = let - # rspamd could be used as a milter, but then it cannot apply - # its checks "per user" (milter is not yet dispatched to - # users), so we wrap dovecot-lda inside rspamc per recipient - # here. - rspamc_dovecot = pkgs.writeScriptBin "rspamc_dovecot" '' - #! ${pkgs.stdenv.shell} - sender="$1" - original_recipient="$2" - user="$3" - - ${pkgs.coreutils}/bin/cat - | \ - (${pkgs.rspamd}/bin/rspamc -h ${config.myServices.mail.rspamd.sockets.worker-controller} -c bayes -d "$user" --mime || true) | \ - ${pkgs.dovecot}/libexec/dovecot/dovecot-lda -f "$sender" -a "$original_recipient" -d "$user" - ''; - in [ - "flags=ODRhu" "user=vhost:vhost" - "argv=${rspamc_dovecot}/bin/rspamc_dovecot \${sender} \${original_recipient} \${user}@\${nexthop}" - ]; - }; - }; - }; - security.acme.certs."mail" = { - postRun = '' - systemctl restart postfix.service - ''; - extraDomains = { - "smtp.immae.eu" = null; - }; - }; - security.acme.certs."mail-rsa" = { - postRun = '' - systemctl restart postfix.service - ''; - extraDomains = { - "smtp.immae.eu" = null; - }; - }; - system.activationScripts.testmail = { - deps = [ "users" ]; - text = let - allCfg = config.myEnv.monitoring.email_check; - cfg = allCfg.eldiron; - reverseTargets = builtins.attrNames (lib.attrsets.filterAttrs (k: v: builtins.elem "eldiron" v.targets) allCfg); - to_email = cfg': host': - let sep = if lib.strings.hasInfix "+" cfg'.mail_address then "_" else "+"; - in "${cfg'.mail_address}${sep}${host'}@${cfg'.mail_domain}"; - mails_to_receive = builtins.concatStringsSep " " (map (to_email cfg) reverseTargets); - in '' - install -m 0555 -o postfixscripts -g keys -d /var/lib/naemon/checks/email - for f in ${mails_to_receive}; do - if [ ! -f /var/lib/naemon/checks/email/$f ]; then - install -m 0644 -o postfixscripts -g keys /dev/null -T /var/lib/naemon/checks/email/$f - touch -m -d @0 /var/lib/naemon/checks/email/$f - fi - done - ''; - }; - systemd.services.postfix.serviceConfig.Slice = "mail.slice"; - }; -} diff --git a/modules/private/mail/relay.nix b/modules/private/mail/relay.nix deleted file mode 100644 index 668d365..0000000 --- a/modules/private/mail/relay.nix +++ /dev/null @@ -1,235 +0,0 @@ -{ lib, pkgs, config, nodes, name, ... }: -{ - config = lib.mkIf config.myServices.mailBackup.enable { - security.acme.certs."mail" = config.myServices.certificates.certConfig // { - postRun = '' - systemctl restart postfix.service - ''; - domain = config.hostEnv.fqdn; - extraDomains = let - zonesWithMx = builtins.filter (zone: - lib.attrsets.hasAttr "withEmail" zone && lib.lists.length zone.withEmail > 0 - ) config.myEnv.dns.masterZones; - mxs = map (zone: "${config.myEnv.servers."${name}".mx.subdomain}.${zone.name}") zonesWithMx; - in builtins.listToAttrs (map (mx: lib.attrsets.nameValuePair mx null) mxs); - }; - secrets.keys = { - "postfix/mysql_alias_maps" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - # We need to specify that option to trigger ssl connection - tls_ciphers = TLSv1.2 - user = ${config.myEnv.mail.postfix.mysql.user} - password = ${config.myEnv.mail.postfix.mysql.password} - hosts = ${config.myEnv.mail.postfix.mysql.remoteHost} - dbname = ${config.myEnv.mail.postfix.mysql.database} - query = SELECT DISTINCT 1 - FROM forwardings - WHERE - ((regex = 1 AND '%s' REGEXP CONCAT('^',source,'$') ) OR (regex = 0 AND source = '%s')) - AND active = 1 - AND '%s' NOT IN - ( - SELECT source - FROM forwardings_blacklisted - WHERE source = '%s' - ) UNION - SELECT 'devnull@immae.eu' - FROM forwardings_blacklisted - WHERE source = '%s' - ''; - }; - "postfix/ldap_mailboxes" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - server_host = ldaps://${config.myEnv.mail.dovecot.ldap.host}:636 - search_base = ${config.myEnv.mail.dovecot.ldap.base} - query_filter = ${config.myEnv.mail.dovecot.ldap.postfix_mailbox_filter} - bind_dn = ${config.myEnv.mail.dovecot.ldap.dn} - bind_pw = ${config.myEnv.mail.dovecot.ldap.password} - result_attribute = immaePostfixAddress - result_format = dummy - version = 3 - ''; - }; - "postfix/sympa_mailbox_maps" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - hosts = ${config.myEnv.mail.sympa.postgresql.host} - user = ${config.myEnv.mail.sympa.postgresql.user} - password = ${config.myEnv.mail.sympa.postgresql.password} - dbname = ${config.myEnv.mail.sympa.postgresql.database} - query = SELECT DISTINCT 1 FROM list_table WHERE '%s' IN ( - CONCAT(name_list, '@', robot_list), - CONCAT(name_list, '-request@', robot_list), - CONCAT(name_list, '-editor@', robot_list), - CONCAT(name_list, '-unsubscribe@', robot_list), - CONCAT(name_list, '-owner@', robot_list), - CONCAT('sympa-request@', robot_list), - CONCAT('sympa-owner@', robot_list), - CONCAT('sympa@', robot_list), - CONCAT('listmaster@', robot_list), - CONCAT('bounce@', robot_list), - CONCAT('abuse-feedback-report@', robot_list) - ) - ''; - }; - "postfix/ldap_ejabberd_users_immae_fr" = { - user = config.services.postfix.user; - group = config.services.postfix.group; - permissions = "0440"; - text = '' - server_host = ldaps://${config.myEnv.jabber.ldap.host}:636 - search_base = ${config.myEnv.jabber.ldap.base} - query_filter = ${config.myEnv.jabber.postfix_user_filter} - domain = immae.fr - bind_dn = ${config.myEnv.jabber.ldap.dn} - bind_pw = ${config.myEnv.jabber.ldap.password} - result_attribute = immaeXmppUid - result_format = ejabberd@localhost - version = 3 - ''; - }; - }; - - networking.firewall.allowedTCPPorts = [ 25 ]; - - users.users."${config.services.postfix.user}".extraGroups = [ "keys" ]; - services.filesWatcher.postfix = { - restart = true; - paths = [ - config.secrets.fullPaths."postfix/mysql_alias_maps" - config.secrets.fullPaths."postfix/sympa_mailbox_maps" - config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr" - config.secrets.fullPaths."postfix/ldap_mailboxes" - ]; - }; - services.postfix = { - mapFiles = let - recipient_maps = let - name = n: i: "relay_${n}_${toString i}"; - pair = n: i: m: lib.attrsets.nameValuePair (name n i) ( - if m.type == "hash" - then pkgs.writeText (name n i) m.content - else null - ); - pairs = n: v: lib.imap1 (i: m: pair n i m) v.recipient_maps; - in lib.attrsets.filterAttrs (k: v: v != null) ( - lib.attrsets.listToAttrs (lib.flatten ( - lib.attrsets.mapAttrsToList pairs config.myEnv.mail.postfix.backup_domains - )) - ); - relay_restrictions = lib.attrsets.filterAttrs (k: v: v != null) ( - lib.attrsets.mapAttrs' (n: v: - lib.attrsets.nameValuePair "recipient_access_${n}" ( - if lib.attrsets.hasAttr "relay_restrictions" v - then pkgs.writeText "recipient_access_${n}" v.relay_restrictions - else null - ) - ) config.myEnv.mail.postfix.backup_domains - ); - virtual_map = { - virtual = let - cfg = config.myEnv.monitoring.email_check.eldiron; - address = "${cfg.mail_address}@${cfg.mail_domain}"; - in pkgs.writeText "postfix-virtual" ( - builtins.concatStringsSep "\n" ( - ["${address} 1"] ++ - lib.attrsets.mapAttrsToList ( - n: v: lib.optionalString v.external '' - script_${n}@mail.immae.eu 1 - '' - ) config.myEnv.mail.scripts - ) - ); - }; - in - recipient_maps // relay_restrictions // virtual_map; - config = { - ### postfix module overrides - readme_directory = "${pkgs.postfix}/share/postfix/doc"; - smtp_tls_CAfile = lib.mkForce ""; - smtp_tls_cert_file = lib.mkForce ""; - smtp_tls_key_file = lib.mkForce ""; - - message_size_limit = "1073741824"; # Don't put 0 here, it's not equivalent to "unlimited" - mailbox_size_limit = "1073741825"; # Workaround, local delivered mails should all go through scripts - alias_database = "\$alias_maps"; - - ### Relay domains - relay_domains = let - backups = lib.flatten (lib.attrsets.mapAttrsToList (n: v: v.domains or []) config.myEnv.mail.postfix.backup_domains); - virtual_domains = config.myEnv.mail.postfix.additional_mailbox_domains - ++ lib.remove null (lib.flatten (map - (zone: map - (e: if e.receive - then "${e.domain}${lib.optionalString (e.domain != "") "."}${zone.name}" - else null - ) - (zone.withEmail or []) - ) - config.myEnv.dns.masterZones - )); - in - backups ++ virtual_domains; - relay_recipient_maps = let - backup_recipients = lib.flatten (lib.attrsets.mapAttrsToList (n: v: - lib.imap1 (i: m: "${m.type}:/etc/postfix/relay_${n}_${toString i}") v.recipient_maps - ) config.myEnv.mail.postfix.backup_domains); - virtual_alias_maps = [ - "hash:/etc/postfix/virtual" - "mysql:${config.secrets.fullPaths."postfix/mysql_alias_maps"}" - "ldap:${config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"}" - ]; - virtual_mailbox_maps = [ - "ldap:${config.secrets.fullPaths."postfix/ldap_mailboxes"}" - "pgsql:${config.secrets.fullPaths."postfix/sympa_mailbox_maps"}" - ]; - in - backup_recipients ++ virtual_alias_maps ++ virtual_mailbox_maps; - smtpd_relay_restrictions = [ - "defer_unauth_destination" - ] ++ lib.flatten (lib.attrsets.mapAttrsToList (n: v: - if lib.attrsets.hasAttr "relay_restrictions" v - then [ "check_recipient_access hash:/etc/postfix/recipient_access_${n}" ] - else [] - ) config.myEnv.mail.postfix.backup_domains); - - ### Additional smtpd configuration - smtpd_tls_received_header = "yes"; - smtpd_tls_loglevel = "1"; - - ### Email sending configuration - smtp_tls_security_level = "may"; - smtp_tls_loglevel = "1"; - - ### Force ip bind for smtp - smtp_bind_address = config.myEnv.servers."${name}".ips.main.ip4; - smtp_bind_address6 = builtins.head config.myEnv.servers."${name}".ips.main.ip6; - - smtpd_milters = [ - "unix:${config.myServices.mail.milters.sockets.opendkim}" - "unix:${config.myServices.mail.milters.sockets.openarc}" - "unix:${config.myServices.mail.milters.sockets.opendmarc}" - ]; - }; - enable = true; - enableSmtp = true; - enableSubmission = false; - destination = ["localhost"]; - # This needs to reverse DNS - hostname = config.hostEnv.fqdn; - setSendmail = false; - sslCert = "/var/lib/acme/mail/fullchain.pem"; - sslKey = "/var/lib/acme/mail/key.pem"; - recipientDelimiter = "+"; - }; - }; -} - diff --git a/modules/private/mail/rspamd.nix b/modules/private/mail/rspamd.nix deleted file mode 100644 index 05f1300..0000000 --- a/modules/private/mail/rspamd.nix +++ /dev/null @@ -1,87 +0,0 @@ -{ lib, pkgs, config, ... }: -{ - options.myServices.mail.rspamd.sockets = lib.mkOption { - type = lib.types.attrsOf lib.types.path; - default = { - worker-controller = "/run/rspamd/worker-controller.sock"; - }; - readOnly = true; - description = '' - rspamd sockets - ''; - }; - config = lib.mkIf config.myServices.mail.enable { - services.cron.systemCronJobs = let - cron_script = pkgs.runCommand "cron_script" { - buildInputs = [ pkgs.makeWrapper ]; - } '' - mkdir -p $out - cp ${./scan_reported_mails} $out/scan_reported_mails - patchShebangs $out - for i in $out/*; do - wrapProgram "$i" --prefix PATH : ${lib.makeBinPath [ pkgs.coreutils pkgs.rspamd pkgs.flock ]} - done - ''; - in - [ "*/20 * * * * vhost ${cron_script}/scan_reported_mails" ]; - - systemd.services.rspamd.serviceConfig.Slice = "mail.slice"; - services.rspamd = { - enable = true; - debug = false; - overrides = { - "actions.conf".text = '' - reject = null; - add_header = 6; - greylist = null; - ''; - "milter_headers.conf".text = '' - extended_spam_headers = true; - ''; - }; - locals = { - "redis.conf".text = '' - servers = "${config.myEnv.mail.rspamd.redis.socket}"; - db = "${config.myEnv.mail.rspamd.redis.db}"; - ''; - "classifier-bayes.conf".text = '' - users_enabled = true; - backend = "redis"; - servers = "${config.myEnv.mail.rspamd.redis.socket}"; - database = "${config.myEnv.mail.rspamd.redis.db}"; - autolearn = true; - cache { - backend = "redis"; - } - new_schema = true; - statfile { - BAYES_HAM { - spam = false; - } - BAYES_SPAM { - spam = true; - } - } - ''; - }; - workers = { - controller = { - extraConfig = '' - enable_password = "${config.myEnv.mail.rspamd.write_password_hashed}"; - password = "${config.myEnv.mail.rspamd.read_password_hashed}"; - ''; - bindSockets = [ { - socket = config.myServices.mail.rspamd.sockets.worker-controller; - mode = "0660"; - owner = config.services.rspamd.user; - group = "vhost"; - } ]; - }; - }; - postfix = { - enable = true; - config = {}; - }; - }; - }; -} diff --git a/modules/private/mail/scan_reported_mails b/modules/private/mail/scan_reported_mails deleted file mode 100755 index fe9f4d6..0000000 --- a/modules/private/mail/scan_reported_mails +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -( flock -n 9 || exit 1 -shopt -s nullglob -for spool in /var/lib/vhost/.rspamd/*/pending; do - rspamd_folder=$(dirname $spool) - mail_user=$(basename $rspamd_folder) - mv $rspamd_folder/pending $rspamd_folder/processing - - for mtype in ham spam; do - if [ -d $rspamd_folder/processing/$mtype ]; then - output="$(rspamc -h /run/rspamd/worker-controller.sock -c bayes -d $mail_user learn_$mtype $rspamd_folder/processing/$mtype/*)" - echo "[$mtype: $mail_user]" ${output} >> /var/lib/vhost/.rspamd/rspamd.log - mkdir -p $rspamd_folder/processed/$mtype - cp $rspamd_folder/processing/$mtype/* $rspamd_folder/processed/$mtype/ - fi - done - - rm -rf $rspamd_folder/processing -done -) 9>/var/lib/vhost/scan_reported_mails.lock diff --git a/modules/private/mail/sieve_bin/imapsieve_copy b/modules/private/mail/sieve_bin/imapsieve_copy deleted file mode 100755 index 2ca1f23..0000000 --- a/modules/private/mail/sieve_bin/imapsieve_copy +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -# Inspired from https://docs.iredmail.org/dovecot.imapsieve.html - -MSG_TYPE="$1" -OUTPUT_DIR="/var/lib/vhost/.rspamd/${USER}/pending/${MSG_TYPE}" -FILE="${OUTPUT_DIR}/$(date +%Y%m%d%H%M%S)-${RANDOM}${RANDOM}.eml" -mkdir -p "${OUTPUT_DIR}" -cat > ${FILE} < /dev/stdin diff --git a/modules/private/mail/sieve_scripts/backup.sieve b/modules/private/mail/sieve_scripts/backup.sieve deleted file mode 100644 index 3014c0a..0000000 --- a/modules/private/mail/sieve_scripts/backup.sieve +++ /dev/null @@ -1,7 +0,0 @@ -# vim: filetype=sieve -require ["copy","mailbox","fileinto","regex"]; -if header :is "X-Spam" "Yes" { - fileinto :create :copy "Backup/Spam"; -} else { - fileinto :create :copy "Backup/Ham"; -} diff --git a/modules/private/mail/sieve_scripts/report_ham.sieve b/modules/private/mail/sieve_scripts/report_ham.sieve deleted file mode 100644 index f9b8481..0000000 --- a/modules/private/mail/sieve_scripts/report_ham.sieve +++ /dev/null @@ -1,11 +0,0 @@ -require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"]; - -if environment :matches "imap.mailbox" "*" { - set "mailbox" "${1}"; -} - -if string "${mailbox}" "Trash" { - stop; -} - -pipe :copy "imapsieve_copy" [ "ham" ]; diff --git a/modules/private/mail/sieve_scripts/report_spam.sieve b/modules/private/mail/sieve_scripts/report_spam.sieve deleted file mode 100644 index 9a1f794..0000000 --- a/modules/private/mail/sieve_scripts/report_spam.sieve +++ /dev/null @@ -1,3 +0,0 @@ -require ["vnd.dovecot.pipe", "copy", "imapsieve" ]; - -pipe :copy "imapsieve_copy" [ "spam" ]; diff --git a/modules/private/mail/sympa.nix b/modules/private/mail/sympa.nix deleted file mode 100644 index 0626ac0..0000000 --- a/modules/private/mail/sympa.nix +++ /dev/null @@ -1,213 +0,0 @@ -{ lib, pkgs, config, ... }: -let - domain = "lists.immae.eu"; - sympaConfig = config.myEnv.mail.sympa; -in -{ - config = lib.mkIf config.myServices.mail.enable { - myServices.databases.postgresql.authorizedHosts = { - backup-2 = [ - { - username = "sympa"; - database = "sympa"; - ip4 = [config.myEnv.servers.backup-2.ips.main.ip4]; - ip6 = config.myEnv.servers.backup-2.ips.main.ip6; - } - ]; - }; - services.websites.env.tools.vhostConfs.mail = { - extraConfig = lib.mkAfter [ - '' - Alias /static-sympa/ /var/lib/sympa/static_content/ - - Require all granted - AllowOverride none - - - SetHandler "proxy:unix:/run/sympa/wwsympa.socket|fcgi://" - Require all granted - - '' - ]; - }; - - secrets.keys = { - "sympa/db_password" = { - permissions = "0400"; - group = "sympa"; - user = "sympa"; - text = sympaConfig.postgresql.password; - }; - } - // lib.mapAttrs' (n: v: lib.nameValuePair "sympa/data_sources/${n}.incl" { - permissions = "0400"; group = "sympa"; user = "sympa"; text = v; - }) sympaConfig.data_sources - // lib.mapAttrs' (n: v: lib.nameValuePair "sympa/scenari/${n}" { - permissions = "0400"; group = "sympa"; user = "sympa"; text = v; - }) sympaConfig.scenari; - users.users.sympa.extraGroups = [ "keys" ]; - systemd.slices.mail-sympa = { - description = "Sympa slice"; - }; - - systemd.services.sympa.serviceConfig.SupplementaryGroups = [ "keys" ]; - systemd.services.sympa-archive.serviceConfig.SupplementaryGroups = [ "keys" ]; - systemd.services.sympa-bounce.serviceConfig.SupplementaryGroups = [ "keys" ]; - systemd.services.sympa-bulk.serviceConfig.SupplementaryGroups = [ "keys" ]; - systemd.services.sympa-task.serviceConfig.SupplementaryGroups = [ "keys" ]; - - systemd.services.sympa.serviceConfig.Slice = "mail-sympa.slice"; - systemd.services.sympa-archive.serviceConfig.Slice = "mail-sympa.slice"; - systemd.services.sympa-bounce.serviceConfig.Slice = "mail-sympa.slice"; - systemd.services.sympa-bulk.serviceConfig.Slice = "mail-sympa.slice"; - systemd.services.sympa-task.serviceConfig.Slice = "mail-sympa.slice"; - - # https://github.com/NixOS/nixpkgs/pull/84202 - systemd.services.sympa.serviceConfig.ProtectKernelModules = lib.mkForce false; - systemd.services.sympa-archive.serviceConfig.ProtectKernelModules = lib.mkForce false; - systemd.services.sympa-bounce.serviceConfig.ProtectKernelModules = lib.mkForce false; - systemd.services.sympa-bulk.serviceConfig.ProtectKernelModules = lib.mkForce false; - systemd.services.sympa-task.serviceConfig.ProtectKernelModules = lib.mkForce false; - systemd.services.sympa.serviceConfig.ProtectKernelTunables = lib.mkForce false; - systemd.services.sympa-archive.serviceConfig.ProtectKernelTunables = lib.mkForce false; - systemd.services.sympa-bounce.serviceConfig.ProtectKernelTunables = lib.mkForce false; - systemd.services.sympa-bulk.serviceConfig.ProtectKernelTunables = lib.mkForce false; - systemd.services.sympa-task.serviceConfig.ProtectKernelTunables = lib.mkForce false; - - systemd.services.wwsympa = { - wantedBy = [ "multi-user.target" ]; - after = [ "sympa.service" ]; - serviceConfig = { - Slice = "mail-sympa.slice"; - Type = "forking"; - PIDFile = "/run/sympa/wwsympa.pid"; - Restart = "always"; - ExecStart = ''${pkgs.spawn_fcgi}/bin/spawn-fcgi \ - -u sympa \ - -g sympa \ - -U wwwrun \ - -M 0600 \ - -F 2 \ - -P /run/sympa/wwsympa.pid \ - -s /run/sympa/wwsympa.socket \ - -- ${pkgs.sympa}/lib/sympa/cgi/wwsympa.fcgi - ''; - StateDirectory = "sympa"; - ProtectHome = true; - ProtectSystem = "full"; - ProtectControlGroups = true; - }; - }; - - services.postfix = { - mapFiles = { - # Update relay list when changing one of those - sympa_virtual = pkgs.writeText "virtual.sympa" '' - sympa-request@${domain} postmaster@immae.eu - sympa-owner@${domain} postmaster@immae.eu - - sympa-request@cip-ca.fr postmaster@immae.eu - sympa-owner@cip-ca.fr postmaster@immae.eu - ''; - sympa_transport = pkgs.writeText "transport.sympa" '' - ${domain} error:User unknown in recipient table - sympa@${domain} sympa:sympa@${domain} - listmaster@${domain} sympa:listmaster@${domain} - bounce@${domain} sympabounce:sympa@${domain} - abuse-feedback-report@${domain} sympabounce:sympa@${domain} - - sympa@cip-ca.fr sympa:sympa@cip-ca.fr - listmaster@cip-ca.fr sympa:listmaster@cip-ca.fr - bounce@cip-ca.fr sympabounce:sympa@cip-ca.fr - abuse-feedback-report@cip-ca.fr sympabounce:sympa@cip-ca.fr - ''; - }; - config = { - transport_maps = lib.mkAfter [ - "hash:/etc/postfix/sympa_transport" - "hash:/var/lib/sympa/sympa_transport" - ]; - virtual_alias_maps = lib.mkAfter [ - "hash:/etc/postfix/sympa_virtual" - ]; - virtual_mailbox_maps = lib.mkAfter [ - "hash:/etc/postfix/sympa_transport" - "hash:/var/lib/sympa/sympa_transport" - "hash:/etc/postfix/sympa_virtual" - ]; - }; - masterConfig = { - sympa = { - type = "unix"; - privileged = true; - chroot = false; - command = "pipe"; - args = [ - "flags=hqRu" - "user=sympa" - "argv=${pkgs.sympa}/libexec/queue" - "\${nexthop}" - ]; - }; - sympabounce = { - type = "unix"; - privileged = true; - chroot = false; - command = "pipe"; - args = [ - "flags=hqRu" - "user=sympa" - "argv=${pkgs.sympa}/libexec/bouncequeue" - "\${nexthop}" - ]; - }; - }; - }; - services.sympa = { - enable = true; - listMasters = sympaConfig.listmasters; - mainDomain = domain; - domains = { - "${domain}" = { - webHost = "mail.immae.eu"; - webLocation = "/sympa"; - }; - "cip-ca.fr" = { - webHost = "mail.cip-ca.fr"; - webLocation = "/sympa"; - }; - }; - - database = { - type = "PostgreSQL"; - user = sympaConfig.postgresql.user; - host = sympaConfig.postgresql.socket; - name = sympaConfig.postgresql.database; - passwordFile = config.secrets.fullPaths."sympa/db_password"; - createLocally = false; - }; - settings = { - sendmail = "/run/wrappers/bin/sendmail"; - log_smtp = "on"; - sendmail_aliases = "/var/lib/sympa/sympa_transport"; - aliases_program = "${pkgs.postfix}/bin/postmap"; - }; - settingsFile = { - "virtual.sympa".enable = false; - "transport.sympa".enable = false; - } // lib.mapAttrs' (n: v: lib.nameValuePair - "etc/${domain}/data_sources/${n}.incl" - { source = config.secrets.fullPaths."sympa/data_sources/${n}.incl"; }) sympaConfig.data_sources - // lib.mapAttrs' (n: v: lib.nameValuePair - "etc/${domain}/scenari/${n}" - { source = config.secrets.fullPaths."sympa/scenari/${n}"; }) sympaConfig.scenari; - web = { - server = "none"; - }; - - mta = { - type = "none"; - }; - }; - }; -} diff --git a/modules/private/mail/verify_from.py b/modules/private/mail/verify_from.py deleted file mode 100755 index b75001e..0000000 --- a/modules/private/mail/verify_from.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python3 -import Milter -import argparse -from email.header import decode_header -from email.utils import parseaddr - -class CheckMilter(Milter.Base): - def __init__(self): - self.envelope_from = None - self.header_from = None - - @Milter.noreply - def connect(self, IPname, family, hostaddr): - return Milter.CONTINUE - - def hello(self, heloname): - return Milter.CONTINUE - - def envfrom(self, mailfrom, *args): - self.envelope_from = parseaddr(mailfrom)[1] - return Milter.CONTINUE - - @Milter.noreply - def envrcpt(self, to, *str): - return Milter.CONTINUE - - @Milter.noreply - def header(self, name, hval): - if name.lower() == "from": - self.header_from = parseaddr(decode_header(hval)[-1][0])[1] - return Milter.CONTINUE - - def eoh(self): - if self.header_from is not None and self.header_from != "" and self.header_from != self.envelope_from: - self.setreply("553", xcode="5.7.1", msg="<%s>: From header rejected: not matching envelope From %s" - % (self.header_from, self.envelope_from)) - return Milter.REJECT - - return Milter.CONTINUE - - @Milter.noreply - def body(self, chunk): - return Milter.CONTINUE - - def eom(self): - return Milter.ACCEPT - - def close(self): - return Milter.CONTINUE - - def abort(self): - return Milter.CONTINUE - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("--socket", "-s", type=str, help="socket to listen to") - config = parser.parse_args() - - Milter.factory = CheckMilter - Milter.runmilter("check_from", config.socket, timeout=300) -- cgit v1.2.3