From bb45b20f8a8b815d455dcfa2c56e8667fd25c12e Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Tue, 13 Oct 2026 21:43:13 +1100 Subject: [PATCH] Route rspamd-tagged mail to Junk through Stalwart's spam filter (#544) Stalwart only files mail into Junk natively when its own spam filter marks it, so rspamd-tagged mail reached Junk only for accounts with a Sieve script, and first boot loads upstream DNSBLs, HTTP lists and URL lookups. - enable the spam filter with one header rule scoring `X-Spam: Yes` above the spam threshold, covering every account including newly provisioned ones - remove the upstream spam rules, tags, DNSBL servers, HTTP lists and lookup keys - disable the classifier model and Pyzor Reviewed-on: https://git.unkin.net/unkin/argocd-apps/pulls/544 Co-authored-by: unkin-agent Co-committed-by: unkin-agent --- apps/base/mail/stalwart-configmap.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/base/mail/stalwart-configmap.yaml b/apps/base/mail/stalwart-configmap.yaml index cf485e4..437f83a 100644 --- a/apps/base/mail/stalwart-configmap.yaml +++ b/apps/base/mail/stalwart-configmap.yaml @@ -1,6 +1,7 @@ --- # config.json only names the datastore; everything else lives in Postgres and # is converged from plan.ndjson by the stalwart-apply PostSync Job. +# The spam filter only scores rspamd's X-Spam header, feeding the native Junk path. # The Coordinator uses the plain Redis client: its cluster client never # resubscribes once the Valkey node it subscribed on is replaced. apiVersion: v1 @@ -29,7 +30,14 @@ data: {"@type":"update","object":"MtaOutboundStrategy","value":{"route":{"match":{"0":{"if":"is_local_domain(rcpt_domain)","then":"'local'"}},"else":"'smarthost'"}}} {"@type":"update","object":"MtaStageAuth","value":{"require":{"match":{},"else":"local_port != 25 && local_port != 24"}}} {"@type":"update","object":"SenderAuth","value":{"dkimSignDomain":{"match":{},"else":"false"}}} - {"@type":"update","object":"SpamSettings","value":{"enable":false,"spamFilterRulesUrl":null}} + {"@type":"reconcile","object":"SpamRule","matchOn":["name"],"value":{"rspamd":{"@type":"Header","name":"RSPAMD_SPAM","enable":true,"priority":0,"condition":{"match":{"0":{"if":"name_lower == 'x-spam' && value_lower == 'yes'","then":"'RSPAMD_SPAM'"}},"else":"false"}}}} + {"@type":"reconcile","object":"SpamTag","matchOn":["tag"],"value":{"rspamd":{"@type":"Score","tag":"RSPAMD_SPAM","score":10.0}}} + {"@type":"destroy","object":"SpamDnsblServer"} + {"@type":"destroy","object":"HttpLookup"} + {"@type":"destroy","object":"MemoryLookupKey"} + {"@type":"update","object":"SpamClassifier","value":{"model":{"@type":"Disabled"}}} + {"@type":"update","object":"SpamPyzor","value":{"enable":false}} + {"@type":"update","object":"SpamSettings","value":{"enable":true,"spamFilterRulesUrl":null}} {"@type":"update","object":"Metrics","value":{"prometheus":{"@type":"Enabled","authSecret":{"@type":"None"}}}} {"@type":"update","object":"Http","value":{"allowedEndpoints":{"match":{"0":{"if":"starts_with(path, '/metrics') && local_port != 9090","then":"404"}},"else":"200"}}} {"@type":"update","object":"SystemSettings","value":{"defaultHostname":"mail.unkin.net","defaultDomainId":"#unkin","defaultCertificateId":"#cert"}}