mirror of
https://github.com/Mailu/Mailu.git
synced 2025-01-18 03:21:36 +02:00
Add another type decorator for idna email support
This commit is contained in:
parent
792c720c13
commit
93d5254b3f
@ -14,12 +14,13 @@ import smtplib
|
||||
import idna
|
||||
|
||||
|
||||
class Idna(db.TypeDecorator):
|
||||
class IdnaDomain(db.TypeDecorator):
|
||||
""" Stores a Unicode string in it's IDNA representation (ASCII only)
|
||||
"""
|
||||
|
||||
impl = db.String
|
||||
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
return idna.encode(value)
|
||||
|
||||
@ -27,10 +28,36 @@ class Idna(db.TypeDecorator):
|
||||
return idna.decode(value)
|
||||
|
||||
|
||||
class IdnaEmail(db.TypeDecorator):
|
||||
""" Stores a Unicode string in it's IDNA representation (ASCII only)
|
||||
"""
|
||||
|
||||
impl = db.String
|
||||
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
localpart, domain_name = value.split('@')
|
||||
|
||||
email = "{0}@{1}".format(
|
||||
localpart,
|
||||
idna.encode(domain_name).decode('ascii'),
|
||||
)
|
||||
return email
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
localpart, domain_name = value.split('@')
|
||||
|
||||
email = "{0}@{1}".format(
|
||||
localpart,
|
||||
idna.decode(domain_name),
|
||||
)
|
||||
return email
|
||||
|
||||
|
||||
# Many-to-many association table for domain managers
|
||||
managers = db.Table('manager',
|
||||
db.Column('domain_name', Idna, db.ForeignKey('domain.name')),
|
||||
db.Column('user_email', db.String(255), db.ForeignKey('user.email'))
|
||||
db.Column('domain_name', IdnaDomain, db.ForeignKey('domain.name')),
|
||||
db.Column('user_email', IdnaEmail, db.ForeignKey('user.email'))
|
||||
)
|
||||
|
||||
|
||||
@ -40,6 +67,7 @@ class CommaSeparatedList(db.TypeDecorator):
|
||||
|
||||
impl = db.String
|
||||
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if type(value) is not list:
|
||||
raise TypeError("Shoud be a list")
|
||||
@ -68,7 +96,7 @@ class Domain(Base):
|
||||
"""
|
||||
__tablename__ = "domain"
|
||||
|
||||
name = db.Column(Idna, primary_key=True, nullable=False)
|
||||
name = db.Column(IdnaDomain, primary_key=True, nullable=False)
|
||||
managers = db.relationship('User', secondary=managers,
|
||||
backref=db.backref('manager_of'), lazy='dynamic')
|
||||
max_users = db.Column(db.Integer, nullable=False, default=0)
|
||||
@ -124,8 +152,8 @@ class Alternative(Base):
|
||||
|
||||
__tablename__ = "alternative"
|
||||
|
||||
name = db.Column(Idna, primary_key=True, nullable=False)
|
||||
domain_name = db.Column(Idna, db.ForeignKey(Domain.name))
|
||||
name = db.Column(IdnaDomain, primary_key=True, nullable=False)
|
||||
domain_name = db.Column(IdnaDomain, db.ForeignKey(Domain.name))
|
||||
domain = db.relationship(Domain,
|
||||
backref=db.backref('alternatives', cascade='all, delete-orphan'))
|
||||
|
||||
@ -155,19 +183,19 @@ class Email(object):
|
||||
|
||||
@declarative.declared_attr
|
||||
def domain_name(cls):
|
||||
return db.Column(Idna, db.ForeignKey(Domain.name),
|
||||
nullable=False)
|
||||
return db.Column(IdnaDomain, db.ForeignKey(Domain.name),
|
||||
nullable=False, default=IdnaDomain)
|
||||
|
||||
# This field is redundant with both localpart and domain name.
|
||||
# It is however very useful for quick lookups without joining tables,
|
||||
# especially when the mail server il reading the database.
|
||||
# especially when the mail server is reading the database.
|
||||
@declarative.declared_attr
|
||||
def email(cls):
|
||||
updater = lambda context: "{0}@{1}".format(
|
||||
context.current_parameters["localpart"],
|
||||
idna.encode(context.current_parameters["domain_name"]).decode('ascii'),
|
||||
context.current_parameters["domain_name"],
|
||||
)
|
||||
return db.Column(db.String(255, collation="NOCASE"),
|
||||
return db.Column(IdnaEmail,
|
||||
primary_key=True, nullable=False,
|
||||
default=updater)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user