Antispam: lessons refused by the engine no longer pass for learned

Found on the NAS, where nothing had been learned in weeks while the UI said
"Marked as spam": the source tree predated v1.3.2, so api/worker-* had no
controller password and every lesson got 401 — and the trail of state that
left behind kept it broken after the password was fixed.

- /learn records a lesson only when rspamd accepted it. Recording refused ones
  made the menu claim "Marked as spam" and its dedup blocked every retry.
- Bootstrap: done-markers move to a new key. The old one may have been written
  by the "-0" bug (a total outage read as a clean run of zero), which left an
  account marked done with nothing taught and never retried; every older
  install re-runs the bootstrap once, harmlessly (rspamd skips what it knows).
- "Learn from my Spam folder now" in Settings > Antispam filtering queues the
  bootstrap for the user's accounts at once, instead of the hourly sweep.
- webmail.sh update now recreates rspamd: it reads the controller password only
  when created, so a changed .env reached the app but never the engine.
- doctor's advice for the 401 names both real causes (a pre-v1.3.2 compose
  file, or an rspamd started with an old password) and the fix for each; the
  old "update v1.3.2" advice could not help.
- docs/nas-install.md: how to refresh the source tree on a tarball install.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 20:25:14 +02:00
co-authored by Claude Opus 5.5
parent 165442d897
commit befa1c2404
7 changed files with 276 additions and 15 deletions
+26
View File
@@ -404,6 +404,32 @@ migrations stay expand-then-contract (see `docs/migrations.md` discipline in
`deployment-setup-instructions.md` §9). For the rare breaking migration, restore
the dump that `update` took in step 1.
### Refreshing the source tree (installs without git)
`update` replaces the **images**. The files around them — `docker-compose.yml`,
`deploy/webmail.sh`, `docker/rspamd/local.d` (read by the antispam engine) — come
from the source tree on the NAS, and change only when that tree does. On an
install that was unpacked from a tarball rather than cloned, refresh it now and
then, keeping `.env` and the data directory:
```bash
cd /share/Container/webmail # the folder that holds src/
curl -fsSL -o main.tar.gz http://192.168.1.185:8418/lukas/webmail-client/archive/main.tar.gz
tar -xzf main.tar.gz # unpacks to ./webmail-client
cp -p src/.env webmail-client/.env
[ -f src/docker/.env.prod ] && cp -p src/docker/.env.prod webmail-client/docker/.env.prod
./src/deploy/webmail.sh down # stop with the OLD files
mv src src-old-$(date +%Y%m%d) # kept as a backup
mv webmail-client src
chmod +x src/deploy/*.sh src/docker/*.sh
cd src && ./deploy/webmail.sh up && ./deploy/webmail.sh doctor
```
`down`/`up` rather than `update`: every container is recreated from the new
compose file, including the ones `update` leaves alone, and bind mounts point at
the new folder instead of the renamed one. Data lives in `DATA_ROOT`, outside
`src/`, and `.env` keeps `IMAGE_TAG`, so the same version comes back up.
### Building images elsewhere
Building on the NAS is simple but slow and RAM-hungry. Two alternatives: