From 3e19f85fadf41a600678f21bad1562647a961809 Mon Sep 17 00:00:00 2001 From: Joshua Tauberer Date: Sat, 18 Sep 2021 19:26:31 -0400 Subject: [PATCH] Add domain maps from Unicode forms of internationalized domains to their ASCII forms When an email is received by Postfix using SMTPUTF8 and the recipient domain is a Unicode internationalized domain, it was failing to be delivered (bouncing with 'relay access denied') because our users and aliases tables only store ASCII (IDNA) forms of internationalized domains. In this commit, domain maps are added to the auto_aliases table from the Unicode form of each mail domain to its IDNA form, if those forms are different. The Postfix domains query is updated to look at the auto_aliases table now as well, since it is the only table with Unicode forms of the mail domains. However, mail delivery is still not working since the Dovecot LMTP server does not support SMTPUTF8, and mail still bounces but with an error that SMTPUTF8 is not supported. --- management/mailconfig.py | 16 ++++++++++++++-- setup/mail-users.sh | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/management/mailconfig.py b/management/mailconfig.py index 04a4c8b..0c58747 100755 --- a/management/mailconfig.py +++ b/management/mailconfig.py @@ -218,6 +218,9 @@ def get_mail_aliases_ex(env): domains = {} for address, forwards_to, permitted_senders, auto in get_mail_aliases(env): + # skip auto domain maps since these are not informative in the control panel's aliases list + if auto and address.startswith("@"): continue + # get alias info domain = get_domain(address) @@ -259,11 +262,12 @@ def get_domain(emailaddr, as_unicode=True): def get_mail_domains(env, filter_aliases=lambda alias : True, users_only=False): # Returns the domain names (IDNA-encoded) of all of the email addresses # configured on the system. If users_only is True, only return domains - # with email addresses that correspond to user accounts. + # with email addresses that correspond to user accounts. Exclude Unicode + # forms of domain names listed in the automatic aliases table. domains = [] domains.extend([get_domain(login, as_unicode=False) for login in get_mail_users(env)]) if not users_only: - domains.extend([get_domain(address, as_unicode=False) for address, *_ in get_mail_aliases(env) if filter_aliases(address) ]) + domains.extend([get_domain(address, as_unicode=False) for address, _, _, auto in get_mail_aliases(env) if filter_aliases(address) and not auto ]) return set(domains) def add_mail_user(email, pw, privs, env): @@ -569,6 +573,14 @@ def kick(env, mail_result=None): if alias == administrator: continue # don't make an alias from the administrator to itself --- this alias must be created manually auto_aliases[alias] = administrator + # Add domain maps from Unicode forms of IDNA domains to the ASCII forms stored in the alias table. + for domain in get_mail_domains(env): + try: + domain_unicode = idna.decode(domain.encode("ascii")) + if domain == domain_unicode: continue # not an IDNA/Unicode domain + auto_aliases["@" + domain_unicode] = "@" + domain + except (ValueError, UnicodeError, idna.IDNAError): + continue add_auto_aliases(auto_aliases, env) diff --git a/setup/mail-users.sh b/setup/mail-users.sh index efa5cac..c0320e7 100755 --- a/setup/mail-users.sh +++ b/setup/mail-users.sh @@ -111,7 +111,7 @@ tools/editconf.py /etc/postfix/main.cf \ # SQL statement to check if we handle incoming mail for a domain, either for users or aliases. cat > /etc/postfix/virtual-mailbox-domains.cf << EOF; dbpath=$db_path -query = SELECT 1 FROM users WHERE email LIKE '%%@%s' UNION SELECT 1 FROM aliases WHERE source LIKE '%%@%s' +query = SELECT 1 FROM users WHERE email LIKE '%%@%s' UNION SELECT 1 FROM aliases WHERE source LIKE '%%@%s' UNION SELECT 1 FROM auto_aliases WHERE source LIKE '%%@%s' EOF # SQL statement to check if we handle incoming mail for a user.