From f5e48d1a8bf6db24b3883e79e018ac0eecd7126f Mon Sep 17 00:00:00 2001 From: missytake Date: Wed, 18 Feb 2026 00:37:53 +0100 Subject: [PATCH 1/5] config: load default values from Config(), not chatmail.ini.f --- chatmaild/src/chatmaild/config.py | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/chatmaild/src/chatmaild/config.py b/chatmaild/src/chatmaild/config.py index de6704c09..8127efd77 100644 --- a/chatmaild/src/chatmaild/config.py +++ b/chatmaild/src/chatmaild/config.py @@ -10,12 +10,7 @@ def read_config(inipath): assert Path(inipath).exists(), inipath cfg = iniconfig.IniConfig(inipath) - params = cfg.sections["params"] - default_config_content = get_default_config_content(params["mail_domain"]) - df_params = iniconfig.IniConfig("ini", data=default_config_content)["params"] - new_params = dict(df_params.items()) - new_params.update(params) - return Config(inipath, params=new_params) + return Config(inipath, params=cfg.sections["params"]) class Config: @@ -36,16 +31,18 @@ def __init__(self, inipath, params): self.max_user_send_per_minute = int(params.get("max_user_send_per_minute", 60)) self.max_user_send_burst_size = int(params.get("max_user_send_burst_size", 10)) - self.max_mailbox_size = params["max_mailbox_size"] - self.max_message_size = int(params.get("max_message_size", "31457280")) - self.delete_mails_after = params["delete_mails_after"] - self.delete_large_after = params["delete_large_after"] - self.delete_inactive_users_after = int(params["delete_inactive_users_after"]) - self.username_min_length = int(params["username_min_length"]) - self.username_max_length = int(params["username_max_length"]) - self.password_min_length = int(params["password_min_length"]) - self.passthrough_senders = params["passthrough_senders"].split() - self.passthrough_recipients = params["passthrough_recipients"].split() + self.max_mailbox_size = params.get("max_mailbox_size", "500M") + self.max_message_size = int(params.get("max_message_size", 31457280)) + self.delete_mails_after = params.get("delete_mails_after", "20") + self.delete_large_after = params.get("delete_large_after", "7") + self.delete_inactive_users_after = int( + params.get("delete_inactive_users_after", 100) + ) + self.username_min_length = int(params.get("username_min_length", 9)) + self.username_max_length = int(params.get("username_max_length", 9)) + self.password_min_length = int(params.get("password_min_length", 9)) + self.passthrough_senders = params.get("passthrough_senders", "").split() + self.passthrough_recipients = params.get("passthrough_recipients", "").split() self.www_folder = params.get("www_folder", "") self.filtermail_smtp_port = int(params.get("filtermail_smtp_port", "10080")) self.filtermail_smtp_port_incoming = int( From 90d6280a215270572e10a9235b901a05abf24fbd Mon Sep 17 00:00:00 2001 From: missytake Date: Tue, 24 Feb 2026 14:43:58 +0100 Subject: [PATCH 2/5] config: default delete_inactive_users_after is 90, actually --- chatmaild/src/chatmaild/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chatmaild/src/chatmaild/config.py b/chatmaild/src/chatmaild/config.py index 8127efd77..f0f6724ca 100644 --- a/chatmaild/src/chatmaild/config.py +++ b/chatmaild/src/chatmaild/config.py @@ -36,7 +36,7 @@ def __init__(self, inipath, params): self.delete_mails_after = params.get("delete_mails_after", "20") self.delete_large_after = params.get("delete_large_after", "7") self.delete_inactive_users_after = int( - params.get("delete_inactive_users_after", 100) + params.get("delete_inactive_users_after", 90) ) self.username_min_length = int(params.get("username_min_length", 9)) self.username_max_length = int(params.get("username_max_length", 9)) From 179459dce5975d1e2ccc4fbbef7e9cd7af9d9e28 Mon Sep 17 00:00:00 2001 From: missytake Date: Tue, 24 Feb 2026 14:44:46 +0100 Subject: [PATCH 3/5] config: comment out values in chatmail.ini.f, so defaults take precedence --- chatmaild/src/chatmaild/ini/chatmail.ini.f | 42 ++++++++++---------- chatmaild/src/chatmaild/tests/test_config.py | 7 +++- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/chatmaild/src/chatmaild/ini/chatmail.ini.f b/chatmaild/src/chatmaild/ini/chatmail.ini.f index 5d3cbe0d0..372130589 100644 --- a/chatmaild/src/chatmaild/ini/chatmail.ini.f +++ b/chatmaild/src/chatmaild/ini/chatmail.ini.f @@ -12,42 +12,42 @@ # # email sending rate per user and minute -max_user_send_per_minute = 60 +#max_user_send_per_minute = 60 # per-user max burst size for sending rate limiting (GCRA bucket capacity) -max_user_send_burst_size = 10 +#max_user_send_burst_size = 10 # maximum mailbox size of a chatmail address -# Oldest messages will be removed automatically, so mailboxes never run full. -max_mailbox_size = 500M +# (Oldest messages will be removed automatically, so mailboxes never run full) +#max_mailbox_size = 500M # maximum message size for an e-mail in bytes -max_message_size = 31457280 +#max_message_size = 31457280 # days after which mails are unconditionally deleted -delete_mails_after = 20 +#delete_mails_after = 20 # days after which large messages (>200k) are unconditionally deleted -delete_large_after = 7 +#delete_large_after = 7 # days after which users without a successful login are deleted (database and mails) -delete_inactive_users_after = 90 +#delete_inactive_users_after = 90 # minimum length a username must have -username_min_length = 9 +#username_min_length = 9 # maximum length a username can have -username_max_length = 9 +#username_max_length = 9 # minimum length a password must have -password_min_length = 9 +#password_min_length = 9 # list of chatmail addresses which can send outbound un-encrypted mail -passthrough_senders = +#passthrough_senders = # list of e-mail recipients for which to accept outbound un-encrypted mails # (space-separated, item may start with "@" to whitelist whole recipient domains) -passthrough_recipients = +#passthrough_recipients = # Use externally managed TLS certificates instead of built-in acmetool. # Paths refer to files on the deployment server (not the build machine). @@ -64,18 +64,18 @@ # # SMTP outgoing filtermail and reinjection -filtermail_smtp_port = 10080 -postfix_reinject_port = 10025 +#filtermail_smtp_port = 10080 +#postfix_reinject_port = 10025 # SMTP incoming filtermail and reinjection -filtermail_smtp_port_incoming = 10081 -postfix_reinject_port_incoming = 10026 +#filtermail_smtp_port_incoming = 10081 +#postfix_reinject_port_incoming = 10026 # if set to "True" IPv6 is disabled -disable_ipv6 = False +#disable_ipv6 = False # Your email adress, which will be used in acmetool to manage Let's Encrypt SSL certificates -acme_email = +#acme_email = # Defaults to https://iroh.{{mail_domain}} and running `iroh-relay` on the chatmail # service. @@ -108,13 +108,13 @@ # in per-maildir ".in/.out" files. # Note that you need to manually cleanup these files # so use this option with caution on production servers. -imap_rawlog = false +#imap_rawlog = false # set to true if you want to enable the IMAP COMPRESS Extension, # which allows IMAP connections to be efficiently compressed. # WARNING: Enabling this makes it impossible to hibernate IMAP # processes which will result in much higher memory/RAM usage. -imap_compress = false +#imap_compress = false # diff --git a/chatmaild/src/chatmaild/tests/test_config.py b/chatmaild/src/chatmaild/tests/test_config.py index 040b45fab..9abab7bf7 100644 --- a/chatmaild/src/chatmaild/tests/test_config.py +++ b/chatmaild/src/chatmaild/tests/test_config.py @@ -13,7 +13,12 @@ def test_read_config_basic(example_config): assert not example_config.privacy_pdo and not example_config.privacy_postal inipath = example_config._inipath - inipath.write_text(inipath.read_text().replace("60", "37")) + inipath.write_text( + inipath.read_text().replace( + "#max_user_send_per_minute = 60", + "max_user_send_per_minute = 37", + ) + ) example_config = read_config(inipath) assert example_config.max_user_send_per_minute == 37 assert example_config.mail_domain == "chat.example.org" From fef67b8bd7ad33dafe5d23fada22075b1ac95450 Mon Sep 17 00:00:00 2001 From: missytake Date: Tue, 12 May 2026 15:20:51 +0200 Subject: [PATCH 4/5] config: remove testrun-specific overrides --- chatmaild/src/chatmaild/config.py | 26 +--------------- .../src/chatmaild/ini/override-testrun.ini | 16 ---------- chatmaild/src/chatmaild/tests/test_config.py | 31 +++++++------------ 3 files changed, 12 insertions(+), 61 deletions(-) delete mode 100644 chatmaild/src/chatmaild/ini/override-testrun.ini diff --git a/chatmaild/src/chatmaild/config.py b/chatmaild/src/chatmaild/config.py index f0f6724ca..db79d75db 100644 --- a/chatmaild/src/chatmaild/config.py +++ b/chatmaild/src/chatmaild/config.py @@ -161,31 +161,7 @@ def get_default_config_content(mail_domain, **overrides): for name, value in extra.items(): new_line = f"{name} = {value}" new_lines.append(new_line) - - content = "\n".join(new_lines) - - # apply testrun privacy overrides - - if mail_domain.endswith(".testrun.org"): - override_inipath = inidir.joinpath("override-testrun.ini") - privacy = iniconfig.IniConfig(override_inipath)["privacy"] - lines = [] - for line in content.split("\n"): - for key, value in privacy.items(): - value_lines = value.format(mail_domain=mail_domain).strip().split("\n") - if not line.startswith(f"{key} =") or not value_lines: - continue - if len(value_lines) == 1: - lines.append(f"{key} = {value}") - else: - lines.append(f"{key} =") - for vl in value_lines: - lines.append(f" {vl}") - break - else: - lines.append(line) - content = "\n".join(lines) - return content + return "\n".join(new_lines) def is_valid_ipv4(address: str) -> bool: diff --git a/chatmaild/src/chatmaild/ini/override-testrun.ini b/chatmaild/src/chatmaild/ini/override-testrun.ini deleted file mode 100644 index af337173d..000000000 --- a/chatmaild/src/chatmaild/ini/override-testrun.ini +++ /dev/null @@ -1,16 +0,0 @@ - -[privacy] - -passthrough_recipients = privacy@testrun.org echo@{mail_domain} - -privacy_postal = - Merlinux GmbH, Represented by the managing director H. Krekel, - Reichgrafen Str. 20, 79102 Freiburg, Germany - -privacy_mail = privacy@testrun.org -privacy_pdo = - Prof. Dr. Fabian Schmieder, lexICT UG (limited), Ostfeldstr. 49, 30559 Hannover. - You can contact him at *delta-privacy@merlinux.eu* (Keyword: DPO) -privacy_supervisor = - State Commissioner for Data Protection and Freedom of Information of - Baden-Württemberg in 70173 Stuttgart, Germany. diff --git a/chatmaild/src/chatmaild/tests/test_config.py b/chatmaild/src/chatmaild/tests/test_config.py index 9abab7bf7..bde15ca83 100644 --- a/chatmaild/src/chatmaild/tests/test_config.py +++ b/chatmaild/src/chatmaild/tests/test_config.py @@ -36,26 +36,17 @@ def test_read_config_basic_using_defaults(tmp_path, maildomain): example_config = read_config(inipath) assert example_config.max_user_send_per_minute == 60 assert example_config.filtermail_smtp_port_incoming == 10081 - - -def test_read_config_testrun(make_config): - config = make_config("something.testrun.org") - assert config.mail_domain == "something.testrun.org" - assert len(config.privacy_postal.split("\n")) > 1 - assert len(config.privacy_supervisor.split("\n")) > 1 - assert len(config.privacy_pdo.split("\n")) > 1 - assert config.privacy_mail == "privacy@testrun.org" - assert config.filtermail_smtp_port == 10080 - assert config.postfix_reinject_port == 10025 - assert config.max_user_send_per_minute == 60 - assert config.max_mailbox_size == "500M" - assert config.delete_mails_after == "20" - assert config.delete_large_after == "7" - assert config.username_min_length == 9 - assert config.username_max_length == 9 - assert config.password_min_length == 9 - assert "privacy@testrun.org" in config.passthrough_recipients - assert config.passthrough_senders == [] + assert example_config.filtermail_smtp_port == 10080 + assert example_config.postfix_reinject_port == 10025 + assert example_config.max_user_send_per_minute == 60 + assert example_config.max_mailbox_size == "500M" + assert example_config.delete_mails_after == "20" + assert example_config.delete_large_after == "7" + assert example_config.username_min_length == 9 + assert example_config.username_max_length == 9 + assert example_config.password_min_length == 9 + assert example_config.passthrough_recipients == [] + assert example_config.passthrough_senders == [] def test_config_userstate_paths(make_config, tmp_path): From 89cc636546cc2d5d7810d1d5dd651d0b681a5f80 Mon Sep 17 00:00:00 2001 From: missytake Date: Tue, 12 May 2026 22:27:27 +0200 Subject: [PATCH 5/5] config: remove filtermail ports from default ini --- chatmaild/src/chatmaild/ini/chatmail.ini.f | 8 -------- 1 file changed, 8 deletions(-) diff --git a/chatmaild/src/chatmaild/ini/chatmail.ini.f b/chatmaild/src/chatmaild/ini/chatmail.ini.f index 372130589..85bdb6d4c 100644 --- a/chatmaild/src/chatmaild/ini/chatmail.ini.f +++ b/chatmaild/src/chatmaild/ini/chatmail.ini.f @@ -63,14 +63,6 @@ # Deployment Details # -# SMTP outgoing filtermail and reinjection -#filtermail_smtp_port = 10080 -#postfix_reinject_port = 10025 - -# SMTP incoming filtermail and reinjection -#filtermail_smtp_port_incoming = 10081 -#postfix_reinject_port_incoming = 10026 - # if set to "True" IPv6 is disabled #disable_ipv6 = False