993: Make aliases case-insensitive (too) r=mergify[bot] a=Nebukadneza

Even though RFC5321 2.4 explains that local-parts are to be case-sensitive,
this does not seem to be how EMail is used today. Thus, instead of reverting
user-emails back to being case sensitive, let’s make aliases case-insensitive
too. Not only more consistent, this also allows users to enjoy receiving EMails
from large airlines or car-rental agencies onto their already existing aliases.

For the rare case of case sensitive aliases existing, let’s query for the
forced-lowercase alias only in the event that the preserved-case one isn’t
found …

closes #867

## What type of PR?
bug-fix

## What does this PR do?
Make aliases optionally case-insensitive: After attempting to resolve an alias in its preserved case, also attempt to match it case-insensitively.

This followed after some more thought from  #868 …

### Related issue(s)
closes #867

## Prerequistes
Before we can consider review and merge, please make sure the following list is done and checked.
If an entry in not applicable, you can check it or remove it from the list.

- [x] In case of feature or enhancement: documentation updated accordingly
- [x] Unless it's docs or a minor change: add [changelog](https://mailu.io/master/contributors/guide.html#changelog) entry file.


Co-authored-by: Dario Ernst <dario@kanojo.de>
master
bors[bot] 5 years ago
commit 7021278bfb

@ -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.

@ -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
Loading…
Cancel
Save