Fehlermeldung
dkim=fail (body hash did not verify)
Auch ausgegeben als
- dkim=neutral (body hash did not verify)
mailauth schreibt im strikten Modus `dkim=fail (body hash did not verify)` und im standardmäßigen toleranten Modus `dkim=neutral (body hash did not verify)` (beides reproduziert mit 8.0.1). OpenDKIM meldet dieselbe Situation als `dkim=fail reason="signature verification failed"` (reproduziert mit 2.11.0).
DKIM verifiers (Gmail, mailauth, Rspamd…) — Authentication-Results after the body changed in transit
Was der Fehler bedeutet
Das Tag `bh=` der DKIM-Signatur enthält einen Hash des Nachrichtentexts, so wie der Absender ihn signiert hat. Der Empfänger hat den empfangenen Text (nach der Kanonisierung) gehasht und einen anderen Wert erhalten – der Text hat sich also unterwegs verändert. Die Signatur über die Header war gar nicht das Problem: Nach RFC 6376 ist ein abweichender Body-Hash ein dauerhafter Fehler. Typische Verursacher sind Footer von Mailinglisten, Disclaimer und Security-Gateways, die Links umschreiben.
Warum der Fehler auftritt
Ein Footer oder Disclaimer wurde angehängt
häufigMailinglisten (Footer zum Abbestellen), Firmen-Disclaimer, die ein ausgehendes Gateway hinzufügt, oder „Sent from…“-Zeilen, die Relays einfügen, verändern den kanonisierten Nachrichtentext.
Ein Security-Gateway hat den Nachrichtentext umgeschrieben
häufigUmschreiben von Links (Safe Links, URL Defense), Entfernen von Anhängen oder Einfügen von Bannern durch eingehende oder ausgehende Filter.
Die MIME-Transferkodierung hat sich geändert
gelegentlichEin Relay ohne 8BITMIME wandelt 8-Bit-Inhalte in Quoted-Printable oder base64 um. Der dekodierte Text ist identisch, die signierten Bytes sind es nicht.
Der Signierer hat andere Zeilenenden gehasht
gelegentlichSigniercode, der LF-Zeilenenden hasht, während die Nachricht mit CRLF verschickt wird (oder bei der später Whitespace am Zeilenende entfernt wird), erzeugt einen Body-Hash, der bei der Kanonisierung `simple` nie übereinstimmt.
So behebst du den Fehler
- 1.
bh= selbst neu berechnen
Vergleichst du den neu berechneten Body-Hash der gesendeten und der empfangenen Kopie, erkennst du, ob der Signierer oder ein Relay schuld ist.
bash # Recompute bh= for relaxed body canonicalization and compare with the header's bh= value python3 - message.eml <<'EOF' import base64, hashlib, re, sys raw = open(sys.argv[1], "rb").read().replace(b"\r\n", b"\n") body = raw.split(b"\n\n", 1)[1] lines = [re.sub(rb"[ \t]+", b" ", l).rstrip(b" \t") for l in body.split(b"\n")] canon = b"\r\n".join(lines).rstrip(b"\r\n") + b"\r\n" print("computed bh=", base64.b64encode(hashlib.sha256(canon).digest()).decode()) EOF grep -o "bh=[^;]*" message.eml - 2.
Nach jeder Änderung signieren
Mach den DKIM-Signierer zum letzten Schritt auf deinem ausgehenden Weg; bei Zwischenstationen, auf die du keinen Einfluss hast, setze nach Möglichkeit auf ARC und DMARC-Alignment über SPF.
text # Postfix: run content filters (disclaimers, antivirus) BEFORE the DKIM signing milter smtpd_milters = inet:127.0.0.1:10025, inet:127.0.0.1:8891 # ^ disclaimer milter ^ OpenDKIM (signs last)
Verwandte Fehler
dkim=fail reason="signature verification failed"OpenDKIM (Authentication-Results header added by the opendkim milter); mailauth reports the same as "bad signature"dkim=permerrorOpenDKIM (Authentication-Results); mailauth reports syntax errors as dkim=neutraldkim=fail reason="key not found in DNS"OpenDKIM (Authentication-Results); mailauth reports it as dkim=neutral (no key)