A client found a single recipient domain where every Marketo email went to Spam due to failing DKIM validation. (A bad DKIM signature should really result in the message being dropped completely, so sending it to Spam was dangerously generous!)
We knew the DKIM DNS record (m1._domainkey.example.com
) for Marketo was correct, and of course were reassured by only one company reporting problems. But still, you have to track things down.
What DKIM signs
DKIM signs the important parts of outbound SMTP messages: the SMTP body and s set of common SMTP headers.
If a DKIM signature is valid, the recipient knows those parts of the message were generated on a server controlled by the signer, which increases trust.
(It also works both ways: the signer can’t claim they didn’t generate the message. This is known as “non-repudiation” and is important in regulated industries.)
A sample DKIM-Signature
header looks like this:
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1754422263;
s=m1; d=example.com; i=@example.com;
h=List-Unsubscribe:List-Unsubscribe-Post:Content-Type:MIME-Version:Subject:To:From:Date;
bh=+Sv3HC8ADc5Pw461LNuM4JotacUIplmGEq0oW2dh958=;
b=djmGGvM8Pyh+Wb8pjFRDu1laQpirD7eKY+3QamZTBoRpt0ugu3XlqV82rjVnNxG1
eVE98WsxcKp7mrS85tt1/AhWjyidytICcu9ijb5NGTIEyeXO92heaIczEN0c1wI8AeU
839pMpPiCW6LOvJCTTkeLRNIkSEP3RnV/G1+Jblw=
The h=
parameter lists the message headers covered by the signature: Subject
, To
, From
, Date
and a few others. These headers cannot be changed without invalidating the signature. Makes sense, right? If a hacker could change the Subject
and From
and still have a valid signature, that would undermine protection against impersonation + repudiation. (The message body is always signed and can’t be altered without invalidating the sig, but the body isn’t the only important part.)
Any header not in that list can be safely changed in transit: for example, the standard Message-ID
and nonstandard X-
headers like X-MSFBL
.[1] Setting a new Message-ID
can cause other confusion[2] of course, but it won’t make the message bad from a DKIM perspective.
Sometimes the clues are in [ALL CAPS]
It turned out the company had a bad combo of configs.
They had a mail scanner prepending[MARKETING]
to the Subject
of Marketo emails after accepting them — something you’ve probably seen before. But when the Subject
line is altered, that by definition breaks the DKIM signature if it includes (and it almost always does) the Subject
.
What a server should do, in this order, is:
- validate any DKIM signature(s) against the original content
- assuming signatures were valid, add another header like
X-DKIM-Originally-Valid: example.com, mktomail.com
- remove all
DKIM-Signature
headers; alternately, leave the originalDKIM-Signature
headers behind, but only if the message isn’t processed by any other servers that validate DKIM - change the
Subject
line or anything else (sometimes those servers add aWARNING
to the body too) - optionally, re-sign the message using the new body + header content; in this case you’ll be signing it on behalf of your domain, not the original sender domain, but the sig can be used by other internal systems
What this company was doing instead was changing the Subject
line, leaving the DKIM-Signature
headers as-is, then forwarding to an SMTP server elsewhere in their infrastructure. That SMTP server was validating DKIM as if the messages were from the outside world. Naturally, all the altered messages failed DKIM!
The solution was to bypass DKIM validation on that next-hop server, since that check isn’t appropriate if you ever alter content after delivery.
Notes
[1] In this example, copied from a real Marketo email, an intermediate server could also tweak Reply-To
. Make of that what you will!
[2] The Message-ID
header is key to accurate threading in email clients. When you reply to a message, the original Message-ID
is automatically copied to the In-Reply-To
of your reply. So if new Message-ID
s get assigned they won’t be grouped into the same conversation.