aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/private/mail/milters.nix14
-rw-r--r--modules/private/mail/postfix.nix7
-rwxr-xr-xmodules/private/mail/verify_from.py60
-rw-r--r--overlays/python-packages/default.nix1
-rw-r--r--pkgs/python-packages/default.nix1
-rw-r--r--pkgs/python-packages/pymilter.nix11
6 files changed, 93 insertions, 1 deletions
diff --git a/modules/private/mail/milters.nix b/modules/private/mail/milters.nix
index 16c8a7a..5de03cf 100644
--- a/modules/private/mail/milters.nix
+++ b/modules/private/mail/milters.nix
@@ -129,5 +129,19 @@
129 config.secrets.fullPaths."opendkim/eldiron.private" 129 config.secrets.fullPaths."opendkim/eldiron.private"
130 ]; 130 ];
131 }; 131 };
132
133 systemd.services.milter_verify_from = {
134 description = "Verify from milter";
135 after = [ "network.target" ];
136 wantedBy = [ "multi-user.target" ];
137
138 serviceConfig = {
139 User = "postfix";
140 Group = "postfix";
141 ExecStart = let python = pkgs.python3.withPackages (p: [ p.pymilter ]);
142 in "${python}/bin/python ${./verify_from.py} -s /run/milter_verify_from/verify_from.sock";
143 RuntimeDirectory = "milter_verify_from";
144 };
145 };
132 }; 146 };
133} 147}
diff --git a/modules/private/mail/postfix.nix b/modules/private/mail/postfix.nix
index 40a9577..e0347ec 100644
--- a/modules/private/mail/postfix.nix
+++ b/modules/private/mail/postfix.nix
@@ -377,7 +377,12 @@
377 ]; 377 ];
378 smtpd_recipient_restrictions = "permit_sasl_authenticated,reject"; 378 smtpd_recipient_restrictions = "permit_sasl_authenticated,reject";
379 milter_macro_daemon_name = "ORIGINATING"; 379 milter_macro_daemon_name = "ORIGINATING";
380 smtpd_milters = "unix:${config.myServices.mail.milters.sockets.opendkim}"; 380 smtpd_milters = builtins.concatStringsSep "," [
381 # FIXME: put it back when opensmtpd is upgraded and able to
382 # rewrite the from header
383 #"unix:/run/milter_verify_from/verify_from.sock"
384 "unix:${config.myServices.mail.milters.sockets.opendkim}"
385 ];
381 }; 386 };
382 destination = ["localhost"]; 387 destination = ["localhost"];
383 # This needs to reverse DNS 388 # This needs to reverse DNS
diff --git a/modules/private/mail/verify_from.py b/modules/private/mail/verify_from.py
new file mode 100755
index 0000000..b75001e
--- /dev/null
+++ b/modules/private/mail/verify_from.py
@@ -0,0 +1,60 @@
1#!/usr/bin/env python3
2import Milter
3import argparse
4from email.header import decode_header
5from email.utils import parseaddr
6
7class CheckMilter(Milter.Base):
8 def __init__(self):
9 self.envelope_from = None
10 self.header_from = None
11
12 @Milter.noreply
13 def connect(self, IPname, family, hostaddr):
14 return Milter.CONTINUE
15
16 def hello(self, heloname):
17 return Milter.CONTINUE
18
19 def envfrom(self, mailfrom, *args):
20 self.envelope_from = parseaddr(mailfrom)[1]
21 return Milter.CONTINUE
22
23 @Milter.noreply
24 def envrcpt(self, to, *str):
25 return Milter.CONTINUE
26
27 @Milter.noreply
28 def header(self, name, hval):
29 if name.lower() == "from":
30 self.header_from = parseaddr(decode_header(hval)[-1][0])[1]
31 return Milter.CONTINUE
32
33 def eoh(self):
34 if self.header_from is not None and self.header_from != "" and self.header_from != self.envelope_from:
35 self.setreply("553", xcode="5.7.1", msg="<%s>: From header rejected: not matching envelope From %s"
36 % (self.header_from, self.envelope_from))
37 return Milter.REJECT
38
39 return Milter.CONTINUE
40
41 @Milter.noreply
42 def body(self, chunk):
43 return Milter.CONTINUE
44
45 def eom(self):
46 return Milter.ACCEPT
47
48 def close(self):
49 return Milter.CONTINUE
50
51 def abort(self):
52 return Milter.CONTINUE
53
54if __name__ == "__main__":
55 parser = argparse.ArgumentParser()
56 parser.add_argument("--socket", "-s", type=str, help="socket to listen to")
57 config = parser.parse_args()
58
59 Milter.factory = CheckMilter
60 Milter.runmilter("check_from", config.socket, timeout=300)
diff --git a/overlays/python-packages/default.nix b/overlays/python-packages/default.nix
index 8a9949e..0feff55 100644
--- a/overlays/python-packages/default.nix
+++ b/overlays/python-packages/default.nix
@@ -25,4 +25,5 @@ in
25 apprise = fromMyPythonPackages "apprise"; 25 apprise = fromMyPythonPackages "apprise";
26 buildbot = import ./buildbot.nix; 26 buildbot = import ./buildbot.nix;
27 wokkel = fromMyPythonPackages "wokkel"; 27 wokkel = fromMyPythonPackages "wokkel";
28 pymilter = fromMyPythonPackages "pymilter";
28} 29}
diff --git a/pkgs/python-packages/default.nix b/pkgs/python-packages/default.nix
index 747bbe6..2616d64 100644
--- a/pkgs/python-packages/default.nix
+++ b/pkgs/python-packages/default.nix
@@ -3,4 +3,5 @@
3 apprise = callPackage ./apprise { inherit mylibs; pythonPackages = python.pkgs; }; 3 apprise = callPackage ./apprise { inherit mylibs; pythonPackages = python.pkgs; };
4 buildbot-plugins = callPackage ./buildbot/plugins { inherit mylibs python; }; 4 buildbot-plugins = callPackage ./buildbot/plugins { inherit mylibs python; };
5 wokkel = callPackage ./wokkel.nix { pythonPackages = python.pkgs; }; 5 wokkel = callPackage ./wokkel.nix { pythonPackages = python.pkgs; };
6 pymilter = callPackage ./pymilter.nix { pythonPackages = python.pkgs; };
6} 7}
diff --git a/pkgs/python-packages/pymilter.nix b/pkgs/python-packages/pymilter.nix
new file mode 100644
index 0000000..736794e
--- /dev/null
+++ b/pkgs/python-packages/pymilter.nix
@@ -0,0 +1,11 @@
1{ pythonPackages, libmilter }: with pythonPackages;
2buildPythonPackage rec {
3 pname = "pymilter";
4 version = "1.0.4";
5 src = fetchPypi {
6 inherit pname version;
7 sha256 = "1bpcvq7d72q0zi7c8h5knhasywwz9gxc23n9fxmw874n5k8hsn7k";
8 };
9 doCheck = false;
10 buildInputs = [ libmilter ];
11}