From e1371c4f8497dee1e344a349eabef904ac4f313e Mon Sep 17 00:00:00 2001 From: Lukas Remis Date: Mon, 21 Sep 2026 22:28:58 +0200 Subject: [PATCH] doctor: the antispam check printed nothing on the install it was for MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It hid its own result behind an `elif ... ; fi` with no `else`, gated on `docker compose ps --status running --services` — a flag older Compose does not accept. On the QNAP the flag failed, the elif went false, and the check produced no output whatsoever. A check that goes quiet when something unexpected happens is the failure it was written to catch. Drop the gate and classify the probe's own output instead: AUTHORISED, a 401, a stopped stack, or anything else. Every branch prints, and the "anything else" branch shows the raw tail rather than swallowing it. Also say so when antispam is absent from ENABLED_PLUGINS. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018SqJYt7jD7oUEkoY68sBZo --- deploy/webmail.sh | 48 +++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/deploy/webmail.sh b/deploy/webmail.sh index 3dfaddd..04f8326 100755 --- a/deploy/webmail.sh +++ b/deploy/webmail.sh @@ -369,30 +369,46 @@ cmd_doctor() { # the scan worker while every learn is refused by the controller. Prove the # app containers can actually reach it rather than trusting that the variable # is set somewhere. + # + # Every path below says something. The first cut of this check hid its own + # result behind an `elif` with no `else` and a `docker compose ps --status` + # that older Compose does not accept, so on the install it was written for it + # printed nothing at all — the same silence it exists to break. case " ${ENABLED_PLUGINS:-} " in - *" antispam "*|" ") - if [ -z "${RSPAMD_CONTROLLER_PASSWORD:-}" ]; then - red " RSPAMD_CONTROLLER_PASSWORD is empty — antispam will classify but never learn" - echo " fix: webmail.sh init regenerates it, then: webmail.sh update"; ok=1 - elif compose ps --status running --services 2>/dev/null | grep -qx rspamd; then - # From inside the api container, with the password it really has: - # that is the call the learning loop makes. - if compose exec -T api python -c " -import os, sys, urllib.request + *" antispam "*) + if [ -z "${RSPAMD_CONTROLLER_PASSWORD:-}" ]; then + red " RSPAMD_CONTROLLER_PASSWORD is empty — antispam will classify but never learn" + echo " fix: webmail.sh init regenerates it, then: webmail.sh update"; ok=1 + else + # The call the learning loop makes, from the container that makes it, + # with the password that container actually holds. + probe="$(compose exec -T api python -c " +import os, urllib.request req = urllib.request.Request( os.environ.get('RSPAMD_CONTROLLER_URL', 'http://rspamd:11334') + '/stat', headers={'Password': os.environ.get('RSPAMD_CONTROLLER_PASSWORD', ''), 'Deliver-To': 'doctor'}) urllib.request.urlopen(req, timeout=5).read() -" >/dev/null 2>&1; then - grn " antispam engine reachable and learning is authorised" - else +print('AUTHORISED') +" 2>&1)" || true + case "$probe" in + *AUTHORISED*) + grn " antispam engine reachable and learning is authorised" ;; + *401*|*Unauthorized*) red " the api container cannot authenticate to the antispam controller." red " Mail will still be classified, but NOTHING will be learned." - echo " usually RSPAMD_CONTROLLER_PASSWORD reaching rspamd but not api/worker-*." - echo " fix: webmail.sh update (v1.3.1+ passes it to both)"; ok=1 - fi - fi ;; + echo " RSPAMD_CONTROLLER_PASSWORD reaches rspamd but not api/worker-*." + echo " fix: webmail.sh update v1.3.2 (or later), which passes it to both" + ok=1 ;; + *"not running"*|*"No such service"*|*"no such service"*|*"is not running"*) + ylw " antispam not checked — the stack is not running. Start it, then re-run doctor." ;; + *) + ylw " antispam check inconclusive; the engine may be starting. Raw result:" + printf ' %s\n' "$(printf '%s' "$probe" | tail -3)" ;; + esac + fi ;; + *) + ylw " antispam is not in ENABLED_PLUGINS — no spam filtering on this install" ;; esac if command -v ss >/dev/null 2>&1; then