2026.08 / Rspamd false positive 047
Docker Mailserver Rspamd Rejecting Legitimate Email? Trace the Score
A legitimate sender says your Docker Mailserver host refused their message as spam. Raising the global reject threshold or allowlisting the visible From: address may make the next test pass, but neither action explains the decision—and both can weaken filtering for everyone.
Rspamd evaluates many signals, adds their symbol scores, and recommends an action to Postfix through the Milter interface. The safe fix is to preserve one failed attempt, identify the exact action and symbols, repair the bad signal where possible, and use a narrow authenticated exception only when the sender cannot repair it.
Keep real addresses, message bodies, queue IDs, IP addresses, authentication results, hosted domains, and configuration dumps private. The examples below use reserved domains and placeholders.
First identify the actual outcome
| Sender or mailbox evidence | What happened |
|---|---|
Permanent 5xx SMTP response mentioning spam or policy | The server rejected the transaction. The sender normally receives a non-delivery report. |
Temporary 4xx response | The message was deferred or grey-listed. A conforming sender should retry; this is not a permanent rejection. |
| Message arrives with spam headers or in Junk | It was accepted. Follow the score and mailbox filtering path rather than a reject investigation. |
| No matching server event | The sender may have reached another MX, an old address, or a different IPv4/IPv6 host. |
Rspamd’s action model distinguishes reject, greylist/soft reject, add header, and no action. Treat the full SMTP response and your own log event as the starting evidence, not the sender’s summary that “the server blocked it.”
1. Capture one narrow Docker Mailserver log window
Ask the sender privately for the complete SMTP response, attempted time with timezone, and envelope recipient. Then inspect a short period on the mail host:
docker compose logs --since 20m mailserver
Use the real Compose service name. Locate the matching connection and record privately:
- the SMTP reply and enhanced status code;
- the envelope sender and recipient—not only the message headers;
- the Rspamd action, total score, required threshold, and symbol list;
- whether Postfix accepted a queue ID or rejected before queueing;
- which public source address and hostname the server actually observed.
If no event matches, verify the domain’s MX, then resolve every MX target. Split delivery across a stale secondary MX or old AAAA record can make two senders see different filters.
2. Read the symbols, not just the total
A total such as 16.2 explains little by itself. The useful evidence is the set of named symbols that produced it. Group them by cause:
- Authentication: SPF, DKIM, and DMARC failures or missing records.
- Identity and DNS: reverse-DNS, HELO, resolver, DNSBL, or reputation signals.
- Message construction: malformed MIME, suspicious URLs, mismatched sender headers, missing plain-text parts, or unusual attachments.
- Statistical learning: Bayes or neural symbols influenced by prior training.
- Policy overrides: a force-action, map, or custom rule chose an action beyond ordinary score arithmetic.
One high-value symbol can dominate a decision, or several modest failures can cross the threshold together. Do not disable every symbol in the list. First ask which symbol is factually wrong and which accurately describes a repairable sender fault.
3. Confirm the effective action thresholds
Do not assume defaults from a forum post. Docker Mailserver and Rspamd versions can differ, and persistent overrides may change the packaged policy. Query the running container:
docker compose exec mailserver \
rspamadm configdump actions
docker compose exec mailserver \
rspamadm configtest
Keep the complete dump private. In a simplified example, an installation might grey-list at one score, add spam headers at a higher score, and reject only above a final threshold. The values on your running instance are what matter.
Rspamd uses layered configuration. Docker Mailserver documents persistent custom Rspamd files through its configuration volume, while Rspamd distinguishes local.d additions from override.d replacements. An override can replace more packaged configuration than intended, so review mounted custom files before changing a number.
4. Repair authentication and sender identity first
If the symbols point to SPF, DKIM, DMARC, reverse DNS, or HELO, the best fix belongs with the sender. For a domain you control, verify:
dig +short TXT example.net
dig +short TXT selector._domainkey.example.net
dig +short TXT _dmarc.example.net
dig +short -x <sender-address>
Use the observed envelope and signing domains from the failed attempt. A message can show spf=pass yet still fail DMARC because the envelope domain does not align with the visible From: domain. A forwarded message can also break SPF while retaining valid aligned DKIM. Diagnose the actual combination rather than requiring every mechanism to pass independently.
If this is a third-party sender, return the exact redacted symbols and authentication result to its administrator. A broad local allowlist hides its broken identity only for your users.
5. Check DNS from inside the container
Docker Mailserver’s Rspamd guide warns that Rspamd depends heavily on working DNS. Compare a basic lookup on the host and inside the service:
dig example.net
docker compose exec mailserver \
getent ahosts example.net
Then inspect the container’s configured resolver privately and check logs for timeouts, SERVFAIL, or unavailable DNS lists. Do not publish resolver addresses or internal network details.
If many unrelated senders suddenly gain DNS-related symbols, suspect the resolver path before creating many sender exceptions. Confirm outbound DNS reachability, Docker DNS state, upstream resolver health, and whether a DNSBL has usage or resolver restrictions. Repair the shared fault, restart only the affected component if required, and compare one fresh scan.
6. Preserve and rescan the original message carefully
If the sender can provide the complete original message as an .eml file through a private channel, save it outside the public repository and scan it with the Rspamd client available in the running container:
docker compose exec -T mailserver \
rspamc < /private/path/sample.eml
Never commit the sample: raw messages contain addresses, message IDs, routing headers, and often personal content. Also understand the limitation: an offline rescan may not reproduce connection-level facts such as the original source address, SMTP authentication, recipient context, time-sensitive DNS data, or prior greylisting state. The original server log remains primary evidence.
A rescan is most useful for message-content and MIME symbols. Compare it with the original decision; do not treat a different score as proof that the problem disappeared.
7. Inspect custom rules and learning state
Review only the persistent Rspamd customization paths mounted into the container. Look for:
- global score changes copied from an old guide;
- an
override.dfile that unintentionally replaced packaged settings; - sender, recipient, domain, or address maps that are too broad;
- forced actions that explain a rejection below the apparent threshold;
- Bayes or neural symbols with unexpectedly large influence.
Docker Mailserver notes that its optional spam-learning database is global rather than isolated per user. Training a disputed message as ham can therefore affect filtering for every mailbox. Do not use learning as the first response to broken DKIM, a malformed newsletter, or an unsafe URL. Train only when a complete representative message is genuinely misclassified and trusted administrators control the process.
8. Prefer a narrow, authenticated exception
Sometimes a necessary third party cannot change its mail promptly. If an exception is justified, bind it to evidence that is hard to forge. A visible From: address alone is not enough; headers are easy to spoof.
Depending on the legitimate route, a narrow rule might require a specific domain plus valid aligned DKIM, or a tightly controlled sending route plus another authenticated property. Rspamd’s whitelist module supports conditions involving valid DKIM and SPF, while its settings and maps can scope behavior. Test the exact semantics against the version you run.
- Document the business owner and reason.
- Limit the sender/domain and, if appropriate, recipient scope.
- Require authentication rather than trusting display text.
- Set a review or expiry date.
- Run
rspamadm configtestbefore reload or recreation. - Verify that an unauthenticated spoof does not receive the exception.
Avoid a prefilter “accept everything from this domain” rule unless you fully understand that it can bypass later filters. Lowering or disabling the global reject action to accommodate one sender is broader still.
9. Verify with a controlled matrix
After the smallest repair, test outcomes rather than only container health:
- Ask the affected sender to send one new, ordinary message.
- Correlate its exact timestamp and recipient with a fresh log event.
- Confirm the intended action and symbol changes.
- Confirm the message reaches the intended inbox or expected Junk policy.
- Send one normal message from another known-good external provider.
- If you added an authenticated exception, test a safe controlled message that lacks that authentication and confirm it does not match.
- Re-run
rspamadm configtestafter normal container recreation and verify the persistent policy remains active.
An HTTP health check, a running container, or one accepted SMTP connection does not prove the filter now makes the right decision. The evidence is a fresh message with the expected action and no unintended bypass.
Compact diagnosis order
- Classify the result as reject, temporary deferral, or accepted spam.
- Match one attempt in a narrow Docker Mailserver log window.
- Record the Rspamd action, score, threshold, and complete symbol set privately.
- Query effective actions and validate configuration.
- Repair sender authentication, DNS, identity, or message construction.
- Check shared resolver faults when many senders are affected.
- Review custom rules and global learning before changing policy.
- If unavoidable, create a narrow authenticated, expiring exception.
- Test the affected sender, a known-good sender, and an exception-negative case.
Authoritative references: Docker Mailserver’s Rspamd integration guide and environment-variable reference; Rspamd’s official documentation for actions and scores, authenticated whitelist conditions, and client and learning behavior; plus Postfix’s before-queue Milter documentation. Match every command and configuration path to your pinned versions.