1
0
mirror of https://github.com/mail-in-a-box/mailinabox.git synced 2026-03-14 17:27:23 +01:00

First steps in migrating to dkimpy-milter

This commit is contained in:
github@kiekerjan.isdronken.nl
2021-12-11 00:54:56 +01:00
parent 21fd62ef4f
commit ded1b55ebd
7 changed files with 81 additions and 58 deletions

View File

@@ -105,21 +105,22 @@ def do_dns_update(env, force=False):
if len(updated_domains) > 0:
shell('check_call', ["/usr/sbin/service", "nsd", "restart"])
# Write the OpenDKIM configuration tables for all of the mail domains.
# Write the DKIM configuration tables for all of the mail domains.
from mailconfig import get_mail_domains
if write_opendkim_tables(get_mail_domains(env), env):
# Settings changed. Kick opendkim.
shell('check_call', ["/usr/sbin/service", "opendkim", "restart"])
if write_dkim_tables(get_mail_domains(env), env):
# Settings changed. Kick dkimpy.
shell('check_call', ["/usr/sbin/service", "dkimpy-milter", "restart"])
if len(updated_domains) == 0:
# If this is the only thing that changed?
updated_domains.append("OpenDKIM configuration")
updated_domains.append("DKIM configuration")
# Clear bind9's DNS cache so our own DNS resolver is up to date.
# (ignore errors with trap=True)
shell('check_call', ["/usr/sbin/rndc", "flush"], trap=True)
if len(updated_domains) == 0:
# if nothing was updated (except maybe OpenDKIM's files), don't show any output
# if nothing was updated (except maybe DKIM's files), don't show any output
return ""
else:
return "updated DNS: " + ",".join(updated_domains) + "\n"
@@ -303,10 +304,18 @@ def build_zone(domain, domain_properties, additional_records, env, is_zone=True)
if not has_rec(None, "TXT", prefix="v=spf1 "):
records.append((None, "TXT", 'v=spf1 mx -all', "Recommended. Specifies that only the box is permitted to send @%s mail." % domain))
# Append the DKIM TXT record to the zone as generated by OpenDKIM.
# Append the DKIM TXT record to the zone as generated by DKIMpy.
# Skip if the user has set a DKIM record already.
opendkim_record_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/mail.txt')
with open(opendkim_record_file) as orf:
dkim_record_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim2/box-rsa.dns')
with open(dkim_record_file) as orf:
m = re.match(r'(\S+)\s+IN\s+TXT\s+\( ((?:"[^"]+"\s+)+)\)', orf.read(), re.S)
val = "".join(re.findall(r'"([^"]+)"', m.group(2)))
if not has_rec(m.group(1), "TXT", prefix="v=DKIM1; "):
records.append((m.group(1), "TXT", val, "Recommended. Provides a way for recipients to verify that this machine sent @%s mail." % domain))
# Also add a ed25519 DKIM record
dkim_record_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim2/box-ed25519.dns')
with open(dkim_record_file) as orf:
m = re.match(r'(\S+)\s+IN\s+TXT\s+\( ((?:"[^"]+"\s+)+)\)', orf.read(), re.S)
val = "".join(re.findall(r'"([^"]+)"', m.group(2)))
if not has_rec(m.group(1), "TXT", prefix="v=DKIM1; "):
@@ -817,14 +826,15 @@ def sign_zone(domain, zonefile, env):
########################################################################
def write_opendkim_tables(domains, env):
# Append a record to OpenDKIM's KeyTable and SigningTable for each domain
def write_dkim_tables(domains, env):
# Append a record to DKIMpy's KeyTable and SigningTable for each domain
# that we send mail from (zones and all subdomains).
opendkim_key_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/mail.private')
dkim_rsa_key_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim2/box-rsa.key')
dkim_ed_key_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim2/box-ed25519.key')
if not os.path.exists(opendkim_key_file):
# Looks like OpenDKIM is not installed.
if not os.path.exists(dkim_rsa_key_file) || not os.path.exists(dkim_ed_key_file):
# Looks like DKIMpy is not installed.
return False
config = {
@@ -846,7 +856,12 @@ def write_opendkim_tables(domains, env):
# signing domain must match the sender's From: domain.
"KeyTable":
"".join(
"{domain} {domain}:mail:{key_file}\n".format(domain=domain, key_file=opendkim_key_file)
"{domain} {domain}:box-rsa:{key_file}\n".format(domain=domain, key_file=dkim_rsa_key_file)
for domain in domains
),
"KeyTableEd25519":
"".join(
"{domain} {domain}:box-ed25519:{key_file}\n".format(domain=domain, key_file=dkim_ed_key_file)
for domain in domains
),
}
@@ -854,18 +869,18 @@ def write_opendkim_tables(domains, env):
did_update = False
for filename, content in config.items():
# Don't write the file if it doesn't need an update.
if os.path.exists("/etc/opendkim/" + filename):
with open("/etc/opendkim/" + filename) as f:
if os.path.exists("/etc/dkim/" + filename):
with open("/etc/dkim/" + filename) as f:
if f.read() == content:
continue
# The contents needs to change.
with open("/etc/opendkim/" + filename, "w") as f:
with open("/etc/dkim/" + filename, "w") as f:
f.write(content)
did_update = True
# Return whether the files changed. If they didn't change, there's
# no need to kick the opendkim process.
# no need to kick the dkimpy process.
return did_update
########################################################################

View File

@@ -376,7 +376,7 @@ def scan_mail_log_line(line, collector):
if SCAN_BLOCKED:
scan_postfix_smtpd_line(date, log, collector)
elif service in ("postfix/qmgr", "postfix/pickup", "postfix/cleanup", "postfix/scache",
"spampd", "postfix/anvil", "postfix/master", "opendkim", "postfix/lmtp",
"spampd", "postfix/anvil", "postfix/master", "dkimpy", "postfix/lmtp",
"postfix/tlsmgr", "anvil"):
# nothing to look at
return True

View File

@@ -28,7 +28,7 @@ def get_services():
{ "name": "Dovecot LMTP LDA", "port": 10026, "public": False, },
{ "name": "Postgrey", "port": 10023, "public": False, },
{ "name": "Spamassassin", "port": 10025, "public": False, },
{ "name": "OpenDKIM", "port": 8891, "public": False, },
{ "name": "DKIMpy", "port": 8892, "public": False, },
{ "name": "OpenDMARC", "port": 8893, "public": False, },
{ "name": "Mail-in-a-Box Management Daemon", "port": 10222, "public": False, },
{ "name": "SSH Login (ssh)", "port": get_ssh_port(), "public": True, },