various fixes

This commit is contained in:
holger krekel
2023-12-09 00:18:03 +01:00
parent d8c8040f07
commit 1b1f9365c9
13 changed files with 171 additions and 90 deletions

View File

@@ -1,21 +1,19 @@
from pathlib import Path
from fnmatch import fnmatch
import iniconfig
class Config:
def __init__(self, mailname, section):
self.mailname = mailname
self.privacy_postal = section.get("privacy_postal")
self.privacy_mail = section.get("privacy_mail")
self.privacy_pdo = section.get("privacy_pdo")
self.privacy_supervisor = section.get("privacy_supervisor")
self.has_privacy_policy = self.privacy_mail != None
system_mailname_path = Path("/etc/mailname")
def read_config(inipath, mailname):
def read_config(inipath, mailname=None):
if mailname is None:
with open(system_mailname_path) as f:
mailname = f.read().strip()
ini = iniconfig.IniConfig(inipath)
privacy = None
privacy = {}
for section in ini:
if section.name.startswith("privacy:"):
domain = section["domain"]
@@ -23,4 +21,20 @@ def read_config(inipath, mailname):
privacy = section
break
return Config(mailname, privacy or {})
return Config(inipath, mailname, privacy, params=ini.sections["params"])
class Config:
def __init__(self, inipath, mailname, privacy, params):
self._inipath = inipath
self.mailname = mailname
self.privacy_postal = privacy.get("privacy_postal")
self.privacy_mail = privacy.get("privacy_mail")
self.privacy_pdo = privacy.get("privacy_pdo")
self.privacy_supervisor = privacy.get("privacy_supervisor")
self.max_user_send_per_minute = int(params["max_user_send_per_minute"])
self.filtermail_smtp_port = int(params["filtermail_smtp_port"])
self.postfix_reinject_port = int(params["postfix_reinject_port"])
def _getbytefile(self):
return open(self._inipath, "rb")

View File

@@ -11,6 +11,8 @@ from aiosmtpd.smtp import SMTP
from aiosmtpd.controller import Controller
from smtplib import SMTP as SMTPClient
from .config import read_config
def check_encrypted(message):
"""Check that the message is an OpenPGP-encrypted message."""
@@ -76,13 +78,15 @@ class SMTPController(Controller):
class BeforeQueueHandler:
def __init__(self):
def __init__(self, config):
self.config = config
self.send_rate_limiter = SendRateLimiter()
async def handle_MAIL(self, server, session, envelope, address, mail_options):
logging.info(f"handle_MAIL from {address}")
envelope.mail_from = address
if not self.send_rate_limiter.is_sending_allowed(address):
max_sent = self.config.max_user_send_per_minute
if not self.send_rate_limiter.is_sending_allowed(address, max_sent):
return f"450 4.7.1: Too much mail from {address}"
parts = envelope.mail_from.split("@")
@@ -97,13 +101,14 @@ class BeforeQueueHandler:
if error:
return error
logging.info("re-injecting the mail that passed checks")
client = SMTPClient("localhost", "10025")
client = SMTPClient("localhost", self.config.postfix_reinject_port)
client.sendmail(envelope.mail_from, envelope.rcpt_tos, envelope.content)
return "250 OK"
async def asyncmain_beforequeue(port):
Controller(BeforeQueueHandler(), hostname="127.0.0.1", port=port).start()
async def asyncmain_beforequeue(config):
port = config.filtermail_smtp_port
Controller(BeforeQueueHandler(config), hostname="127.0.0.1", port=port).start()
def check_DATA(envelope):
@@ -142,16 +147,14 @@ def check_DATA(envelope):
class SendRateLimiter:
MAX_USER_SEND_PER_MINUTE = 80
def __init__(self):
self.addr2timestamps = {}
def is_sending_allowed(self, mail_from):
def is_sending_allowed(self, mail_from, max_send_per_minute):
last = self.addr2timestamps.setdefault(mail_from, [])
now = time.time()
last[:] = [ts for ts in last if ts >= (now - 60)]
if len(last) <= self.MAX_USER_SEND_PER_MINUTE:
if len(last) <= max_send_per_minute:
last.append(now)
return True
return False
@@ -160,9 +163,10 @@ class SendRateLimiter:
def main():
args = sys.argv[1:]
assert len(args) == 1
config = read_config(args[0])
logging.basicConfig(level=logging.WARN)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
task = asyncmain_beforequeue(port=int(args[0]))
task = asyncmain_beforequeue(config)
loop.create_task(task)
loop.run_forever()

View File

@@ -2,7 +2,7 @@
Description=Chatmail Postfix BeforeQeue filter
[Service]
ExecStart={execpath} 10080
ExecStart={execpath} {config_path}
Restart=always
RestartSec=30