Exim's DKIM signatures do not verify on Microsoft servers (outlook, hotmail) *only*
<p><strong>Gmail as well as a local ISP passes DKIM for Exim emails</strong>, but Microsoft does not, with the fail noted in the header:</p>

<blockquote>
  <p>Authentication-Results: spf=pass (sender IP is [correct IP]) 
  smtp.mailfrom=[correct domain].co.uk; outlook.com; <strong>dkim=fail (signature did
  not  verify)</strong> header.d=[correct domain];outlook.com;
  dmarc=bestguesspass  action=none header.from=[correct domain];</p>
</blockquote>

<p>What I have tried:</p>

<p>I sent an email to outlook from the same domain through Google Apps (G Suite) email (using a different DKIM selector, i.e. another public key in another DNS TXT record) to compare the message sources - Google's message passed DKIM.</p>

<p>I noticed two things:</p>

<ol>
<li><p>Google included far fewer headers in the "h" tag , so I reconfigured Exim to also use precisely these, but to no avail.</p></li>
<li><p>Google included the header names in lower-case in the "h" tag, whereas Exim does not, even though I entered them in lower-case in Exim's configuration. I read that header names should be lower-cased when generating the <em>header signature hash</em>, but the text does not state that the same applies to the header names in the "h" tag (<a href="http://dkimcore.org/specification.html" rel="nofollow noreferrer">http://dkimcore.org/specification.html</a> section 3.2), yet Google seems to do this. I imagine overriding this in Exim would be quite hard?</p></li>
</ol>

<p>I also noticed that besides the differences in "h", the DKIM-Signature header structure is exactly the same in both bar some whitespace differences (the exim one also only has spaces and new lines after the semicolon separators, so it appears to be fine, it's just broken up differently). At first I thought maybe Exim wasn't setting some required tags, but in such a case the error should be different anyway.</p>

<p>Exim Version: 4.87
Running on a cPanel 11 centOS 7.2 server
Exim DKIM configuration:</p>

<pre><code>dkim_remote_smtp:
  driver = smtp
  interface = &lt;; ${if exists {/etc/mailips}{${lookup{${lc:$sender_address_domain}}lsearch{/etc/maili
ps}{$value}{${lookup{${lc:$sender_address_domain}}lsearch{/etc/mailips}{$value}{${lookup{${perl{get_
sender_from_uid}}}lsearch*{/etc/mailips}{$value}{}}}}}}}}
  helo_data = ${if exists {/etc/mailhelo}{${lookup{${lc:$sender_address_domain}}lsearch{/etc/mailhel
o}{$value}{${lookup{${lc:$sender_address_domain}}lsearch{/etc/mailhelo}{$value}{${lookup{${perl{get_
sender_from_uid}}}lsearch*{/etc/mailhelo}{$value}{$primary_hostname}}}}}}}{$primary_hostname}}
  dkim_domain = ${lc:$sender_address_domain}
  dkim_selector = default
  dkim_private_key = "/var/cpanel/domain_keys/private/${dkim_domain}"
  dkim_canon = relaxed
  dkim_sign_headers = to:from:subject:message-id:date:user-agent:mime-version:content-transfer-encoding
</code></pre>

<p>(The last line was added by me - it did not work before either)</p>

<p>As it seems the error specifically relates to the signature verification, I do not believe the following is relevant, but I include it anyway:</p>

<p>The Exim email is being sent by Mr nobody on the server, but the envelope-from and the Return-Path header is the correct email address of the intended sender. There shouldn't be any problems in this area since SPF, even on MS, is passing.</p>

<p>While the email sent from Google has</p>

<blockquote>
  <p>Message-ID: &lt;[id]@[domain of sender]></p>
</blockquote>

<p>the email sent by Exim has</p>

<blockquote>
  <p>Message-ID: &lt;[id]@[server host name]></p>
</blockquote>

<p>Any help/ideas would be much appreciated. As always MS making life difficult... interesting?</p>