At 02:14 a pager fires: the transactional mail queue on api.example.dev is backing up, and every send returns the same line. The on-call engineer pastes the bounce into Slack and nobody knows which of three DNS records broke.
That is the usual shape of this incident. The 550 5.7.26 bounce is not an SMTP bug, it is an authentication verdict from the receiver.
What is 550 5.7.26 and why does it appear?
The full text reads 550 5.7.26 Unauthenticated email from domain is not allowed. It is a policy rejection, not a relay failure. The recipient's MTA evaluated your message against DMARC and found no passing authentication identifier aligned with your From domain.
Receivers like Google Workspace and Microsoft 365 now enforce DMARC for bulk senders. If your domain publishes p=reject but your mail stream is unsigned, every message dies at the gateway. No retry helps.
How does DKIM authentication actually work?
DKIM is a cryptographic signature attached as a header. The mechanism runs in five steps at the protocol level.
- Your MTA builds the message body, computes a SHA-256 hash of selected headers and the body, then signs that hash with your private key.
- It adds a
DKIM-Signature: header containing d=example.dev, s=s2024, h=from:to:subject:date, and b= (the signature) plus bh= (the body hash).
- The receiving server parses
d= and s=, then queries DNS for s2024._domainkey.example.dev TXT.
- It reads the
p= tag โ the base64-encoded public key โ and verifies the signature against the hash.
- If the hash matches and the
d= domain aligns with the From domain, DKIM passes and DMARC can pass on that alone.
The DNS record itself looks exactly like this:
s2024._domainkey.example.dev. 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1vX...IDAQAB"
Note the tags: v=DKIM1 is the version, k=rsa the key type, p= the public key. A record missing p= is treated as a revoked key and fails closed.
Which selector name and key length should you use?
| Setting | Recommended value | Why it matters |
|---|
| Selector | s2024 or mail2024 | Dated selectors let you rotate keys without downtime |
| Key type | RSA 2048-bit | Industry default; validates everywhere |
| Key size | 2048 bits | 1024-bit keys are flagged weak by many receivers |
| TXT record TTL | 3600 seconds | Long enough to cache, short enough to rotate |
| Chunking | Split at 255 bytes | RFC 6376 caps a single TXT string at 255 chars |
A 2048-bit key produces roughly 392 base64 characters, so it must be split into two or three quoted strings inside one TXT record. Panels that insert a space between chunks silently corrupt the key.
If you want to confirm the record before touching production, the free DNS propagation checker on SarangAI resolves selector records from multiple regions and shows the raw TXT payload.
A real failure case: the launch-day 550 storm
A SaaS team shipped a new billing service on a Tuesday. Within an hour, 4,000 invoice emails bounced with 550 5.7.26. The old marketing domain worked fine; the new mail.example.dev domain did not.
Root cause: the DNS record had been created at s2024._domainkey.mail.example.dev (a subdomain wildcard, not the sending domain), while the MTA signed with d=example.dev. Selector mismatch. The MTA reported success because it only signs, it never verifies.
The fix took eleven minutes: publish the correct record, flush the resolver cache, and re-send the queue. The lesson is that DKIM signing success is not the same as DKIM verification success. Always verify from the outside.
Step-by-step remediation walkthrough
- Generate the key pair. Run
openssl genrsa -out dkim.key 2048 then openssl rsa -in dkim.key -pubout -out dkim.pub. Expected result: two files, and the public key printed below the header line.
- Extract the base64 body. Strip the
-----BEGIN PUBLIC KEY----- lines and all newlines. Expected result: a single continuous base64 string of about 392 characters.
- Publish the TXT record. Create
s2024._domainkey.example.dev TXT with v=DKIM1; k=rsa; p=<base64>. Expected result: the record returns from public resolvers within the TTL window.
- Verify with dig. Run
dig +short TXT s2024._domainkey.example.dev. Expected result: the full record echoed back with no extra spaces inside p=.
- Configure the signer. In your MTA or ESP, set the domain, selector, and private key path. Expected result: outgoing messages carry a
DKIM-Signature: header.
- Send a test to a Gmail account. Open the message, choose "Show original". Expected result:
dkim=pass with header.d=example.dev.
- Check DMARC alignment. Run the DKIM and DMARC checks on SarangAI against the live record. Expected result: aligned pass, and the 550 5.7.26 bounce stops on the next send cycle.
Here is the same verification loop as a Python script you can drop into a CI pipeline:
import dns.resolver
def check_dkim(domain: str, selector: str) -> bool:
name = f"{selector}._domainkey.{domain}"
try:
answers = dns.resolver.resolve(name, "TXT")
except dns.resolver.NXDOMAIN:
print(f"FAIL: no TXT record at {name}")
return False
record = b"".join(answers[0].strings).decode()
ok = record.startswith("v=DKIM1") and "p=" in record and len(record) > 200
print(f"{name} -> {'PASS' if ok else 'FAIL'}: {record[:60]}...")
return ok
check_dkim("example.dev", "s2024")
Common mistakes that keep the bounce alive
- Wrong selector in DNS. The record sits at
default._domainkey but the MTA signs with s2024. The receiver queries the signing selector and finds nothing.
- Truncated public key. A copy-paste that drops the last 20 base64 characters produces
dkim=fail (bad signature) instead of a missing-record error, which sends you chasing the wrong problem.
- Spaces inside the TXT value. Some DNS panels inject a space between 255-byte chunks. Use quoted-string concatenation, not a literal space.
- 1024-bit keys in 2024. Many receivers accept them but downgrade trust scoring, and some outright reject. Generate 2048-bit from the start.
- Signing a subdomain but sending from the apex.
d=mail.example.dev does not align with From: [email protected], so DMARC fails even though DKIM passes.
Verifying the fix from the command line
The fastest external check is a raw DNS query, since it bypasses your own resolver cache:
$ dig +short TXT s2024._domainkey.example.dev
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1vX..."
$ dig +short TXT _dmarc.example.dev
"v=DMARC1; p=reject; rua=mailto:[email protected]"
$ swaks --to [email protected] --from [email protected] --server smtp.example.dev
<** 550 5.7.26 Unauthenticated email from example.dev is not allowed. Please contact your provider.
That last line is what you are trying to eliminate. Once the selector resolves and the signature verifies, swaks returns 250 2.0.0 OK and the queue drains.
Key Takeaways
- 550 5.7.26 is a DMARC authentication rejection, not an SMTP transport error.
- Publish DKIM at
selector._domainkey.domain with a 2048-bit RSA key split at 255-byte chunks.
- Selector mismatch between DNS and the signing MTA is the single most common cause.
- Verify with
dig +short TXT <selector>._domainkey.example.dev before blaming the mail server.
- SarangAI's free DNS propagation checker confirms the record resolves correctly from public resolvers.
Frequently Asked Questions
What does 550 5.7.26 Unauthenticated email from domain is not allowed actually mean?
It means the recipient's MTA rejected your message because the From domain had no valid DKIM signature, no SPF alignment, or no DMARC pass, so the domain failed authentication checks.
Which DKIM selector name should I use?
Any name works as long as your signing software and DNS record match, but use a dated selector like s2024 or mail2024 so you can rotate keys without overwriting the old record.
How long should a DKIM key be?
Use 2048-bit RSA for production. 1024-bit still validates but many providers flag it as weak, and 4096-bit keys exceed the 255-byte TXT chunk limit and break some resolvers.
Why does my DKIM record fail even though it exists?
Usually a typo in the selector, a missing p= tag, wrong TXT chunking, or a space inserted by the DNS panel, which invalidates the base64 public key.
Can I fix 550 5.7.26 without DKIM?
Only if you publish SPF and DMARC with alignment for your sending IP. DKIM is the fastest fix because it survives forwarding and does not depend on the sending IP address.