Why does Gmail bounce my email with 550 5.7.30 or 421 4.7.30?
Gmail slowed down or blocked the message because no DKIM signature on it passed. Gmail asks large senders for DKIM even when SPF passes. Whoever sends the mail turns on DKIM signing, and you publish the key it gives you in your domain's DNS.
The bounce
Google's list of Gmail SMTP errors gives two texts. Under 550 5.7.30:
This message was blocked because it didn't pass DKIM authentication. Gmail requires bulk email senders to authenticate their email with DKIM.
Authentication results: DKIM = did not pass
Under 421 4.7.30, the temporary form:
Your email has been rate limited because DKIM authentication didn't pass for this message. Gmail requires all email bulk senders to authenticate their email with DKIM.
Authentication results: DKIM = Did not pass.
What Gmail checked
Gmail's sender guidelines ask senders who send more than 5,000 messages per day to Gmail accounts to "Set up SPF and DKIM email authentication for your domain." A message that passes SPF still needs DKIM.
Gmail looked for a DKIM signature, fetched the public key the signature names from DNS, and checked the signature against it. "Did not pass" covers two cases:
- There is no signature. The service or server never signed the message. Many services sign only once you turn DKIM on for your domain.
- The signature fails. The key is missing from DNS, the service changed its key and the DNS record still holds the old one, or the message changed after it was signed.
Who has to fix it
Whoever sends the mail signs it, and the owner of the domain publishes the key.
- No signature: turn on DKIM in the service, or in your email provider for mail you write yourself, and publish the record it gives you. Sign with your own domain, so the signature also counts for DMARC: services call this custom DKIM.
- A failing signature: compare the key in your DNS with the one the service shows, under the same selector. Check a DKIM key in DNS shows how, and I set up DKIM, but the source still fails covers the cases where the key looks right.
The records
A DKIM key lives under its selector, below _domainkey in your domain. A service gives you one of two kinds:
s1._domainkey.example.com CNAME s1.dkim.newsletter.example
s1._domainkey.example.com TXT v=DKIM1; k=rsa; p=MIIBIjANBgkqh...
A CNAME points to a key the service keeps and rotates. A TXT record holds the key itself, and you replace it when the service changes its key. Copy the name and value exactly as the service shows them. Set up DKIM for a sending service has the steps.
What it looks like in your DMARC reports
In the aggregate reports for your domain, the source behind this bounce shows up as a row like this:
<row>
<source_ip>192.0.2.10</source_ip>
<count>40</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>pass</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<spf>
<domain>example.com</domain>
<result>pass</result>
</spf>
</auth_results>
SPF passes and aligns, so DMARC passes, but auth_results has no dkim element: the mail carried no signature. A signature that fails shows up as a dkim element with your domain, its selector and fail. The dkim under policy_evaluated is "The result of the DKIM DMARC Identifier Alignment test" (RFC 9990, section 3.1.1.9).
In Mailmoni, the explanation of a source like this says there is no DKIM signature and tells you to set up DKIM in the service, or, when a signature fails, to check the DKIM key for its selector in DNS.