diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 8bfb12fb..95dc16a6 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -436,20 +436,37 @@ class Alias(Base, Email): @classmethod def resolve(cls, localpart, domain_name): - return cls.query.filter( - sqlalchemy.and_(cls.domain_name == domain_name, - sqlalchemy.or_( - sqlalchemy.and_( - cls.wildcard == False, - cls.localpart == localpart - ), sqlalchemy.and_( - cls.wildcard == True, - sqlalchemy.bindparam("l", localpart).like(cls.localpart) + alias_preserve_case = cls.query.filter( + sqlalchemy.and_(cls.domain_name == domain_name, + sqlalchemy.or_( + sqlalchemy.and_( + cls.wildcard == False, + cls.localpart == localpart + ), sqlalchemy.and_( + cls.wildcard == True, + sqlalchemy.bindparam("l", localpart).like(cls.localpart) + ) ) ) - ) - ).order_by(cls.wildcard, sqlalchemy.func.char_length(cls.localpart).desc()).first() + ).order_by(cls.wildcard, sqlalchemy.func.char_length(cls.localpart).desc()).first() + if alias_preserve_case: + return alias_preserve_case + if localpart: + localpart = localpart.lower() + return cls.query.filter( + sqlalchemy.and_(cls.domain_name == domain_name, + sqlalchemy.or_( + sqlalchemy.and_( + cls.wildcard == False, + sqlalchemy.func.lower(cls.localpart) == localpart + ), sqlalchemy.and_( + cls.wildcard == True, + sqlalchemy.bindparam("l", localpart).like(sqlalchemy.func.lower(cls.localpart)) + ) + ) + ) + ).order_by(cls.wildcard, sqlalchemy.func.char_length(sqlalchemy.func.lower(cls.localpart)).desc()).first() class Token(Base): """ A token is an application password for a given user. diff --git a/towncrier/newsfragments/867.bugfix b/towncrier/newsfragments/867.bugfix new file mode 100644 index 00000000..ef9b04a7 --- /dev/null +++ b/towncrier/newsfragments/867.bugfix @@ -0,0 +1 @@ +Make aliases optionally case-insensitive: After attempting to resolve an alias in its preserved case, also attempt to match it case-insensitively