Skip to content
ecdsa.com
OpenDKIM (Authentication-Results header added by the opendkim milter); mailauth reports the same as "bad signature"DKIM

Error message

dkim=fail reason="signature verification failed"

Also printed as

  • dkim=fail (bad signature)

OpenDKIM writes `dkim=fail reason="signature verification failed"` for both header and body changes (reproduced with OpenDKIM 2.11.0). mailauth distinguishes them: "bad signature" for headers, "body hash did not verify" for the body.

What it means

The receiving server found the DKIM key and computed the signature over the message as it arrived, and it did not match: the signed headers (or, for OpenDKIM, also the body) changed after the sender signed the message, or the published key does not belong to the signing key. DKIM signs exact bytes after canonicalization, so any rewrite by a relay — a subject tag, a footer, a re-encoded MIME part — breaks it. For DMARC this counts as a failed DKIM check.

Why it happens

How to fix it

  1. 1.

    Compare the signed headers with the received ones

    The `h=` tag lists what was signed. Compare those headers in the received copy with a copy taken at the sender (Sent folder).

    bash
    # Which headers did the signature cover, and what do they look like now?
    grep -i "^DKIM-Signature" -A4 received.eml | grep -o "h=[^;]*"
    grep -iE "^(From|To|Subject|Date|Message-ID|Content-Type):" received.eml
  2. 2.

    For lists and forwarders: ARC and re-signing

    Intermediaries that must modify messages should add ARC headers and sign with their own domain, so receivers can still evaluate the original authentication.

    text
    # Mailing list / forwarder: add ARC and re-sign with the list's own domain (Mailman 3 example)
    [ARC]
    enabled: yes
    authserv_id: lists.example.org
    domain: lists.example.org
    selector: arc2026
    privkey: /etc/mailman3/arc.private
  3. 3.

    Verify the DNS key against the private key

    `opendkim-testkey` confirms that the published record for the selector matches the key the signer uses.

    bash
    opendkim-testkey -d example.com -s sel -k /etc/opendkim/keys/sel.private -vvv   # DNS record matches the private key?

Related errors

Browse the full signature error database