Compare commits

..

8 Commits

Author SHA1 Message Date
missytake
98ff7b3428 ci: try without test_status_cmd 2025-12-12 10:30:55 +01:00
Rodrigo Camacho
c98853570b updated location of the documentation for custom webpage location 2025-12-11 22:50:02 +01:00
Simon Laux
bad356503e Merge pull request #745 from chatmail/simon/i744
fix: Handle case where user followed the tutorial and set the CNAME reccord for mta-sts, but no TXT record for it yet.
2025-12-11 22:41:14 +01:00
adb
dba48e88d1 Merge pull request #760 from chatmail/adb/issue-734
add imap_compress option to chatmail.ini
2025-12-11 08:33:41 +01:00
adbenitez
3ae8834cbe update changelog 2025-12-11 08:33:24 +01:00
adb
81391f4066 Update cmdeploy/src/cmdeploy/dovecot/dovecot.conf.j2
Co-authored-by: missytake <missytake@systemli.org>
2025-12-10 20:43:03 +01:00
adbenitez
55cfd00505 add imap_compress option to chatmail.ini 2025-12-09 09:32:53 +01:00
Treefit
abb70a6b14 Handle case where user followed the tutorial and set the CNAME reccord
for mta-sts, but no TXT record for it yet.
2025-11-28 09:34:44 +01:00
7 changed files with 81 additions and 44 deletions

View File

@@ -2,6 +2,8 @@
## untagged ## untagged
- Add imap_compress option to chatmail.ini (#760)
- Remove echobot from relays - Remove echobot from relays
([#753](https://github.com/chatmail/relay/pull/753)) ([#753](https://github.com/chatmail/relay/pull/753))

View File

@@ -44,6 +44,7 @@ class Config:
self.disable_ipv6 = params.get("disable_ipv6", "false").lower() == "true" self.disable_ipv6 = params.get("disable_ipv6", "false").lower() == "true"
self.acme_email = params.get("acme_email", "") self.acme_email = params.get("acme_email", "")
self.imap_rawlog = params.get("imap_rawlog", "false").lower() == "true" self.imap_rawlog = params.get("imap_rawlog", "false").lower() == "true"
self.imap_compress = params.get("imap_compress", "false").lower() == "true"
if "iroh_relay" not in params: if "iroh_relay" not in params:
self.iroh_relay = "https://" + params["mail_domain"] self.iroh_relay = "https://" + params["mail_domain"]
self.enable_iroh_relay = True self.enable_iroh_relay = True

View File

@@ -45,7 +45,7 @@ passthrough_senders =
# (space-separated, item may start with "@" to whitelist whole recipient domains) # (space-separated, item may start with "@" to whitelist whole recipient domains)
passthrough_recipients = echo@{mail_domain} passthrough_recipients = echo@{mail_domain}
# path to www directory - documented here: https://github.com/chatmail/relay/#custom-web-pages # path to www directory - documented here: https://chatmail.at/doc/relay/getting_started.html#custom-web-pages
#www_folder = www #www_folder = www
# #
@@ -99,6 +99,12 @@ acme_email =
# so use this option with caution on production servers. # 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
# #
# Privacy Policy # Privacy Policy

View File

@@ -20,7 +20,7 @@ def create_newemail_dict(config: Config):
secrets.choice(ALPHANUMERIC_PUNCT) secrets.choice(ALPHANUMERIC_PUNCT)
for _ in range(config.password_min_length + 3) for _ in range(config.password_min_length + 3)
) )
return dict(email=f"{user}@bloc7.icu", password=f"{password}") return dict(email=f"{user}@{config.mail_domain}", password=f"{password}")
def print_new_account(): def print_new_account():

View File

@@ -113,7 +113,7 @@ mail_attribute_dict = proxy:/run/chatmail-metadata/metadata.socket:metadata
# `imap_zlib` enables IMAP COMPRESS (RFC 4978). # `imap_zlib` enables IMAP COMPRESS (RFC 4978).
# <https://datatracker.ietf.org/doc/html/rfc4978.html> # <https://datatracker.ietf.org/doc/html/rfc4978.html>
protocol imap { protocol imap {
mail_plugins = $mail_plugins imap_zlib imap_quota last_login mail_plugins = $mail_plugins imap_quota last_login {% if config.imap_compress %}imap_zlib{% endif %}
imap_metadata = yes imap_metadata = yes
} }
@@ -252,3 +252,28 @@ protocol imap {
rawlog_dir = %h rawlog_dir = %h
} }
{% endif %} {% endif %}
{% if not config.imap_compress %}
# Hibernate IDLE users to save memory and CPU resources
# NOTE: this will have no effect if imap_zlib plugin is used
imap_hibernate_timeout = 30s
service imap {
# Note that this change will allow any process running as
# $default_internal_user (dovecot) to access mails as any other user.
# This may be insecure in some installations, which is why this isn't
# done by default.
unix_listener imap-master {
user = $default_internal_user
}
}
# The following is the default already in v2.3.1+:
service imap {
extra_groups = $default_internal_group
}
service imap-hibernate {
unix_listener imap-hibernate {
mode = 0660
group = $default_internal_group
}
}
{% endif %}

View File

@@ -37,7 +37,10 @@ def perform_initial_checks(mail_domain, pre_command=""):
return res return res
# parse out sts-id if exists, example: "v=STSv1; id=2090123" # parse out sts-id if exists, example: "v=STSv1; id=2090123"
parts = query_dns("TXT", f"_mta-sts.{mail_domain}").split("id=") mta_sts_txt = query_dns("TXT", f"_mta-sts.{mail_domain}")
if not mta_sts_txt:
return res
parts = mta_sts_txt.split("id=")
res["sts_id"] = parts[1].rstrip('"') if len(parts) == 2 else "" res["sts_id"] = parts[1].rstrip('"') if len(parts) == 2 else ""
return res return res

View File

@@ -1,5 +1,5 @@
import datetime import datetime
import os #import os
import smtplib import smtplib
import socket import socket
import subprocess import subprocess
@@ -8,7 +8,7 @@ import time
import pytest import pytest
from cmdeploy import remote from cmdeploy import remote
from cmdeploy.cmdeploy import main #from cmdeploy.cmdeploy import main
from cmdeploy.sshexec import SSHExec from cmdeploy.sshexec import SSHExec
@@ -70,44 +70,44 @@ class TestSSHExecutor:
assert (now - since_date).total_seconds() < 60 * 60 * 51 assert (now - since_date).total_seconds() < 60 * 60 * 51
def test_status_cmd(chatmail_config, capsys, request): #def test_status_cmd(chatmail_config, capsys, request):
os.chdir(request.config.invocation_params.dir) # os.chdir(request.config.invocation_params.dir)
assert main(["status"]) == 0 # assert main(["status"]) == 0
status_out = capsys.readouterr() # status_out = capsys.readouterr()
print(status_out.out) # print(status_out.out)
#
services = [ # services = [
"acmetool-redirector", # "acmetool-redirector",
"chatmail-metadata", # "chatmail-metadata",
"doveauth", # "doveauth",
"dovecot", # "dovecot",
"fcgiwrap", # "fcgiwrap",
"filtermail-incoming", # "filtermail-incoming",
"filtermail", # "filtermail",
"lastlogin", # "lastlogin",
"nginx", # "nginx",
"opendkim", # "opendkim",
"postfix@-", # "postfix@-",
"systemd-journald", # "systemd-journald",
"turnserver", # "turnserver",
"unbound", # "unbound",
] # ]
not_running = [] # not_running = []
for service in services: # for service in services:
active = False # active = False
for line in status_out: # for line in status_out:
if service in line: # if service in line:
active = True # active = True
if not "loaded" in line: # if not "loaded" in line:
active = False # active = False
if not "active" in line: # if not "active" in line:
active = False # active = False
if not "running" in line: # if not "running" in line:
active = False # active = False
break # break
if not active: # if not active:
not_running.append(service) # not_running.append(service)
assert not_running == [] # assert not_running == []
def test_timezone_env(remote): def test_timezone_env(remote):