2026.07 / mail authentication 036
Fix Gmail 550 5.7.26 with Docker Mailserver
Gmail’s 550-5.7.26 response means the receiving server rejected a message because it could not authenticate the sending domain to the level its policy required. With Docker Mailserver, the useful question is not “which DNS record should I copy?” It is: which identity did Gmail evaluate, which mechanism passed, and did that identity align with the address visible in From?
Google’s current sender guidance requires SPF or DKIM for all senders to personal Gmail accounts and requires SPF, DKIM, and DMARC for bulk senders. Google recommends configuring all three even at low volume. A self-hosted personal server can therefore be rejected long before it sends anything resembling bulk mail if neither SPF nor DKIM authenticates the real message.
Do not weaken DMARC blindly or keep resending the same broken message. Save the full rejection, verify public DNS, then prove authentication on one controlled message.
First: keep the complete Gmail rejection
The enhanced code is only the start. Save the entire SMTP response from the Docker Mailserver log or non-delivery report. Gmail uses variants that may mention an unauthenticated sender, a domain’s DMARC policy, or missing alignment. Record the queue ID and timestamp, but redact mailbox addresses, message content, host addresses, and infrastructure details before sharing evidence.
docker compose logs --since 30m mailserver
# Search narrowly after you know the queue ID or recipient domain
docker compose logs --since 30m mailserver | \
grep -E 'status=(bounced|deferred)|5[.]7[.]26|gmail'
A Postfix line with status=bounced and Gmail’s 550 confirms a permanent remote rejection. Repeated retries will not repair DNS or signing. Stop automated retests until the authentication path is coherent.
Understand the three identities Gmail compares
SPF, DKIM, and DMARC are related, but they do not validate the same thing:
| Check | Identity it validates | What must be true |
|---|---|---|
| SPF | The envelope sender / Return-Path domain | The observed sending address is authorised by that domain’s SPF policy. |
| DKIM | The signing domain in the signature’s d= tag | The signature verifies against the selector’s public key in DNS. |
| DMARC | The visible RFC5322 From domain | At least one passing SPF or DKIM identity aligns with the visible From domain. |
Under relaxed DMARC alignment, the organisational domains may match; strict alignment requires an exact domain match. This is why “SPF passed” is not enough when a web app uses an unrelated bounce domain, and why “DKIM passed” is not enough when the signer uses a different organisation’s domain.
1. Audit the public DNS Gmail can actually see
Query a public recursive resolver rather than trusting a DNS control panel preview. Replace the names below with your own domain and current DKIM selector:
dig +short TXT example.com @1.1.1.1
dig +short TXT selector1._domainkey.example.com @1.1.1.1
dig +short TXT _dmarc.example.com @1.1.1.1
# Also query an authoritative nameserver when debugging propagation
dig +short NS example.com
dig +short TXT example.com @ns1.dns-provider.example
You should find one SPF policy at the root, a DKIM public key at the selector Docker Mailserver uses, and one DMARC policy at _dmarc. Two separate SPF TXT records do not merge; SPF evaluation can return a permanent error. A DKIM record under the wrong selector is invisible to a message signed with another selector. A DMARC record on the root domain is in the wrong place.
2. Make SPF describe every legitimate outbound route
For direct sending, the SPF policy must authorise the address Gmail sees connecting. If Docker Mailserver sends through a smarthost, the policy must authorise that relay provider’s documented mechanism instead. Use one record and stay within SPF’s DNS-lookup limit.
# Illustrative direct-sender policy; use your real authorised route
example.com. TXT "v=spf1 ip4:192.0.2.10 -all"
# Illustrative provider pattern; use only the provider's official value
example.com. TXT "v=spf1 include:_spf.mail-provider.example -all"
The documentation-only address above comes from the reserved 192.0.2.0/24 range; do not copy it into production. Do not add Google, Microsoft, or a random “common SPF” include unless that service actually sends mail for your domain. After publishing, query public DNS again and allow for the record’s TTL.
3. Prove Docker Mailserver is signing with the expected domain
Current Docker Mailserver releases use Rspamd for DKIM signing, while older installations may still use OpenDKIM. Follow documentation for the image tag you actually run. Inspect the public key generated for your domain and selector without printing private key material:
# List DMS DKIM-related files and permissions; do not print private keys
docker compose exec mailserver sh -lc \
'find /tmp/docker-mailserver -type f -path "*dkim*" -printf "%p %m\n"'
# Inspect recent signing or authentication messages
docker compose logs --since 30m mailserver | \
grep -Ei 'dkim|rspamd|opendkim'
Compare the selector and domain in the outgoing message’s DKIM-Signature header with the DNS name you queried. A common failure is generating a key successfully but publishing the TXT record under the wrong DNS zone, leaving an obsolete selector active, or mounting configuration that does not contain the new key. Restart or reload only as your pinned DMS version documents, then send one new message; an old queued message does not gain a new signature retroactively.
4. Publish DMARC in monitoring mode before enforcement
If this is a new domain or you have not inventoried every sender, begin with a monitoring policy and a reporting mailbox you control:
_dmarc.example.com. TXT \
"v=DMARC1; p=none; rua=mailto:[email protected]; adkim=r; aspf=r"
p=none does not authenticate anything and is not a fix for failed SPF or DKIM. It asks receivers to monitor rather than quarantine or reject based on DMARC policy while you gather evidence. Once every legitimate stream passes aligned authentication, move deliberately to quarantine and then reject. Keep the report mailbox operational and expect aggregate XML reports rather than human-readable support messages.
If Gmail’s response explicitly says your existing DMARC policy caused rejection, temporarily relaxing enforcement can restore legitimate mail while you repair alignment—but only after confirming the DNS change is authorised and understanding the spoofing trade-off. The durable fix is aligned authentication, not permanent p=none.
5. Check alignment, not just pass/fail
Suppose the visible header is From: [email protected]. DMARC can pass through either route:
- SPF route: SPF passes for the envelope sender, such as
[email protected], and that domain aligns withexample.com. - DKIM route: the message has a valid signature with
d=example.com, aligned with the visible From domain.
A third-party contact form that uses a visitor’s address as From is a classic failure. The application does not control the visitor’s domain and cannot authenticate as it. Use a From address on a domain you control, put the visitor in Reply-To, and authenticate the controlled domain. Never forge a customer’s From identity merely to make replies convenient.
6. Test one fresh message and read the received evidence
Send one ordinary message to a Gmail mailbox you control. In Gmail, open Show original and inspect Authentication-Results:
Authentication-Results: mx.google.com;
spf=pass smtp.mailfrom=example.com;
dkim=pass [email protected] header.s=selector1;
dmarc=pass header.from=example.com
Your values will differ. Success means the fresh message is accepted and Gmail reports the intended aligned result—not merely that an online DNS checker found three TXT records. Also inspect the Docker Mailserver queue and delivery response:
docker compose exec mailserver postqueue -p
docker compose logs --since 15m mailserver
A remote 250 response confirms acceptance, not inbox placement. If authentication passes but the message lands in spam, continue with PTR, forward DNS, TLS, reputation, complaint rate, and message-quality checks rather than changing working SPF or DKIM.
Failure patterns that waste time
- Adding a second SPF record: publish one policy that covers all authorised routes.
- Checking only the root TXT records: DKIM and DMARC live at selector-specific and
_dmarcnames. - Assuming DKIM exists because a key was generated: prove the fresh message carries a valid signature using the published selector.
- Setting DMARC to reject immediately: inventory and monitor legitimate senders before enforcing.
- Using a visitor’s address in From: authenticate your own From domain and use Reply-To for the visitor.
- Testing a queued old message: create a fresh transaction after DNS and signer changes.
- Publishing diagnostic output: redact domains when necessary and never expose credentials, private keys, host addresses, or full mail logs.
Compact 550 5.7.26 recovery checklist
- Save the full Gmail response, queue ID, timestamp, and redacted Postfix event.
- Identify the visible From, envelope sender, DKIM signing domain, and selector.
- Query SPF, selector-specific DKIM, and
_dmarcthrough public DNS. - Confirm SPF authorises the route Gmail observed and that only one SPF record exists.
- Confirm Docker Mailserver signs fresh outbound mail with the intended domain and selector.
- Use a monitoring DMARC policy while inventorying legitimate senders, then enforce gradually.
- Send one controlled fresh message and inspect Gmail’s
Authentication-Results. - Require DMARC pass through aligned SPF or aligned DKIM before declaring the fix complete.
The authoritative starting points are Google’s email sender guidelines, Docker Mailserver’s DKIM, DMARC, and SPF guide, and the DMARC alignment rules in RFC 7489. Use Docker Mailserver documentation matching your pinned image, because signer defaults and supported configuration paths can change.