zend-maildkimcanonicalizationrfc2822

Does DKIM header canonicalization insert a space after each comma in the To: header?


Using Zend Framework 1.12, PHP 5.3.1. Specifying multiple mail recipients to Zend_Mail and using Smtp transport, the "To:" header contains a list of recipients separated by commas. E.g.

To: a@example.com,b@example.com

This appears to be correct syntax according to RFC 2822. I've added DKIM signing (using https://github.com/louisameline/php-mail-signature), which works fine, producing passing signatures accepted by gmail and other verifiers with a single To: recipients. But for multiple recipents, the signature fails.

Sending signed mail to check-auth@verifier.port25.com returns an email to the Return-path containing, among results of various checks, the canonicalized version of headers and body that it computed. I see that it has added a space after each comma when canonicalizing the To: header (I'm specifying relaxed canonicalization for both headers and body). And indeed I hacked my signature generation to add that space when canonicalizing the To: header, and that solved the problem: the port25.com verifier, gmail and others now pass the signature.

But in any description I've seen of DKIM relaxed canonicalization, including a pretty careful reading of section 3.4 of RFC 6376, as well as the code in the signature class I downloaded from github referenced above, there is nothing that adds whitespace where none was present in the original; the specified canonicalizations are all about changing existing whitespace.

So it seems to me that the canonicalization being done by the port25 verifier is at odds with RFC 6376 - except that other DKIM verifiers like gmail, autorespond+dkim-relaxed@dk.elandsys.com, and http://www.appmaildev.com/en/dkim/ all agree on the final result (they don't show the canonicalizations that they performed like port25 does, but if I don't canonicalize with the space after the commas, they reject the signature).

Does anyone here have any insight into this? Since practice in the field appears to differ consistently with the RFC dated 2011, shouldn't the RFC be updated? And of course there is also the question of whether all commas in the To: header value should be canonicalized to comma-space before WSP is replaced by a single space, and whether any other headers are affected.

Summary of final resolution

Evan's answer was exactly right regarding the OP: my MTA was adding the space, not the validator's canonicalization. I just had not looked carefully enough at the To: header that actually had been received.

But knowing that doesn't yield a completely trivial solution to the problem of generating correct signatures. The "root" problem is that Zend_Mail generates the address-list values in headers using a comma without a following space as a separator - although it's perfectly valid syntax, it's also perfectly valid for an MTA to introduce a space after each one. And the relaxed canonicalization specified by RFC 6376 and widely implemented does not accommodate such an MTA rewrite. Changing the Zend_Mail code to use comma-space as the separator would be trivial, except that it is done in the middle of a fairly long and complex method that would involve major copy-paste to override, which felt wrong. So what I ended up doing was to write a pre-filter that puts the space in the headers before signing them. Although it's not 100% perfect wrt all possible syntax variations including comments, applying the following preg_replace to the values of To:, Cc:, and Reply-To: headers does the trick for me:

preg_replace('/(@[a-z0-9]+(\.[a-z0-9-]+)*>?,)([^ ])/i', '\1 \3', $header_value)

Solution

  • What is your MTA, under which platform ?

    I believe it may be the one modifying your headers, not the recipient applications.

    Note : I am the maintainer of the library you mentioned.