TL;DR
| |
That prints the value ready to paste into the DNS provider, two quoted strings separated by a space:
| |
Both go into the same TXT record. Whoever verifies DKIM concatenates them with no spaces. If Google Workspace or Microsoft 365 handed you the text and you do not have the private key, it is the same without the openssl: echo "<value>" | fold -w 255 | sed 's/.*/"&"/' | paste -sd' ' -.
The problem
A TXT record is made of one or more character-strings, and each one is capped at 255 bytes (RFC 1035). The whole record can be much longer; what it cannot have is a single 410-character string.
| RSA key | Length of p= | With v=DKIM1; k=rsa; p= | Fits in one string? |
|---|---|---|---|
| 1024 bits | 216 | 234 | Yes |
| 2048 bits | 392 | 410 | No: two are needed |
| 4096 bits | 736 | 754 | No: three |
Google Workspace and Microsoft 365 generate 2048-bit keys by default, and rightly so: 1024 has been discouraged since RFC 8301. So almost any new DKIM setup today runs into this, and each provider reacts differently:
| Provider | What happens with 410 characters in a row |
|---|---|
| Route 53 | Rejects it with CharacterStringTooLong, in the console and the CLI |
| Google Cloud DNS | Rejects the value; you have to type the quoted strings yourself |
| Cloudflare | Accepts it and splits it into 255-character chunks on its own |
| BIND and most self-hosted servers | The zone file does not load until you use several strings |
RFC 6376 (§3.6.2.2) requires verifiers to concatenate the strings before using them, so splitting the key is not a trick: it is the intended format.
Per provider
BIND / zone file
| |
Route 53
In the console, paste both quoted strings into Value separated by a space or a line break. From the CLI the value is a single string with escaped quotes:
| |
Google Cloud DNS
In the console, same format in the data field. With gcloud:
| |
With Terraform (google_dns_record_set), a single rrdatas element with escaped quotes:
| |
Cloudflare
Paste the full value into Content; the dashboard splits it on save. When you query it with dig you will see two strings even though you entered one: that is normal.
Verifying
| |
Expected: "v=DKIM1; k=rsa; p=MIIB..." "...IDAQAB", two strings, one record. Then check that the key decodes to 2048 bits, which confirms no character was lost at the cut:
| |
If base64 complains, a space slipped inside the key or characters are missing. Finish with a test email and Authentication-Results: ... dkim=pass in the headers; for a closer look, dmarcian’s DKIM Inspector.
Traps
- The cut can go anywhere, even mid-base64, but never put spaces inside the key. The space between the two strings separates strings; it is not data.
- Do not double the quotes. If the panel adds them for you and you paste
"...",digreturns"\"v=DKIM1...\""and the verifier fails. - One record, not two. Two separate TXT records with the same name are two independent values, and neither is a valid key.
- 2048 is the sweet spot. 4096 means three strings and a DNS answer close to the UDP limit; it works, but gains nothing for DKIM.
- Rotation: publish the new key under a new selector, switch the signer, and delete the old selector after the TTL. Never edit the selector in use.
- SPF has the same limit, but an SPF that does not fit in 255 is usually a sign of too many
include:; there the fix is shortening it, not splitting it.
References: Google Workspace — troubleshoot DKIM issues, AWS re:Post — CharacterStringTooLong, and the Mailhardener DNS record splitter if you would rather not use fold.