[Mimedefang] Mimedefang breaks DKIM signing of single-part, plain text emails

Peter Nagel pbnagel at rmi.net
Thu Jan 15 12:41:14 EST 2015

I am using Mimedefang (version 2.75) to sign mail with DKIM, and I
discovered that my signatures fail to verify when I send mail from my iPhone
through the server on which Mimedefang is installed. I'm a real novice at
perl, but I may have found two reasons why DKIM fails under these
circumstances and may have come up with a workable solution. What I don't
know is whether there might be a better way to fix things than what I've
come up with so far.

Apple apparently uses an unconventional mime-version header, "MIME-Version:
1.0 (1.0)," instead of just "MIME-Version: 10.0," and it is that
non-standard header that gets passed to filter_end, where my DKIM signing
occurs. (I am signing $entity->stringify(), by the way, not INPUTMSG, if
that makes any difference.) However, after filter_end returns, mimedefang.pl
(at line 6154) sends a command back to the milter (write_result_line("M",
$ct)) to modify the content-type header, and it looks like one unexpected
result of that is to set the mime-version header to the standard
"MIME-Version 1.0," which, in the case of mail from my iPhone, is not the
same as what DKIM signed.

To test this, I tried commenting out the code at line 6154, and mimedefang's
unexpected behavior went away; with that line commented out, the
mime-version header when mimedefang is finished with the email is the same
as the email's original mime-version header (which is what DKIM signs in
filter_end). I am not entirely sure what Mimedefang is doing here with the
mime-version, but I ultimately solved the problem by calling
$entity->head->replace() to force the mime-version header always to be
"MIME-Version: 1.0" before it even gets to the DKIM signer, and all is well.

Next, I was having a more general problem sending mail that initially
consists of a single-part, text/plain entity. At lines 6000-6003, before
calling filter_end, mimedefang.pl forces all entities to adopt a multipart
mime type, yet at lines 6128-6133, after calling filter_end, it collapses
entities that declare a multipart mime type, but that actually have only one
part, back into single-part entities. This does nothing if the original
email had a multipart mime type to begin with, but it does create a problem
with emails that were initially single-part, because what DKIM signs in
filter_end (multipart/xxx) isn't the same thing as that which Mimedefang
finally converts them back into (text/plain).

To fix this, I have commented out lines 6000-6003 and 6128-6133 in
mimedefang.pl, and my DKIM signatures for single-part, text only emails now
verify correctly, but I am afraid that very well might break something else.

There is an old thread on this list that explains that the reason why
Mimedefang converts entities from single- to multipart and then back again
is so that calls to add_part will work correctly. If that's the case,
wouldn't it be better to do that conversion only if add_part is actually
called, rather than to all entities, where it may or may not be needed?
Finally, there is a comment in the mimedefang.pl code (line 6128) proposing
to make the post-filter_end collapsing of multipart entities back to
single-part entities optional. That seems like a great idea, but I also
wonder if the pre-filter_end conversion of single-part to multipart entities
ought to be optional as well.

More information about the MIMEDefang mailing list