ctucx.git: nixfiles

ctucx' nixfiles

commit c9128cf5f8fd469a173af00faa69e627de34bd5c
parent e7f0fcec1d172d250fb0c2e50d4aaff32da8d855
Author: Leah (ctucx) <leah@ctu.cx>
Date: Wed, 7 Sep 2022 17:13:15 +0200

machines/osterei/maddy: implement mail and mailbox filtering
2 files changed, 179 insertions(+), 66 deletions(-)
M
machines/osterei/maddy.nix
|
124
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
M
secrets/default.nix.age
|
121
+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
diff --git a/machines/osterei/maddy.nix b/machines/osterei/maddy.nix
@@ -1,6 +1,42 @@
 { config, lib, pkgs, ... }:
 
-{
+let
+  maddy                = pkgs.callPackage ../../pkgs/maddy.nix {};
+  secrets              = import ../../secrets/default.nix;
+
+  writePythonScriptBin = name: packagesSelectionFun: text:
+    let
+      mkScriptName = s: (builtins.replaceStrings [ "\\" ] [ "-" ] s);
+      x = pkgs.writeTextFile { name = "unit-script.py"; executable = true; destination = "/bin/${mkScriptName name}"; text = "#!/usr/bin/env python3\n${text}"; };
+      deriv = pkgs.stdenv.mkDerivation {
+        name = mkScriptName name;
+        buildInputs = [ (pkgs.python3.withPackages (pythonPackages: packagesSelectionFun pythonPackages)) ];
+        unpackPhase = "true";
+        installPhase = ''
+          mkdir -p $out/bin
+          cp ${x}/bin/${mkScriptName name} $out/bin/${mkScriptName name}
+        '';
+      };
+    in "${deriv}/bin/${mkScriptName name}";
+
+in {
+
+  nixpkgs.overlays = [
+    (final: prev: {
+      maddy = maddy;
+    })
+  ];
+
+  environment.etc."maddy/filters/mailbox/leah@ctu.cx.toml".text = "${builtins.toJSON secrets.maddy.mailboxFilter}";
+  environment.etc."maddy/filters/receive.toml".text             = "${builtins.toJSON secrets.maddy.receiveFilter}";
+
+  security.acme.certs."osterei.ctu.cx".reloadServices           = [ "maddy.service" ];
+
+  systemd.services.maddy.serviceConfig.ReadOnlyPaths            = [ "/etc/maddy/filters" ];
+
+  age.secrets.restic-maddy.file                                 = ../../secrets/osterei/restic/maddy.age;
+
+  networking.firewall.allowedTCPPorts                           = [ 25 143 465 587 993 ];
 
   users.groups.maddy = {};
   users.users.maddy = {

@@ -10,24 +46,12 @@
     extraGroups  = [ "nginx" ];
   };
 
-  age.secrets.restic-maddy.file = ../../secrets/osterei/restic/maddy.age;
-
   restic-backups.maddy = {
     user         = "maddy";
     passwordFile = config.age.secrets.restic-maddy.path;
     paths        = [ "/var/lib/maddy" ];
   };
 
-  security.acme.certs."osterei.ctu.cx".reloadServices = [ "maddy.service" ];
-
-  networking.firewall.allowedTCPPorts = [
-    25
-    143
-    465
-    587
-    993
-  ];
-
   services.maddy = {
     enable        = true;
     user          = "maddy";

@@ -37,13 +61,13 @@
     localDomains  = [
       "$(hostname)"
       "$(primary_domain)"
-      "antifa.jetzt"
       "thein.ovh"
       "ctucx.de"
       "trans-agenda.de"
     ];
 
     config = ''
+      #debug on
       log syslog
       
       tls file /var/lib/acme/osterei.ctu.cx/fullchain.pem /var/lib/acme/osterei.ctu.cx/key.pem

@@ -79,6 +103,36 @@
       storage.imapsql local_mailboxes {
           driver sqlite3
           dsn imapsql.db
+          disable_recent false
+          compression zstd
+
+          imap_filter {
+              command ${writePythonScriptBin "mailbox-filter.py" (ps: [ ps.toml ]) ''
+                from email.header import Header, decode_header, make_header
+                import sys, toml, re
+
+                try:
+                  account_name = sys.argv[1]
+                  sender       = sys.argv[2]
+                  recipient    = sys.argv[3]
+                  subject      = make_header(decode_header(sys.argv[4]))
+
+                  config= toml.load('/etc/maddy/filters/mailbox/' + account_name + '.toml')
+
+                  for type in [ 'recipient', 'subject', 'sender' ]:
+                    if type not in config:
+                      continue
+
+                    for key, value in config[type].items():
+                      if(re.search(str("^" + key + "$"), str(eval(type)))):
+                        print(value.replace(",", "\n"))
+                        sys.exit(0)
+
+                except:
+                  sys.exit(0)
+              ''} {account_name} {sender} {original_rcpt_to} {subject}
+          }
+
       }
       
       # ----------------------------------------------------------------------------

@@ -92,21 +146,49 @@
               spf {
                   permerr_action ignore
               }
+              command ${writePythonScriptBin "receive-filter.py" (ps: [ ps.toml ]) ''
+                import sys, toml
+
+                try:
+                  sender    = sys.argv[1]
+                  recipient = sys.argv[2]
+                  config    = toml.load('/etc/maddy/filters/receive.toml')
+
+                  for type in [ 'recipient', 'sender' ]:
+                    if type not in config:
+                      continue
+
+                    if 'reject' in config[type]:
+                      if(eval(type) in config[type]['reject']):
+                        sys.exit(10)
+
+                    if('quarantine' in config[type]):
+                      if(eval(type) in config[type]['quarantine']):
+                        sys.exit(20)
+
+                except SystemExit as e:
+                  sys.exit(e)
+
+                except:
+                  pass
+
+                sys.exit(0)
+              ''} {sender} {rcpts} {
+                  run_on rcpt
+
+                  code 1 ignore
+                  code 2 ignore
+                  code 10 reject
+                  code 20 quarantine
+              }
           }
       
-          # Insert handling for special-purpose local domains here.
-          # e.g.
-          # destination lists.example.org {
-          #     deliver_to lmtp tcp://127.0.0.1:8024
-          # }
-      
           destination postmaster $(local_domains) {
               modify {
                   replace_rcpt static {
                      entry postmaster           postmaster@$(primary_domain)
                      entry leon@thein.ovh       leah@ctu.cx
                      entry leah@thein.ovh       leah@ctu.cx
-                     entry leah@antifa.jetzt    leah@ctu.cx
                   }
       
                   # Implement plus-address notation.
diff --git a/secrets/default.nix.age b/secrets/default.nix.age
@@ -1,47 +1,78 @@
 -----BEGIN AGE ENCRYPTED FILE-----
-YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFZFR6V04rSTJUMjI5VVU2
-VHpwV3pPSzNkTDBnZnI2ZCtQbkJWZE1DdUJzCjlIbjU3Q3F2L3BPa0VTcHJwSXFL
-djVGbXJKS3R3T1UrbW1MWkFKNUhXeWsKLS0tIEVTWXErRVNQT0UrOWUxZStqLzBn
-ZnUxSmZoSUVJTFJJQ1dhSGN4Sld6aEkKxjRFI78EI7wqnZmXpju30J1gkkhoT4xB
-MQFSu2SJ1w7e9jjIZnpGcEzqbgYAWXfl1nq2suqtGljP+qEpiCgyP3a5ruANIvZi
-GMRQvN3hBBh7LIP9qLd28Ab3uP/2ppJihqkYRmIm1WnBQ0xVysyCay/OMNDcIpht
-eIBBv+jNXovnGnxjRhTY/7YTD1f9POnmtV1SCk+31hsb6n6xyPjf39duaPcbvXSU
-fD5yHeRa06apsD4zaEvleXHE4Skv8NObLtSmcC3+p7xzxmHCmWv/OZjgfIIejzXC
-2DhDdvP5f4j+6Iuwd/qLemLPJDXEUSQJZOOwGQlq52Fv5+LeUApScbH3SymmgXWA
-rJ0Gn9PeNmXvJxkdfmgJSCA6/fDmVO/LmLswIGL4vtLD80QpjS9wJfpclsVjJMby
-h6vVYdyNUIiXCb3nISGYeb3bCdPsXtl06hydIcMYheOvbW6X/j8asDCg+jD55o8H
-6ShuEwtuqBNT6pvX5ZLfvrowvxkII6/t9O3zCn2hIDJkHENKcFG3H8N+IWy2DA9r
-x81d7TGzcWGaNQnLT/aH9+WwOiXZuJQ9fBpick0YoMOQOJhW4aAYtCSzPlBD8eEB
-tcKbDouc3HdzrOOWWjTkg0LXbEfZxuZPCppEPbmEpGPZzrSmPbnbEzOPkDZ6sIIb
-cOWEtBNEhz3MV86M8sjOqlEO9Iu7EIdpBUkwp/NDK9BhTS4dh88rudBmMkj47phV
-m5XoILlM8qCTTtSnRYS1kn9iMrJCQ8nlA0jKIQ6etTdsUNlZCqBAaSeWDwAxGYcr
-oJvYXA3oUqbK11Q4ivpieXLfli5jzop6jBPTQfQn6n5oSsv4qhjfFo7c1MAlqyiW
-/CJ2O08zFGIceShaqs/pygyf8G/goC/CspTlxKrUZMqy2jN8VeshRvzPc+eIGJCX
-zseXC0uw7wH3Rd++GvABX5hob6kzuB9TmJS+f+eg1hmN0+hvfd9vEi34o7HvnNYm
-qVjByKeq0r01dKHbQeW+Sq40JUjohH4duQ7xETr5C5d6BemWE20tEqVJGilgNUYk
-4B6oXNpxaz0KZsHe0CZnNUJ4sh+MKC+uBSA8bgEoXtyPLX0eZkNYmUgUM9UBEyJf
-tZ26bzwU8VnZqxMoguq/GGq9LX2r1Aw8QOSYJlMFJuwZAwYW9R1RZspp/MtjnOpy
-3xb+XXWRoQNDw5dKobh6l90kw+2LcPipQ8DrTkd1di0bgUA1KNvmhl5MpA741cGZ
-7msrbzhkN68bcKTiKYySCb71ahxHmKD8pOEXn7W285wIMJAwoQX03yYN98SZ8sEf
-QgBciM/ckCHKRNBlN/D/Xf8Ge8fS3B8NCj7qnQG6/+ed3SDb2lIjQQ6fHsu02IXr
-ReaqpKaYGzp3xkLeeLpw5nHaz2yKq0Uu1GWMiiWLqjjw0INYytypsgacx69H/R0P
-NC9kPaSalyD2mbWcIpiL2bv/QSVeJH+NLTk1wAj0J/LzoImLx4V15bXtdNVS8o1W
-Ptr3ULbKFntAdjoOg3ZYrVVBPGH1J+itLLqNtC+aOa5YBG/9Nu/rkUdfI/qlJ4US
-YhAKm0b9HvLDyT5xXTEjEbW2JUSLp/w37vkmeg/xgJRW5uyJ0ZIiPT4n4r6VPPxP
-gIISlDT0DlbzQvIXSRR2CUteBXjcfnmr1vBgqgORUX6hAZ8Fo3gH/qaU+WE/Ppf7
-tzrRv3L1xIBK8aX02kvn8gdEsWBVeB8gOCXcBoWbqB/UVX/czshG02yNGty5LXOZ
-qSk4GkntEEmS1dx5SFMN6RQTcZ4ikgCPvRiaNeMrdqt7hOGSjEUReyOwnhzNka8Z
-603qknQ0Ewi+vbfcJ1Kh51+9HuReAIFNUwsG4uXLFz5e68ABHaefN6upO/ltg0Ng
-YeeOSbh/tSfbWWhFBHzF7nOfRyssTmQD9WJMR/icDwfh80xOmHa9xja4h8pEUTaI
-AxYKzzgQfoc/ExicC8T3pH9Zyz1+jZj05Jsw0KygaAQsLSY8Bu10A55bf3nrUN6E
-6OZ0L7SHdEcd1w7JJpotuaqt4Ow/aC11RRnI/Q9TkB3EUWHQ6/QKdi+mLshpSlq/
-tCu8FWfs1c4ij9cMmKoE2h74alHK8LrU+qmAkTsUZz1HdpmpFLQbLMv6d2GZJ2k1
-hg6P35/a1t2hz1UlW9xGuIh4on1ZeGrgj2E2QwbZNsxOs9zO7uIwzn4GojTiFdAa
-qocmoXoMzOcUuGsLF8KR0ATnmemarHGZL8dfR77pGVKew/o5ibxUrDR91lRycqfZ
-3qPKoX+x9hgA1SKRKIDJjXPJ+S4tmqJzuFE+blhsoONKY+1TmapWhULcxHoVedt2
-oML+LD5N9Lg1LSst8eidvsih+nbfgtLZ6RTVda43ORc/l00YyyX264/klFAZUCLn
-oqLNVUcKNBNaKzrNDWAYLjeUof8KUT/v2Af/8FpDArJcqKeOIgS6311r35uQQ8va
-XZt5mdsWEvZS33EbU7gEWA8O62ahItpRugbsBep6uzXGx23QYfGm6DoUcyag8/bT
-gFii00RzS9H9APVF0C1XK+SGZJKv+nolnOynfKbGDpOcjLaKTr60SRzYVV8Lx6/A
-aEpC/P3hWfXwErxaYpWFT0AEYEOz5pkTrpuIh60AJ6QaCZBKWqGlWKhJD2PMHQ==
+YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNSTNDakJHUWxxVU5hY3Vw
+eUlQemZrOTZHT2Jva3dPL0ZZTWxJelBoNmdzClFvNDdqdjRLT09oRmhseWlnckxS
+SVJTZGJDWUozVjFPcnFpdHgrdlpCbk0KLS0tIHVzb21qeXE3TzZMWTFlVTAwbkM1
+YTYwYnpXY1pPVDdtZGk0bjg3WmkvTDQK6xuh5dKwQi1iSICbRunWARasV4+u7ky5
+V1+lJ+5NI+Q1/BLjtc3bRN3THSFCSVlRP1MWLw+nUY3D1jUd2PiYKKNF7He7JjyK
+6IPk8DT8jETWvDLnQSEfcq5i0wdM1hiZ1lA1tClL72pyo6sbdnHZRFFcHuruBomo
+qzQomXOb/Zatx7BilfzoxFaXULpBqHfYB6+Fmw4eLHFWO1U0PaFa/Yw0U7LGoOdQ
+vF4/3SbhfnlxCJylFwL1pWlPzf3zz+JR8Jr2W5knhsTx/CsENyGqUVL1LkMBjFKq
+AQY+2ONZY7f4TWgCoMBvBa28YMPATCHgLtgVOJMOThm4aTEtNR5LwKFKa4VATbla
+cowXfh0Tv2u+JgOP1rmE6GJdQ0Xu9QkP3dNhEZqgP7/ZlT78pt55+8ASiJLHO8DW
+c0ErL92j2REOSntMQ5eEAvK3fl9OHM+XQhNyh97pbbLeaqZ6FzIZJa4HHTlEK1hm
+yZlZQBcATbB78Db2xEi46iUH53/geFzcgtpuEnP9xTzdSjra4pO/20CHmPGnPVFC
+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
 -----END AGE ENCRYPTED FILE-----