-
Notifications
You must be signed in to change notification settings - Fork 0
/
qmail-arc.py
executable file
·126 lines (92 loc) · 3.79 KB
/
qmail-arc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env python3
"""Qmail mail validator
This is a script meant to be used in qmail before forwarding mail to e.g. Gmail. It will verify
the incoming mail against SPF, DKIM and more and add the appropriate ARC headers. This makes Gmail
(probably) accept mails for which there's a DMARC rule with "reject" set.
Inspiration taken from http://bazaar.launchpad.net/~dkimpy-hackers/dkimpy/trunk/view/head:/arcsign.py
"""
from __future__ import print_function
__author__ = "Markus Birth"
import os
import re
import socket
import sys
import authres
import authres.arc
import dkim
import spf
AUTHSERV_ID = socket.getfqdn() # domain or hostname of mail server
AUTHSERV_HOSTNAME = socket.getfqdn() # full hostname of mail server
DKIM_DOMAIN = b"birth-online.de"
DKIM_SELECTOR = b"mbirth"
# pylint: disable=C0103,C0301
if sys.version_info[0] >= 3:
# Make sys.stdin and stdout binary streams.
sys.stdin = sys.stdin.detach()
sys.stdout = sys.stdout.detach()
privkey = open('/home/mbirth/.dkim-privkey', 'rb').read()
message = sys.stdin.read()
linesep = dkim.util.get_linesep(message)
# Find this line:
# Received: from unknown (sv3-smtp2.lithium.com [208.74.204.9])
# by eukelade.uberspace.de with SMTP; 23 Jun 2017 18:43:18 -0000
up_srv_ip_match = re.search("Received: from (.*?) \(.*? \[([0-9a-f.:]+)\].*by ", message.decode("utf-8"), re.MULTILINE | re.DOTALL)
#sys.stdout.write(repr(up_srv_ip_match).encode("utf-8"))
if not up_srv_ip_match:
# Pass-thru message
sys.stdout.write(message)
sys.exit(0)
up_srv_helo = up_srv_ip_match.group(1).lower()
up_srv_ip = up_srv_ip_match.group(2)
sender_address = os.getenv('SENDER')
results_list = []
### REV IP LOOKUP
iprev_res = "fail"
iprev_hn = "Lookup error"
try:
up_srv_hostn = socket.gethostbyaddr(up_srv_ip)
if up_srv_helo == up_srv_hostn[0]:
iprev_res = "pass"
iprev_hn = up_srv_hostn[0]
else:
iprev_res = "fail"
except:
iprev_res = "temperror"
iprev_result = authres.IPRevAuthenticationResult(result=iprev_res, policy_iprev=up_srv_ip, policy_iprev_comment=iprev_hn)
results_list += [iprev_result]
### SPF CHECK
spf_result = spf.check2(i=up_srv_ip, s=sender_address, h=up_srv_helo)
spf_res = authres.SPFAuthenticationResult(result=spf_result[0], smtp_mailfrom=sender_address, smtp_helo=up_srv_helo, reason=spf_result[1])
results_list += [spf_res]
# Write Received-SPF header (must be added ABOVE Received: lines for this server)
sys.stdout.write('Received-SPF: {0} ({1}) receiver={2}; client-ip={3}; helo={4}; envelope-from={5};'.format(spf_result[0], spf_result[1], AUTHSERV_HOSTNAME, up_srv_ip, up_srv_helo, sender_address).encode("utf-8") + linesep)
### ARC SIGNATURE
#import logging
#logging.basicConfig(level=10)
try:
cv = dkim.CV_None.decode("ascii")
if re.search(b'arc-seal', message, re.IGNORECASE):
arc_vrfy = dkim.arc_verify(message)
cv = arc_vrfy[0].decode("ascii")
arc_res = authres.arc.ARCAuthenticationResult(result=cv)
results_list += [arc_res]
except Exception as e:
sys.stdout.write("X-MTA-Error: qmail-arc failed ARC verifying ({}).".format(e).encode("utf-8") + linesep)
#raise
pass
try:
### PREP AUTH RESULT
auth_res = authres.AuthenticationResultsHeader(authserv_id=AUTHSERV_ID, results=results_list)
auth_res_str = str(auth_res).encode("utf-8") + linesep
message = auth_res_str + message
# parameters: message, selector, domain, privkey, srv_id, signature_algorithm
sig = dkim.arc_sign(message, DKIM_SELECTOR, DKIM_DOMAIN, privkey, b"eukelade.uberspace.de")
#sys.stdout.write(repr(sig).encode("utf-8"))
for line in sig:
sys.stdout.write(line)
except Exception as e:
sys.stdout.write("X-MTA-Error: qmail-arc failed ARC signing ({}).".format(e).encode("utf-8") + linesep)
#raise
pass
#sys.exit(0)
sys.stdout.write(message)