def_whitelist_from_rcvd / welcomelist_from_rcvd does not fire on Cloudron mail app (SpamAssassin 4.0.0) — also no GUI option for sender whitelisting
-
Cloudron mail app version: cloudron/mail 3.18.2 (SpamAssassin 4.0.0, 2022-12-13)
Summary
There is no GUI (or API) way to whitelist a trusted sender domain in the Cloudron mail app — the only exposed mechanism is the free-text "Custom SpamAssassin rules" field, which maps directly to
/app/data/spamd/custom.cf(included fromlocal.cf). While investigating recurring false positives on legitimate Microsoft 365 senders, I found that the relay-verified whitelist directive (whitelist_from_rcvd/ its current aliaswelcomelist_from_rcvd, including thedef_variants) does not fire at all in this setup — confirmed on both long-standing entries and newly added ones. The unauthenticated variant (welcomelist_from, From-header only, no relay check) works correctly.Environment
- Cloudron mail app 3.18.2, SpamAssassin 4.0.0
- spamd invocation (from
ps) :/usr/sbin/spamd --max-children 2 --port 7833 --nouser-config --virtual-config /app/data/spamd/%u --syslog stderr -u cloudron --allow-tell /etc/spamassassin/local.cf(shipped, resets on update) includes two persistent files under/app/data/spamd/:acl.cf(GUI-managed sender allow/blocklist) andcustom.cf(GUI "Custom SpamAssassin rules" free-text field — this is the only place available forscore/whitelist tuning).- No
trusted_networks/internal_networksdirective is present anywhere in the shipped config (local.cf,*.prefiles) or incustom.cf.
Steps to reproduce
- In the mail app's "Custom SpamAssassin rules" field, add:
def_whitelist_from_rcvd *@outlook.com *.protection.outlook.com - Save (this restarts spamd — confirmed via
ps -o etimeon the spamd process). - Take a real inbound message from an
*@outlook.comsender that passed through*.protection.outlook.comrelays (verified via the Received headers). - Re-score it:
docker exec mail spamassassin -t < message.eml - Observe
X-Spam-Status— noUSER_IN_WELCOMELIST/USER_IN_DEF_WHITELIST(deprecated alias) test appears, and the score is identical to a run with the whitelist line removed.
Repeated with:
- A newly added entry for a specific business partner domain (
def_whitelist_from_rcvd *@example.nl *.protection.outlook.com) on a real message from that domain — same result, rule does not fire. - The current directive name instead of the deprecated alias (
def_welcomelist_from_rcvd *@example.nl *.protection.outlook.com) — same result. - A synthetic minimal
.emlwith a single clean Received header (from HOST.outbound.protection.outlook.com (mail-....outbound.protection.outlook.com [IP]) by my.<domain> (Haraka) ...) and a matching From address — same result. SpamAssassin's own debug log correctly identifies this Received header as__LAST_UNTRUSTED_RELAY_NO_AUTH(i.e. it does parse the relay boundary correctly), yet the whitelist rule still does not fire.
Control test (confirms the mechanism itself, isolates the bug)
spamassassin -t --cf="welcomelist_from *@example.nl" < message.eml→
X-Spam-Status: No, score=-100.0 ... tests=...,USER_IN_WELCOMELIST— fires immediately and correctly, at the rule's hardcoded default score of -100.So: the address-only, non-relay-verified directive works reliably; the relay-verified directive (which is presumably intended to be the "safe" option, since it additionally confirms the mail actually arrived via the claimed infrastructure, not just a forged From: header) never fires, in this container/config, regardless of naming (
whitelist_from_rcvdvswelcomelist_from_rcvd) or entry age (default-shipped vs newly added).Suspected cause
_check_welcomelist_rcvd(inMail::SpamAssassin::Plugin::WLBLEval, called fromcheck_from_in_default_welcomelist) presumably relies on SpamAssassin's own trusted/internal relay boundary detection to know which Received header to compare against the second (origin) parameter. Since this Cloudron config declares notrusted_networks/internal_networks, that auto-detection may be picking the wrong boundary or failing silently for this reason — even though the same debug run shows SpamAssassin does correctly tag the relevant Received header as the last untrusted relay via a different, unrelated eval (__LAST_UNTRUSTED_RELAY_NO_AUTH). I have not been able to fully confirm this from the plugin source in the time available; posting here in case someone has already solved this or knows the missing config.Workaround in use
Switched the partner-domain entries to the non-relay-verified directive with a tuned-down score (rather than the default -100, which would let a spoofed From: header fully bypass filtering):
score USER_IN_WELCOMELIST -4.0 welcomelist_from *@example.nlThis is good enough to counter a BAYES/HELO false-positive but does not fully bypass SPF/DKIM/DNSBL-driven detection the way the (non-working) relay-verified version was intended to. It's a knowingly weaker mechanism (spoofable From header) — would much prefer the relay-verified variant to actually work.
Ask
- Is
whitelist_from_rcvd/welcomelist_from_rcvdknown to be broken in this SpamAssassin/Cloudron combination, and if so is there a missing config directive (e.g.trusted_networks) that should be shipped by default or that we should add ourselves incustom.cf? - Separately: is there any plan for a proper GUI/API-level "trusted sender domain" feature in the mail app, so this doesn't require hand-editing SpamAssassin rule syntax in a free-text field?
Happy to provide more debug output / test further if useful.
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login