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