2026.07 / EMAIL DELIVERABILITY 030
Docker Mailserver Emails Going to Spam: A Deliverability Checklist
Your Docker Mailserver container is healthy. SMTP accepts the message. The recipient server returns 250 OK. Then the email lands in spam.
That is not one problem with one switch. Delivery proves that a receiving server accepted the message; inbox placement is a later trust decision. The useful way to debug it is to work from machine identity and authentication outward, using the received message headers as evidence instead of changing DNS records at random.
Start with one controlled message, inspect what the recipient actually saw, and fix failed checks before trying to “improve reputation.”
First: distinguish rejection, deferral, and spam placement
These outcomes need different investigations:
- Rejected: the remote SMTP server returns a permanent
5xxresponse. Read the enhanced status code and provider link in the bounce. - Deferred: the server returns a temporary
4xxresponse. Postfix should queue and retry; inspect the queue and logs rather than repeatedly resending. - Accepted into spam: SMTP completed, but filtering classified the message. Inspect the recipient copy’s full headers.
Do not run dozens of test sends. Repetition from a new or misconfigured host adds noise and may make reputation signals worse.
1. Make the server identity internally consistent
A self-hosted mail server should have one stable, fully qualified hostname such as mail.example.com. Four views of that identity should agree:
- The server’s public address has a PTR (reverse-DNS) record returning
mail.example.com. mail.example.comresolves forward to that same sending address.- Postfix announces that hostname in its SMTP banner and EHLO.
- The SMTP TLS certificate is valid for that hostname.
PTR is normally configured in the VPS provider’s control panel, not at your ordinary DNS host. Do not invent a second PTR per mailbox domain: one server can send for several domains while keeping one machine identity.
# Forward lookup
dig +short A mail.example.com
# Reverse lookup — use your own address, never a copied example
dig +short -x <server-address>
# Check STARTTLS, certificate, and SMTP conversation
openssl s_client -starttls smtp \
-connect mail.example.com:25 \
-servername mail.example.com
Google’s sender guidelines explicitly require valid forward and reverse DNS for sending domains or IPs. A PTR is not a substitute for message authentication, but a missing or generic PTR is a foundational fault.
2. Publish one accurate SPF policy
SPF says which systems may use a domain in the SMTP envelope sender. For a simple host whose MX is the only sender, the policy might be:
example.com. TXT "v=spf1 mx -all"
That is an example, not a value to copy blindly. If a website, helpdesk, newsletter provider, or transactional relay also sends as the domain, the policy must authorize the real mail flow. Publish one SPF record: two separate v=spf1 TXT records produce a permanent error rather than a stricter policy.
dig +short TXT example.com
SPF can pass yet fail DMARC alignment when the authenticated envelope domain differs from the address visible in From:. That distinction matters more than a green “SPF pass” badge.
3. Confirm DKIM is signing the message you sent
DKIM attaches a cryptographic signature to the message. Docker Mailserver can generate the key material, but three things still have to line up:
- the outbound message contains a
DKIM-Signatureheader; - its
d=signing domain is the intended domain; - the selector in
s=resolves to the matching public key in DNS.
# If the signature says s=mail and d=example.com
dig +short TXT mail._domainkey.example.com
With multi-domain setups, generating a key is not always the same as enabling signing for that domain—especially when a custom Rspamd signing map already exists. Preserve working domain entries and add the new domain beside them. The Docker Mailserver project’s DKIM, DMARC, and SPF guide documents the current signing workflow.
4. Check DMARC alignment, not merely record presence
DMARC evaluates whether the visible From: domain aligns with a domain authenticated by SPF or DKIM. At least one aligned path must pass. A practical rollout begins with reporting rather than an immediate reject policy:
_dmarc.example.com. TXT \
"v=DMARC1; p=none; rua=mailto:[email protected]"
Create the report mailbox or alias before publishing it, and remember that aggregate reports may contain metadata about your mail flows. After observing every legitimate sender and fixing alignment, move deliberately toward quarantine or reject. A stricter policy does not repair broken alignment.
Google requires SPF or DKIM for all senders to personal Gmail accounts and imposes SPF, DKIM, DMARC, alignment, and additional requirements on bulk senders. Even a low-volume personal server benefits from deploying all three correctly.
5. Read the recipient’s Authentication-Results header
In Gmail, use Show original. Other clients usually expose “view source” or “view message details.” Look for a block shaped like this:
Authentication-Results: recipient.example;
spf=pass smtp.mailfrom=example.com;
dkim=pass header.d=example.com;
dmarc=pass header.from=example.com
The recipient’s result is more useful than a DNS checker alone because it evaluates the message that really arrived. Diagnose each failure literally:
spf=fail: the observed sender was not authorized, or DNS returned the wrong policy.dkim=none: the message was not signed.dkim=fail: selector/key mismatch, malformed DNS, or message modification broke the signature.dmarc=fail: neither passing mechanism aligned with the visible From domain.
6. Inspect Docker Mailserver and Postfix evidence
Use your actual Compose service or container name. Keep message IDs and remote SMTP responses; redact addresses before sharing logs publicly.
# Recent mail logs
docker logs --since 30m mailserver
# Queue summary
docker exec mailserver postqueue -p
# Confirm the effective hostname
docker exec mailserver postconf myhostname
# List Docker Mailserver accounts
docker exec mailserver setup email list
A log line showing status=sent and a remote 250 response confirms handoff, not inbox placement. A queue full of deferred mail points back to connectivity, DNS, rate, or remote-policy errors before content filtering.
7. Check reputation without chasing magic scores
A new VPS address has little or no sending history. A recycled address may have bad history. Authentication proves authorization; it does not guarantee reputation.
- Check whether the sending address appears on reputable blocklists, then investigate the cause before requesting removal.
- Use provider postmaster tooling when you send enough volume for it to show useful data.
- Keep volumes low, steady, and expected. Do not “warm” an address with fake conversations or purchased lists.
- Secure every account and watch for unexpected queue growth; a compromised mailbox can destroy reputation quickly.
- If the provider assigns an address with entrenched bad history, document the evidence and ask for a clean replacement.
Google advises senders to keep user-reported spam rates below 0.1% and avoid ever reaching 0.3%. For a personal server, the simpler rule is to send only wanted mail and make unsubscribing easy wherever messages are subscription-based.
8. Use a boring controlled test message
Test one variable at a time with a message that resembles legitimate correspondence:
- a real From address and display name;
- a plain subject that describes the message;
- both text and HTML parts if your application normally sends both;
- no URL shorteners, tracking tricks, oversized images, or surprise attachments;
- a valid
Message-IDand sensibleDateheader.
Content matters, but rewriting copy before SPF, DKIM, DMARC, and PTR pass is debugging in the wrong order. Likewise, marking your own test as “not spam” may train one mailbox without proving that the infrastructure is correct.
A compact order of operations
- Stop repeated tests and save one recipient message source.
- Confirm the SMTP result: rejected, deferred, or accepted.
- Verify PTR → hostname → forward DNS, EHLO, and TLS certificate.
- Verify the single SPF policy matches every legitimate sender.
- Confirm the received message has a valid DKIM signature.
- Confirm DMARC passes through SPF or DKIM alignment.
- Inspect Postfix logs and the queue using the message ID.
- Only then assess address/domain reputation and message construction.
- Send one new controlled test and compare headers.
Self-hosted email deliverability is never guaranteed, and inbox algorithms are intentionally not fully public. But the investigation does not have to be mystical. Build a coherent server identity, authenticate the exact message, read the receiving system’s verdict, and change only the layer the evidence says is broken.