{"id":15513779,"url":"https://github.com/evgeni/bley","last_synced_at":"2025-07-01T14:31:26.344Z","repository":{"id":761643,"uuid":"432305","full_name":"evgeni/bley","owner":"evgeni","description":"intelligent greylisting daemon for postfix","archived":false,"fork":false,"pushed_at":"2025-02-11T19:35:16.000Z","size":1819,"stargazers_count":42,"open_issues_count":6,"forks_count":7,"subscribers_count":6,"default_branch":"devel","last_synced_at":"2025-05-11T05:39:34.590Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://bley.mx","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/evgeni.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null}},"created_at":"2009-12-13T13:53:40.000Z","updated_at":"2025-02-11T19:35:19.000Z","dependencies_parsed_at":"2023-11-29T13:30:33.199Z","dependency_job_id":"11230e66-29e8-4e1c-af3d-18aedf53fcc0","html_url":"https://github.com/evgeni/bley","commit_stats":{"total_commits":539,"total_committers":14,"mean_commits":38.5,"dds":0.575139146567718,"last_synced_commit":"fc30d9012e6398a59b391d5b8eb298182b95af35"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/evgeni/bley","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evgeni%2Fbley","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evgeni%2Fbley/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evgeni%2Fbley/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evgeni%2Fbley/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evgeni","download_url":"https://codeload.github.com/evgeni/bley/tar.gz/refs/heads/devel","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evgeni%2Fbley/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262980996,"owners_count":23394446,"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":[],"created_at":"2024-10-02T09:55:09.462Z","updated_at":"2025-07-01T14:31:26.304Z","avatar_url":"https://github.com/evgeni.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"ABOUT\n=====\n`bley` is an intelligent greylisting daemon for Postfix (and Exim).\n\nIt uses various test (incl. RBL and SPF) to decide whether a sender\nshould be greylisted or not, thus mostly eliminating the usual\ngreylisting delay while still filtering most of the spam.\n\nPACKAGES\n========\n\n## [devel builds](https://cloudsmith.io/~bley/repos/bley/packages/)\n\n[![Hosted By: Cloudsmith](https://img.shields.io/badge/OSS%20hosting%20by-cloudsmith-blue?logo=cloudsmith\u0026style=flat-square)](https://cloudsmith.com)\n\nPackage repository hosting is graciously provided by [Cloudsmith](https://cloudsmith.com)\n\n```console\n# mkdir -p /etc/apt/keyrings/\n# curl 'https://dl.cloudsmith.io/public/bley/bley/gpg.31A9C34356A3F75F.key' -o /etc/apt/keyrings/bley.asc\n# echo 'deb [signed-by=/etc/apt/keyrings/bley.asc] https://dl.cloudsmith.io/public/bley/bley/deb/debian sid main' \u003e /etc/apt/sources.list.d/bley.list\n```\n\n## stable builds\n\n * [Debian](https://packages.debian.org/bley) (stretch and buster)\n * [Ubuntu](https://packages.ubuntu.com/bley) (bionic)\n\nDEPENDENCIES\n============\n`bley` is written in [Python](https://www.python.org/) using the\n[Twisted](https://twisted.org/) framework. It uses\n[pyspf](https://github.com/sdgathman/pyspf) for SPF validation and\n[publicsuffix2](https://github.com/nexb/python-publicsuffix2) for checking\nof domains against the [PublicSuffix.org](https://publicsuffix.org)\ndatabase. Database interaction is implemented via\n[sqlite3](https://docs.python.org/3/library/sqlite3.html) for SQLite,\n[psycopg2](https://www.psycopg.org/) for PostgreSQL and\n[mysqlclient](https://github.com/PyMySQL/mysqlclient) for MySQL.\n\nINSTALLATION\n============\n\nQuick and dirty\n---------------\nUnpack the tarball (or clone the git tree), adjust `bley.conf.example`,\nrename it to `bley.conf` and run `python -m bley.cli`.\n\nStill quick, but not dirty\n--------------------------\nUnpack the tarball (or clone the git tree), run `python setup.py build`\nfollowed by `python setup.py install`, copy `/etc/bley/bley.conf.example`\nto `/etc/bley/bley.conf`, adjust it to your needs (see CONFIGURATION below)\nand run `/usr/bin/bley`.\n\nCONFIGURATION\n=============\nBasically you just have to configure the database:\n\n    dbtype = pgsql for PostgreSQL, mysql for MySQL or sqlite3 for SQLite\n    dbhost = the host where the database runs on (usually localhost)\n    dbport = the port where the database runs on (can be left unset for\n             the default 5432 for PostgreSQL and 3306 for MySQL)\n    dbuser = the name of the database user\n    dbpass = the password of the database user\n    dbname = the name (or path in case of SQLite) of the database\n    dbpath = you can also set the path separately and load ${dbpath}/${dbname}\n\nAfter that you can point your Postfix to `bley` as a \n[policy server](https://www.postfix.org/SMTPD_POLICY_README.html) by\nadding `check_policy_service inet:127.0.0.1:1337` to your\n`smtpd_recipient_restrictions` in `main.cf`.\n\n`bley` will be working now, but you probably would like to tune it more\nfor your needs (esp. the used DNWLs and DNSBLs, the greylisting times\nand the hit thresholds).\n\nAdditional Configuration\n------------------------\n\nSometimes, you want to bind `bley` to something else than `127.0.0.1:1337`,\nthis can be achieved with the following two parameters.\n\n    listen_addr = 127.0.0.1\n    listen_port = 1337\n\nAs `bley` is designed to be a deamon, it will write a pid file and a log file.\nThe locations of the two can be configured with the following parameters.\n\n    pid_file = bley.pid\n    log_file = bley.log\n\nSetting `log_file` to the special word `syslog` will make `bley` log to\n`syslog` instead of a file, using the `mail` facility.\n\nIf you want to inform the sender about the greylisting, you can adjust\nthe message sent via\n\n    reject_msg = greylisted, try again later\n\nThe DNSWLs and DNSBLs `bley` uses for its tests can be set via\n\n    dnsbls = zen.spamhaus.org\n    dnswls = list.dnswl.org\n\nThresholds define how many sub-checks have to hit, to trigger a feature\n(whitelisting in case of dnswl, greylisting in case of dnsbl and rfc).\n\n    dnswl_threshold = 1\n    dnsbl_threshold = 1\n    rfc_threshold = 2\n\nHow long should a sender be greylisted, when should we allow him in at\nthe very last and how long should he have to wait more, if he retries to\nearly (all in minutes)?\n\n    greylist_period = 29\n    greylist_max    = 720\n    greylist_penalty= 10\n\nAfter how many days should old entries be deleted from the database?\nEntries of senders who have not verified to be \"good\" should be purged\nearlier.\n\n    purge_days = 40\n    purge_bad_days = 10\n\nSPF ([Sender Policy Framework](http://www.open-spf.org)) checks can be turned\noff. [SPF Best Guess](http://www.open-spf.org/Best_Practices/No_Best_Guess/)\nshould always be turned off.\n\n    use_spf = 1\n    use_spf_guess = 0\n\nIf you use Exim instead of Postfix, set this to 1. It will automatically\nclose connections after the decision is sent. While Postfix supports\nchecking multiple senders over the same connections, Exim does not. In fact\nit even closes the sending part of the socket as soon all details have been\ntransmitted.\n\n    exim_workaround = 0\n\nWhitelisting\n------------\n\nIn some situations, it is useful to be able to whitelist senders or recipients.\nThis can be done by providing lists as files (syntax is [postgrey](https://postgrey.schweikert.ch/) compatible).\n\n    whitelist_recipients_file = ./whitelist_recipients\n    whitelist_clients_file = ./whitelist_clients\n\n### whitelist_recipients_file\n\nThis file contains a list of recipients who are excluded from greylisting.\nOne entry per line. An entry can be either a full email address, the local part,\na domain name or a regular expression:\n\n    user@example.com\n    postmaster@\n    example.com\n    /app.*example/\n\n### whitelist_clients_file\n\nThis file contains a list of clients who are excluded from greylisting.\nOne entry per line. An entry can be either an IP adress, a subnet, a domain name\nor a regular expression.\n\n    192.0.2.200/30\n    example.net\n    /sender.*example/\n\n\nCHECKS\n======\n\nKnown sender\n------------\n\nThe first check is, of course, whether our database already knows about the\n`(ip, sender, recipient)` tuple. If it does, act accordignly, otherways\ncontinue with the other checks.\n\nDNSWL / DNSBL\n-------------\n\nCheck whether the sender IP address is listed in the configured DNSWLs and\nDNSBLs. If either one reaches the configured threshold, the mail is considered\ngood or bad, depending on which threshold was reached.\n\nRFC\n---\n\nWhile the following checks are not all about stricktly implementing the RFC,\nall of them try to identify suboptimal behaviour of the sending MTA, which\noften indicates a spammer.\n\n### HELO\n\nCheck whether the name used in `HELO/EHLO` matches the reverse DNS entry.\n\n### DynIP\n\nCheck whether the hostname looks like a dynamic one.\n\n### sender equals recipient\n\nPeople usually do not send mail themself \"over the Internet\" (and local mail\nshould not be checked by a policy daemon). Spammers on the other hand, often\ntry to bypass address-checks by using the same address as sender and receiver.\n\n### SPF\n\nThe Sender Policy Framework allows domain owners to define which servers are\nallowed to send mail using their domain and which are not.\n\nbleygraph\n=========\n`bley` includes a small graphing utility called `bleygraph`.\nIt will analyze the `bley_log` table of the database, and plot a few graphs\nusing [matplotlib](https://matplotlib.org/).\n\nThere is not much configuration possible for `bleygraph`: the database\nsettings are taken from the `bley` section of `bley.conf` and the path\nfor the graph output (`destdir`) is the only setting in the `bleygraph`\nsection of the configuration file.\n\nMAIL SERVER CONFIGURATION\n=========================\n\nExim\n----\n\nFor exim4, we can install the following ACL:\n\n``` exim\n# Check policy service \"bley\", using the postfix policy service protocol.\n defer log_message = greylisted host $sender_host_address\n        set acl_m0 = request=smtpd_access_policy\\n\\\n                     protocol_state=RCPT\\n\\\n                     protocol_name=${uc:$received_protocol}\\n\\\n                     helo_name=$sender_helo_name\\n\\\n                     client_address=$sender_host_address\\n\\\n                     client_name=$sender_host_name\\n\\\n                     sender=$sender_address\\n\\\n                     recipient=$local_part@$domain\\n\\\n                     \\n\n        set acl_m0 = ${sg\\\n                       {${readsocket{inet:127.0.0.1:1337}{$acl_m0}{5s}{}{action=DUNNO}}}\\\n                       {action=}\\\n                       {}\\\n                     }\n           message = ${sg{$acl_m0}{^\\\\w+\\\\s*}{}}\n         condition = ${if eq{${uc:${substr{0}{5}{$acl_m0}}}}{DEFER}{true}{false}}\n\n# Warn if delayed\nwarn message = ${sg{$acl_m0}{^\\\\w+\\\\s*}{}}\n   condition = ${if eq{${uc:${substr{0}{7}{$acl_m0}}}}{PREPEND}{true}{false}}\n```\n\nOn a Debian system using split configuration for Exim, this can be placed in a file, for instance `/etc/exim4/greylist.bley.conf`, and included from the RCPT acl by setting the `CHECK_RCPT_LOCAL_ACL_FILE` variable to point to that file, in `/etc/exim4/conf.d/main/01_local-variables`.\n\n```\n# /etc/exim4/conf.d/main/01_local-variables\nCHECK_RCPT_LOCAL_ACL_FILE = /etc/exim4/greylist.bley.conf\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevgeni%2Fbley","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevgeni%2Fbley","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevgeni%2Fbley/lists"}