mirror of
https://github.com/chatmail/relay.git
synced 2026-05-14 09:54:38 +00:00
retain "config.mail_domain" as the domain part of @ email addresses, so for ipv4 relays "[1.2.3.4]" and introduce config.ipv4_relay and config.mail_domain_bare helpers.
This commit is contained in:
@@ -13,7 +13,7 @@ import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pyinfra
|
||||
from chatmaild.config import read_config, write_initial_config, is_valid_ipv4
|
||||
from chatmaild.config import read_config, write_initial_config
|
||||
from packaging import version
|
||||
from termcolor import colored
|
||||
|
||||
@@ -87,11 +87,11 @@ def run_cmd_options(parser):
|
||||
def run_cmd(args, out):
|
||||
"""Deploy chatmail services on the remote server."""
|
||||
|
||||
ssh_host = args.ssh_host if args.ssh_host else args.config.mail_domain
|
||||
ssh_host = args.ssh_host if args.ssh_host else args.config.mail_domain_bare
|
||||
sshexec = get_sshexec(ssh_host)
|
||||
require_iroh = args.config.enable_iroh_relay
|
||||
strict_tls = args.config.tls_cert_mode == "acme"
|
||||
if is_valid_ipv4(args.config.mail_domain):
|
||||
if args.config.ipv4_relay:
|
||||
args.dns_check_disabled = True
|
||||
if not args.dns_check_disabled:
|
||||
remote_data = dns.get_initial_remote_data(sshexec, args.config.mail_domain)
|
||||
@@ -121,7 +121,7 @@ def run_cmd(args, out):
|
||||
elif not args.dns_check_disabled and strict_tls and not remote_data["acme_account_url"]:
|
||||
out.red("Deploy completed but letsencrypt not configured")
|
||||
out.red("Run 'cmdeploy run' again")
|
||||
elif is_valid_ipv4(args.config.mail_domain):
|
||||
elif args.config.ipv4_relay:
|
||||
out.green("Deploy completed.")
|
||||
else:
|
||||
out.green("Deploy completed, call `cmdeploy dns` next.")
|
||||
@@ -144,8 +144,9 @@ def dns_cmd_options(parser):
|
||||
|
||||
def dns_cmd(args, out):
|
||||
"""Check DNS entries and optionally generate dns zone file."""
|
||||
if is_valid_ipv4(args.config.mail_domain):
|
||||
print(f"[WARNING] {args.config.mail_domain} is not a domain, skipping DNS checks.")
|
||||
if args.config.ipv4_relay:
|
||||
ipv4 = args.config.ipv4_relay
|
||||
print(f"[WARNING] {ipv4} is not a domain, skipping DNS checks.")
|
||||
return 0
|
||||
ssh_host = args.ssh_host if args.ssh_host else args.config.mail_domain
|
||||
sshexec = get_sshexec(ssh_host, verbose=args.verbose)
|
||||
@@ -184,7 +185,7 @@ def status_cmd_options(parser):
|
||||
def status_cmd(args, out):
|
||||
"""Display status for online chatmail instance."""
|
||||
|
||||
ssh_host = args.ssh_host if args.ssh_host else args.config.mail_domain
|
||||
ssh_host = args.ssh_host if args.ssh_host else args.config.mail_domain_bare
|
||||
sshexec = get_sshexec(ssh_host, verbose=args.verbose)
|
||||
|
||||
out.green(f"chatmail domain: {args.config.mail_domain}")
|
||||
|
||||
@@ -370,7 +370,7 @@ class ChatmailVenvDeployer(Deployer):
|
||||
|
||||
def configure(self):
|
||||
_configure_remote_venv_with_chatmaild(self, self.config)
|
||||
configure_remote_units(self, self.config.mail_domain, self.units)
|
||||
configure_remote_units(self, self.config.mail_domain_bare, self.units)
|
||||
|
||||
def activate(self):
|
||||
activate_remote_units(self, self.units)
|
||||
@@ -384,7 +384,7 @@ class ChatmailDeployer(Deployer):
|
||||
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
self.mail_domain_deliverable = config.mail_domain_deliverable
|
||||
self.mail_domain = config.mail_domain
|
||||
|
||||
def install(self):
|
||||
self.put_file(
|
||||
@@ -417,7 +417,7 @@ class ChatmailDeployer(Deployer):
|
||||
server.shell(
|
||||
name="Setup /etc/mailname",
|
||||
commands=[
|
||||
f"echo {self.mail_domain_deliverable} >/etc/mailname; chmod 644 /etc/mailname"
|
||||
f"echo {self.mail_domain} >/etc/mailname; chmod 644 /etc/mailname"
|
||||
],
|
||||
)
|
||||
|
||||
@@ -469,8 +469,7 @@ def deploy_chatmail(config_path: Path, disable_mail: bool, website_only: bool) -
|
||||
"""
|
||||
config = read_config(config_path)
|
||||
check_config(config)
|
||||
mail_domain = config.mail_domain
|
||||
mail_domain_deliverable = config.mail_domain_deliverable
|
||||
bare_host = config.mail_domain_bare
|
||||
|
||||
if website_only:
|
||||
Deployment().perform_stages([WebsiteDeployer(config)])
|
||||
@@ -527,7 +526,7 @@ def deploy_chatmail(config_path: Path, disable_mail: bool, website_only: bool) -
|
||||
)
|
||||
exit(1)
|
||||
|
||||
tls_deployer = get_tls_deployer(config, mail_domain)
|
||||
tls_deployer = get_tls_deployer(config, bare_host)
|
||||
|
||||
all_deployers = [
|
||||
ChatmailDeployer(config),
|
||||
@@ -535,13 +534,13 @@ def deploy_chatmail(config_path: Path, disable_mail: bool, website_only: bool) -
|
||||
FiltermailDeployer(),
|
||||
JournaldDeployer(),
|
||||
UnboundDeployer(config),
|
||||
TurnDeployer(mail_domain),
|
||||
TurnDeployer(bare_host),
|
||||
IrohDeployer(config.enable_iroh_relay),
|
||||
tls_deployer,
|
||||
WebsiteDeployer(config),
|
||||
ChatmailVenvDeployer(config),
|
||||
MtastsDeployer(),
|
||||
OpendkimDeployer(mail_domain_deliverable),
|
||||
OpendkimDeployer(config.mail_domain),
|
||||
# Dovecot should be started before Postfix
|
||||
# because it creates authentication socket
|
||||
# required by Postfix.
|
||||
|
||||
@@ -68,7 +68,7 @@ class DovecotDeployer(Deployer):
|
||||
)
|
||||
|
||||
def configure(self):
|
||||
configure_remote_units(self, self.config.mail_domain, self.units)
|
||||
configure_remote_units(self, self.config.mail_domain_bare, self.units)
|
||||
_configure_dovecot(self, self.config)
|
||||
|
||||
def activate(self):
|
||||
|
||||
@@ -40,7 +40,7 @@ service imap {
|
||||
process_limit = 50000
|
||||
}
|
||||
|
||||
mail_server_admin = mailto:root@{{ config.mail_domain_deliverable }}
|
||||
mail_server_admin = mailto:root@{{ config.mail_domain }}
|
||||
mail_server_comment = Chatmail server
|
||||
|
||||
# `zlib` enables compressing messages stored in the maildir.
|
||||
|
||||
@@ -12,8 +12,8 @@ from cmdeploy.basedeploy import Deployer
|
||||
class OpendkimDeployer(Deployer):
|
||||
required_users = [("opendkim", None, ["opendkim"])]
|
||||
|
||||
def __init__(self, mail_domain_deliverable):
|
||||
self.mail_domain_deliverable = mail_domain_deliverable
|
||||
def __init__(self, mail_domain):
|
||||
self.mail_domain = mail_domain
|
||||
|
||||
def install(self):
|
||||
apt.packages(
|
||||
@@ -22,7 +22,7 @@ class OpendkimDeployer(Deployer):
|
||||
)
|
||||
|
||||
def configure(self):
|
||||
domain = self.mail_domain_deliverable
|
||||
domain = self.mail_domain
|
||||
dkim_selector = "opendkim"
|
||||
"""Configures OpenDKIM"""
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
myorigin = {{ config.mail_domain_deliverable }}
|
||||
myorigin = {{ config.mail_domain }}
|
||||
|
||||
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
|
||||
biff = no
|
||||
@@ -54,13 +54,13 @@ smtpd_tls_exclude_ciphers = aNULL, RC4, MD5, DES
|
||||
tls_preempt_cipherlist = yes
|
||||
|
||||
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
|
||||
myhostname = {{ config.mail_domain_hostname }}
|
||||
myhostname = {{ config.postfix_myhostname }}
|
||||
alias_maps = hash:/etc/aliases
|
||||
alias_database = hash:/etc/aliases
|
||||
|
||||
# When postfix receives mail for $mydestination,
|
||||
# it hands it over to dovecot via $local_transport.
|
||||
mydestination = {{ config.mail_domain_deliverable }}
|
||||
mydestination = {{ config.mail_domain }}
|
||||
local_transport = lmtp:unix:private/dovecot-lmtp
|
||||
# postfix doesn't check whether local users exist or not:
|
||||
local_recipient_maps =
|
||||
|
||||
@@ -81,7 +81,7 @@ filter unix - n n - - lmtp
|
||||
-o syslog_name=postfix/reinject
|
||||
-o milter_macro_daemon_name=ORIGINATING
|
||||
-o cleanup_service_name=authclean
|
||||
{% if config.mail_domain == config.mail_domain_deliverable %} -o smtpd_milters=unix:opendkim/opendkim.sock
|
||||
{% if not config.ipv4_relay %} -o smtpd_milters=unix:opendkim/opendkim.sock
|
||||
{% endif %}
|
||||
|
||||
# Local SMTP server for reinjecting incoming filtered mail
|
||||
|
||||
@@ -12,7 +12,7 @@ def test_init(tmp_path, maildomain):
|
||||
inipath = tmp_path.joinpath("chatmail.ini")
|
||||
main(["init", "--config", str(inipath), maildomain])
|
||||
config = read_config(inipath)
|
||||
assert config.mail_domain == maildomain
|
||||
assert config.mail_domain_bare == maildomain
|
||||
|
||||
|
||||
def test_capabilities(imap):
|
||||
@@ -89,14 +89,14 @@ def test_concurrent_logins_same_account(
|
||||
assert login_results.get()
|
||||
|
||||
|
||||
def test_no_vrfy(cmfactory, chatmail_config):
|
||||
def test_no_vrfy(cmfactory, chatmail_config, maildomain):
|
||||
ac = cmfactory.get_online_account()
|
||||
addr = ac.get_config("addr")
|
||||
|
||||
s = smtplib.SMTP(chatmail_config.mail_domain)
|
||||
s = smtplib.SMTP(maildomain)
|
||||
s.starttls()
|
||||
|
||||
s.putcmd("vrfy", f"wrongaddress@{chatmail_config.mail_domain_deliverable}")
|
||||
s.putcmd("vrfy", f"wrongaddress@{chatmail_config.mail_domain}")
|
||||
result = s.getreply()
|
||||
print(result)
|
||||
s.putcmd("vrfy", addr)
|
||||
|
||||
@@ -10,7 +10,7 @@ import time
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from chatmaild.config import read_config, format_deliverable_domain, is_valid_ipv4
|
||||
from chatmaild.config import read_config, format_mail_domain, is_valid_ipv4
|
||||
|
||||
|
||||
conftestdir = Path(__file__).parent
|
||||
@@ -59,12 +59,12 @@ def chatmail_config(pytestconfig):
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def maildomain(chatmail_config):
|
||||
return chatmail_config.mail_domain
|
||||
return chatmail_config.mail_domain_bare
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def maildomain_deliverable(maildomain):
|
||||
return format_deliverable_domain(maildomain)
|
||||
return format_mail_domain(maildomain)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
@@ -283,7 +283,7 @@ def gencreds(chatmail_config):
|
||||
next(count)
|
||||
|
||||
def gen(domain=None):
|
||||
domain = domain if domain else chatmail_config.mail_domain_deliverable
|
||||
domain = domain if domain else chatmail_config.mail_domain
|
||||
while 1:
|
||||
num = next(count)
|
||||
alphanumeric = "abcdefghijklmnopqrstuvwxyz1234567890"
|
||||
@@ -322,7 +322,7 @@ class ChatmailACFactory:
|
||||
|
||||
def _make_transport(self, domain):
|
||||
"""Build a transport config dict for the given domain."""
|
||||
domain_deliverable = format_deliverable_domain(domain)
|
||||
domain_deliverable = format_mail_domain(domain)
|
||||
addr, password = self.gencreds(domain_deliverable)
|
||||
transport = {
|
||||
"addr": addr,
|
||||
@@ -347,7 +347,7 @@ class ChatmailACFactory:
|
||||
accounts = []
|
||||
for _ in range(num):
|
||||
account = self.dc.add_account()
|
||||
domain_deliverable = format_deliverable_domain(domain)
|
||||
domain_deliverable = format_mail_domain(domain)
|
||||
addr, password = self.gencreds(domain_deliverable)
|
||||
if _is_ip(domain):
|
||||
# Use DCLOGIN scheme with explicit server hosts,
|
||||
|
||||
Reference in New Issue
Block a user