You can't DKIM sign a cabbage
- steve
- June 18, 2025

The DKIM specification and implementations of DKIM signing and validation code make some unstated assumptions about the environment they’re running in.
The biggest assumption is that they’re being used to sign an email. You can’t DKIM sign a Word doc. You can’t DKIM sign a walrus. And you can’t DKIM sign a cabbage.
But there are things being sent over SMTP that aren’t actually email. They look mostly like an email, but they violate the specifications of email in relatively minor ways. Perhaps it has a line in the body that’s more than 998 characters long. Or maybe it’s missing a Date: header, or it has non-ascii characters in the payload.
Those slight deviations from the standards may not stop the mail from being delivered, depending on how picky the mailservers between you and the recipient are, but they may trigger undefined - or, at least, unexpected - behaviour in DKIM validators.
Hashes
DKIM works by calculating a cryptographic hash - a “fingerprint” - when the mail is signed, calculating a hash in the same way when it’s received. If the hashes are the same then the mail hasn’t been modified (and you can use cryptographic magic to confirm that the mail was signed by the domain in “d=” bit of the DKIM-Signature: header).
If you change even a single character that will change the hash completely. And SMTP doesn’t promise not to change your mail during delivery. DKIM tries to be a little bit robust by offering “canonicalization” to remove minor changes, like header wrapping or whitespace, but there’s not much it can do.
If the DKIM signer and verifier make different assumptions about the message they’re creating a hash for - such as, say, that a header has the same number of characters as it has bytes, or that it has no more than one References: header, or that it’s all ASCII characters (so converting it between an array of bytes and a “string” and back won’t change anything) - then they’ll get different hashes. And then the DKIM validation will fail. Or they might make the same assumptions and get the same hash and DKIM will pass. It’s not consistent - different DKIM validators, or different release versions, or different configurations might behave differently for invalid input.
There were discussions during development of the DKIM specification with questions like “What if the message has [some unusual thing]” and a common answer was that such a message wasn’t an RFC compliant email, so handling that unusual feature was out of scope for DKIM. (Often with an implicit subtext that the message should be rejected anyway, but it’s not DKIM’s problem to handle).
Malicious messages
Invalid messages can be used by bad actors to avoid security systems, often by taking advantage of different interpretations of RFC violations by security filters and the mail client that displays the mail to the user. With multiple Subject: or From: headers you can display one value to the security filter and a different one to the user. Or by putting invalid bytes in the body of the message you can make a security filter stop scanning at that point, but the phishing message after the invalid bytes will still be shown to the user.
One way of dealing with this would be to just reject any invalid message at the border. “550 This isn’t an email, I’m not going to deliver it”.
There’s a lot of slightly malformed mail out there, though. Much less than there was before folks started fixing things up to avoid issues with DKIM, but still some. And users get upset if their well-intentioned - if slightly technically invalid - mail is rejected. So another option is for the security filter to clean the message up - convert non-ASCII characters to properly MIME-escaped symbols, remove invalid characters, wrap lines that are too long. By doing this the security filter can protect everything downstream of it - exchange servers, outlook clients, etc. - from all these security risks but still deliver the mail.
All those changes may break the DKIM hash. And it’s not uncommon for DKIM to be checked before the security filter (and to pass) but then to be checked again after the cleanup and then fail.
What this looks like
These sorts of DKIM failure may not be consistent. You may see them at one mailbox provider, but not another. They’re triggered by the content of the email, so one campaign may see problems while another may not. And customized content - potentially even the name or email address of the recipient - might trigger it for one recipient, while others in the same campaign deliver just fine.
If you’re seeing inconsistent DKIM failures check that you’re sending valid email. Particularly if you see issues at Microsoft or at on-premises enterprise providers, who tend to have more complex and sensitive inbound mail pipelines that may trigger the issue.
The best way to avoid invalid email structure is to keep things relatively simple, and to use supported, production tested software to generate and send your mail. We do check for some of the issues in aboutmy.email though, if you want to do a quick check of your production mail.