diff --git a/core/admin/mailu/internal/views/postfix.py b/core/admin/mailu/internal/views/postfix.py index 3482b290..f8346bb1 100644 --- a/core/admin/mailu/internal/views/postfix.py +++ b/core/admin/mailu/internal/views/postfix.py @@ -33,8 +33,9 @@ def postfix_alias_map(alias): localpart, domain_name = models.Email.resolve_domain(alias) if localpart is None: return flask.jsonify(domain_name) - destination = models.Email.resolve_destination(localpart, domain_name) - return flask.jsonify(",".join(destination)) if destination else flask.abort(404) + if destinations := models.Email.resolve_destination(localpart, domain_name): + return flask.jsonify(",".join(idna_encode(destinations))) + return flask.abort(404) @internal.route("/postfix/transport/") def postfix_transport(email): @@ -142,9 +143,11 @@ def postfix_sender_login(sender): if localpart is None: return flask.jsonify(",".join(wildcard_senders)) if wildcard_senders else flask.abort(404) localpart = localpart[:next((i for i, ch in enumerate(localpart) if ch in flask.current_app.config.get('RECIPIENT_DELIMITER')), None)] - destination = models.Email.resolve_destination(localpart, domain_name, True) - destination = [*destination, *wildcard_senders] if destination else [*wildcard_senders] - return flask.jsonify(",".join(destination)) if destination else flask.abort(404) + destinations = models.Email.resolve_destination(localpart, domain_name, True) or [] + destinations.extend(wildcard_senders) + if destinations: + return flask.jsonify(",".join(idna_encode(destinations))) + return flask.abort(404) @internal.route("/postfix/sender/rate/") def postfix_sender_rate(sender): @@ -169,3 +172,11 @@ def postfix_sender_access(sender): except sqlalchemy.exc.StatementError: pass return flask.abort(404) + +# idna encode domain part of each address in list of addresses +def idna_encode(addresses): + return [ + f"{localpart}@{idna.encode(domain).decode('ascii')}" + for (localpart, domain) in + (address.rsplit("@", 1) for address in addresses) + ]