Initial commit

This commit is contained in:
Markus Birth 2017-06-29 00:23:51 +02:00
commit 2c5e0a55a1
2 changed files with 99 additions and 0 deletions

93
qmail-arc.py Executable file
View File

@ -0,0 +1,93 @@
#!/usr/bin/env python2
"""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 dkim
import spf
AUTHSERV_ID = "uberspace.de" # domain or hostname of mail server
DKIM_DOMAIN = "birth-online.de"
DKIM_SELECTOR = "mbirth"
# pylint: disable=C0103
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('.dkim-privkey', 'rb').read()
message = sys.stdin.read()
up_srv_ip_match = re.search(r"Received: from .* \(HELO (.*)\) \(([0-9.]+)\).*by ", message, re.MULTILINE | re.DOTALL)
up_srv_helo = up_srv_ip_match.group(1).lower()
up_srv_ip = up_srv_ip_match.group(2)
sender_address = os.getenv('SENDER')
### 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)
### SPF CHECK
# Find this line:
# Received: from unknown (HELO sv3-smtp2.lithium.com) (208.74.204.9)
# by serpens.uberspace.de with SMTP; 23 Jun 2017 18:43:18 -0000
spf_result = spf.check2(i=up_srv_ip, s=sender_address, h=up_srv_helo)
# TODO: Received-SPF
### PREP AUTH RESULT
spf_res = authres.SPFAuthenticationResult(result=spf_result[0], smtp_mailfrom=sender_address, smtp_helo=up_srv_helo, reason=spf_result[1])
auth_res = authres.AuthenticationResultsHeader(authserv_id=AUTHSERV_ID, results=[spf_res, iprev_result])
sys.stdout.write(str(auth_res))
### ARC SIGNATURE
cv = dkim.CV_None
if re.search('arc-seal', message, re.IGNORECASE):
cv = dkim.CV_Pass
# parameters: message, selector, domain, privkey, auth_results, chain_validation_status
sig = dkim.arc_sign(message, DKIM_SELECTOR, DKIM_DOMAIN, privkey, str(auth_res)[24:], cv)
for line in sig:
sys.stdout.write(line)
sys.exit(0)
sys.stdout.write(message)

6
requirements.txt Normal file
View File

@ -0,0 +1,6 @@
dkimpy
authres
pyspf
PyDNS
ipaddr
# UNINSTALL: ipaddress