Simple script to gather ham/spam mails from IMAP folders, pipe them through
rspamc and move them to a 'done' imap folder if successful.
This gives the user a simple way of handing over user identified spam mails
to rspamd for training.
The package is installed with pip. This will also install the py-learn-spam
CLI command:
pip install .To enable logging to the systemd journal (requires libsystemd-dev at build
time), install the optional journald extra:
pip install .[journald]If you don't want to clone the repository, you could use
pip install git+https://codeberg.org/archandha/py-learn-spamto install from Codeberg directly.
After installation the script is available as py-learn-spam.
The config file path is resolved in this order:
-c/--configcommand line argumentPY_LEARN_SPAM_CONFIGenvironment variable- Default:
/etc/py-learn-spam.ini
There is a sample INI file (sampe-config.ini) with comments for all
available options. Copy and adapt it to your setup:
cp sampe-config.ini /etc/py-learn-spam.ini
chmod 600 /etc/py-learn-spam.ini # contains IMAP credentialsThree logging targets are supported, configured via [logging] target:
| target | Description |
|---|---|
file |
Write to a log file (default, path set via file =) |
stdout |
Write to stdout — recommended for Docker deployments |
journald |
Write to the systemd journal (requires .[journald]) |
Log output format is controlled via [logging] format:
| format | Description |
|---|---|
text |
Human-readable plain text (default) |
json |
JSON lines — suited for log aggregators like Loki or Graylog |
Target and format are independent and freely combinable.
Example for a Docker-friendly setup in the config file:
[logging]
level = 20
target = stdout
format = jsonBuild the image:
docker build -t py-learn-spam .Run it with the config file mounted in (credentials stay outside the image):
docker run --rm -v /etc/py-learn-spam.ini:/config/py-learn-spam.ini py-learn-spamThe container logs to stdout by default, so set this in your config:
[logging]
target = stdout
format = json # optional, useful for Loki/GraylogFor periodic execution use a systemd timer or cron on the host, or a Kubernetes CronJob — the container is intentionally one-shot and exits after each run.
There are sample files for a systemd unit (py-learn-spam.service) and a
systemd timer (py-learn-spam.timer). After installation with pip the service
calls /usr/local/bin/py-learn-spam directly.
The service runs as a dedicated unprivileged user. Create it once before enabling the service:
useradd --system --no-create-home --shell /bin/false spamlearnFor systemd deployments, logging to the journal is the cleanest option:
[logging]
target = journaldIf you prefer not to use a systemd timer, any cron mechanism works just as well.
STARTTLS starts as a plain-text connection and upgrades to TLS mid-session.
A network-level attacker in a man-in-the-middle position could strip the
STARTTLS capability advertisement before the upgrade happens (STARTTLS
downgrade attack). For remote IMAP servers, use_ssl = SSL (direct TLS) is
therefore the safer choice. use_ssl = TLS or NO are only recommended for
local connections (e.g. host = 127.0.0.1).
Requires Python 3.8 or newer. No external dependencies are needed for the default configuration — everything used is part of the Python standard library.
The optional journald extra pulls in systemd-python for journal support.
There is not much need for further development from my side, as this does what it should. But here and there, there might arise some changes and needs for adaption. Feel free to open an issue or a pull request if you like.
I shifted the main repository to Codeberg.org and will keep the GitHub repository as a mirror.
I'm using ruff now for some time in other projects and will do so in this
mini project as well for consistency.