Two messages can look identical in a mail client and still produce different DKIM body hashes. DKIM verifies the transmitted representation after its specified canonicalization, not the reader's decoded view. MIME rebuilding, content-transfer conversion and boundary changes therefore belong early in the investigation when a message fails only after a processing service.
Separate appearance from representation
A MIME message can contain plain text, HTML, attachments and nested multipart structures. RFC 2046 §5.1.1 places MIME part headers and boundary delimiter lines inside the multipart body. Re-encoding a text part from quoted-printable to base64 can preserve what a user reads while changing the bytes presented to DKIM. Rewrapping encoded lines can also change those bytes. Relaxed canonicalization is a defined whitespace transformation, not a MIME decoder or an equivalence test for rendered content.
RFC 6376 §5.3 advises conversion to a suitable MIME transfer encoding before signing to reduce transport conversions. It specifically requires local representations that will change before transmission to be normalized before signing. The principle is operationally simple: sign the form the receiver is expected to see.
Locate the serialization change
Obtain raw messages at signer output, suspected gateway output and final receiver. Store originals without opening and saving them through an editor that normalizes line endings. Note the collection method because an export tool can itself change the representation.
Compare the Content-Type and Content-Transfer-Encoding fields at the outer message and each relevant MIME part. Check boundary strings, attachment encoding, folded lines and character-set conversion. Determine whether a changed outer header was included in h and whether changed part headers occurred inside the signed body. Treat the two locations separately: an outer header may cause signature verification failure, while a MIME part header normally participates in the body hash.
Work through an encoding example
Illustrative test specification: a text part containing a non-ASCII character is prepared using quoted-printable before the application signs the message. A downstream service decodes that part and serializes it as base64. The displayed sentence remains the same, but the canonicalized body can differ and the original signature can fail. Run this only with controlled content and inspect actual byte differences rather than assuming every service performs this conversion.
Create a small test set containing ASCII-only plain text, non-ASCII text, multipart HTML and a small attachment. Send each through a direct control path and the production-equivalent processing path. If only the latter changes representation, the boundary comparison identifies the component to investigate. If both fail, examine the signer's own serialization and normalization first.
Repair the boundary
Prefer final MIME construction and transfer-encoding selection before signing. Where a security service must rewrite content, arrange an authorized signing step after its final serialization. Confirm its custom-domain support and ownership model; a signature under an unrelated service domain may pass DKIM without aligning for DMARC under RFC 9989 §4.4.1.
Do not repair a sample in place and present it as proof that production is fixed. A modified sample only tests a hypothesis. Change the responsible configuration, send new controlled messages and capture their original receiver results. Avoid broad bypasses of content inspection solely to preserve a signature without reviewing the security consequence.
Preserve a useful incident record
Record the first boundary where serialized content diverges, the MIME field or part affected, the signer and selector, and results for each test variant. Keep the test messages free of customer data. Re-run the suite after gateway upgrades and attachment-processing changes. The completed fix explains why the old representation failed and demonstrates that newly emitted mail survives the full supported route.
Compare a concrete encoded representation
For the UTF-8 bytes C3 A9 representing é, a quoted-printable representation is =C3=A9; a base64 representation is w6k=. With appropriate MIME headers both decode to the same character, but the encoded strings differ. RFC 2045 §6.7 and RFC 2045 §6.8 define the encodings; RFC 6376 §3.7 requires hashing after transfer encoding and before decoding during verification. This isolated representation example is not a complete MIME message or an executed signature test. If a body-length limit is used, determine whether the changed bytes are within coverage rather than assuming every part is protected.