doctor: the antispam check printed nothing on the install it was for

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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018SqJYt7jD7oUEkoY68sBZo
This commit is contained in:
2026-09-21 22:28:58 +02:00
co-authored by Claude Opus 5
parent 31edd4015e
commit e1371c4f84
+28 -12
View File
@@ -369,30 +369,46 @@ cmd_doctor() {
# the scan worker while every learn is refused by the controller. Prove the # 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 # app containers can actually reach it rather than trusting that the variable
# is set somewhere. # 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 case " ${ENABLED_PLUGINS:-} " in
*" antispam "*|" ") *" antispam "*)
if [ -z "${RSPAMD_CONTROLLER_PASSWORD:-}" ]; then if [ -z "${RSPAMD_CONTROLLER_PASSWORD:-}" ]; then
red " RSPAMD_CONTROLLER_PASSWORD is empty — antispam will classify but never learn" 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 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 else
# From inside the api container, with the password it really has: # The call the learning loop makes, from the container that makes it,
# that is the call the learning loop makes. # with the password that container actually holds.
if compose exec -T api python -c " probe="$(compose exec -T api python -c "
import os, sys, urllib.request import os, urllib.request
req = urllib.request.Request( req = urllib.request.Request(
os.environ.get('RSPAMD_CONTROLLER_URL', 'http://rspamd:11334') + '/stat', os.environ.get('RSPAMD_CONTROLLER_URL', 'http://rspamd:11334') + '/stat',
headers={'Password': os.environ.get('RSPAMD_CONTROLLER_PASSWORD', ''), headers={'Password': os.environ.get('RSPAMD_CONTROLLER_PASSWORD', ''),
'Deliver-To': 'doctor'}) 'Deliver-To': 'doctor'})
urllib.request.urlopen(req, timeout=5).read() urllib.request.urlopen(req, timeout=5).read()
" >/dev/null 2>&1; then print('AUTHORISED')
grn " antispam engine reachable and learning is authorised" " 2>&1)" || true
else 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 " the api container cannot authenticate to the antispam controller."
red " Mail will still be classified, but NOTHING will be learned." red " Mail will still be classified, but NOTHING will be learned."
echo " usually RSPAMD_CONTROLLER_PASSWORD reaching rspamd but not api/worker-*." echo " RSPAMD_CONTROLLER_PASSWORD reaches rspamd but not api/worker-*."
echo " fix: webmail.sh update (v1.3.1+ passes it to both)"; ok=1 echo " fix: webmail.sh update v1.3.2 (or later), which passes it to both"
fi 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 ;; fi ;;
*)
ylw " antispam is not in ENABLED_PLUGINS — no spam filtering on this install" ;;
esac esac
if command -v ss >/dev/null 2>&1; then if command -v ss >/dev/null 2>&1; then