{"id":20703179,"url":"https://github.com/sfttech/sftspambridge","last_synced_at":"2025-03-11T04:24:28.484Z","repository":{"id":142753856,"uuid":"222178552","full_name":"SFTtech/sftspambridge","owner":"SFTtech","description":"relay mail from dovecot to a rspamd host for spam learning when declared as spam/ham by users","archived":false,"fork":false,"pushed_at":"2019-11-17T00:51:09.000Z","size":19,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-01-17T19:53:10.272Z","etag":null,"topics":["dovecot","python","rspamd","spam-filtering"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SFTtech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"copying.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"liberapay":"SFTtech"}},"created_at":"2019-11-17T00:50:44.000Z","updated_at":"2019-11-17T00:52:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"a540250a-5ba0-474a-8beb-38623f6eb283","html_url":"https://github.com/SFTtech/sftspambridge","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SFTtech%2Fsftspambridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SFTtech%2Fsftspambridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SFTtech%2Fsftspambridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SFTtech%2Fsftspambridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SFTtech","download_url":"https://codeload.github.com/SFTtech/sftspambridge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242969027,"owners_count":20214561,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dovecot","python","rspamd","spam-filtering"],"created_at":"2024-11-17T01:06:34.817Z","updated_at":"2025-03-11T04:24:28.445Z","avatar_url":"https://github.com/SFTtech.png","language":"Python","funding_links":["https://liberapay.com/SFTtech"],"categories":[],"sub_categories":[],"readme":"sftspambridge\n=============\n\nTransfers E-Mails from **Dovecot** to **rspamd** for spamlearning.\n\nThis is useful if Dovecot is running on a *different machine* than rspamd.\n\n\nIdea\n----\n* Main goal: let `rspamd` learn if a mail is spam/ham when a user moves it to a folder\n\n* Dovecot user moves spam mail to a folder\n  * e.g. from INBOX to Junk means \"new spam mail\"\n  * from Junk to somewhere else except the Trash means \"new ham mail\"\n* The mail is stored in the psql database\n* The rspamd host gets notified that there's a new mail to learn\n* The mail is fed into rspamd as spam or ham\n\n\nHowTo\n-----\n\nComponents:\n* Dovecot sieve configuration\n* Dovecot sieve scripts\n* PostgreSQL database for mail transfer\n* Python script executed by sieve to grab mail\n* Python daemon that receives the mail and feeds it into rspamd\n\n\n### Database config\n\n* Create psql database (I used `spamlearn`) on whatever host (either the rspamdhost, dovecothost, a third one, doesn't matter..)\n* Create two users, e.g. `spamlearn` and `spamlearn_vmail` (you can change the names of course).\n  * `spamlearn` is the 'trusted' user, `spamlearn_vmail` is the untrusted one\n  * Dovecot will feed mails to the database with `spamlearn_vmail` (shared among all Dovecot users),\n    and rspamd will use `spamlearn` to get the mails for learning.\n* Initialize the database as user `spamlearn`:\n  * `./sftspambridge.py dbsetup | sudo -u postgresql psql spamlearn spamlearn`\n  * allow user `spamlearn_vmail` to add new mail:\n    * `grant execute on function add_mail to spamlearn_vmail;`\n\n* allow connections to the database from other hosts\n  * grant access in `pg_hba.conf` (ideally use a VPN network or something, then you don't need psql's ssl anyway)\n  * to secure the connection to the database with ssl, set in `postgresql.conf`:\n```\nssl = on\nssl_cert_file = '/etc/letsencrypt/live/yourhost.lol/current.pem'\nssl_key_file = '/etc/letsencrypt/live/yourhost.lol/current.key'\nssl_ciphers = '!aNULL:!eNULL:!CAMELLIA:HIGH:@STRENGTH'\n```\n\n\n### Dovecot config\n\n* Install and activate sieve\n\n* Among many other things in `conf.d/90-sieve.conf`, ensure there is something like:\n```\nsieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment\nsieve_plugins = sieve_imapsieve sieve_extprograms\n\n# sft spam filtering (tm)\n# if a message was moved to Spam folder\n# (or a flag changed in the Spam dir, e.g. by forwarding/replying)\nimapsieve_mailbox1_name = Junk\nimapsieve_mailbox1_causes = COPY FLAG\nimapsieve_mailbox1_before = file:/etc/dovecot/sieve/report-spam.sieve\n\n# From Spam folder to elsewhere\nimapsieve_mailbox2_name = *\nimapsieve_mailbox2_from = Junk\nimapsieve_mailbox2_causes = COPY\nimapsieve_mailbox2_before = file:/etc/dovecot/sieve/report-ham.sieve\n\n# pipe executables are in here\nsieve_pipe_bin_dir = /etc/dovecot/pipe\n```\n\n* `mkdir /etc/dovecot/pipe/` and place `sftspambridge.py` in there. It will be executed by sieve under user `vmail`\n* `mkdir /etc/dovecot/sieve/` and the `report-spam` and `ham` scripts there (and compile them with the `Makefile`)\n\n\n### Spambridge config\n\nConfigure `sftspambridge` in `/etc/sftspambridge.cfg`.\n\nStore the passwords for the right user accounts:\n\n* On the Dovecot host:\n  * Store the `spamlearn_vmail`-database-user and password under `[database]`\n  * Store your host identifier under `[dovecot]`: If the database is filled by multiple dovecots, we then know which one it was\n  * `chown vmail:vmail /etc/sftspambridge.cfg`\n  * `chmod 600 /etc/sftspambridge.cfg`\n* On the rspamd-host:\n  * Store the `spamlearn`-database-user and password under `[database]`\n  * Store the rspamd controller password under `[rspamd]`\n  * Create user `sftspambridge`\n  * `chown sftspambridge:sftspambridge /etc/sftspambridge.cfg`\n  * `chmod 600 /etc/sftspambridge.cfg`\n\n### systemd service\n\nNeeded on the rspamd-host:\n\n* Add the Linux-user `sftspambridge`\n* Place `sftspambridgereceiver.service` in `/etc/systemd/system`\n* Enable and start the service: `systemctl enable --now sftspambridgereceiver.service`\n\n\nFuture Ideas\n------------\n\n* Delayed learning: Currently the mail is fed into rspamd quite instantly (it's a feature).\n  But if a mail was moved to Junk by mistake, it will be learned as Junk so quickly you can't undo the move.\n  Thus, there could be a configurable delay timer after which the message will be fed to rspamd.\n* There could be a WebUI listing \"proposed\" spam messages from untrusted\n  mail users (that have consented to participate in spam learning). In the UI,\n  messages are 'activated' for actual learning (i.e. a confirmation that it's really spam/ham).\n\n\nLicense\n-------\n\n**GNU GPLv3** or later; see [copying.md](copying.md) and [legal/GPLv3](/legal/GPLv3).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsfttech%2Fsftspambridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsfttech%2Fsftspambridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsfttech%2Fsftspambridge/lists"}