Initial import from Docker volume
This commit is contained in:
121
tools/email_.py
Executable file
121
tools/email_.py
Executable file
@@ -0,0 +1,121 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
import re
|
||||
from email.charset import Charset
|
||||
from email.utils import formataddr, parseaddr
|
||||
|
||||
from trytond.pool import Pool
|
||||
|
||||
__all__ = [
|
||||
'set_from_header', 'validate_email', 'normalize_email',
|
||||
'convert_ascii_email', 'EmailNotValidError']
|
||||
|
||||
|
||||
def _domainaddr(address):
|
||||
_, email = parseaddr(address)
|
||||
if '@' in email:
|
||||
return email.split('@', 1)[1]
|
||||
|
||||
|
||||
def set_from_header(message, sender, from_):
|
||||
"Fill email headers to appear at best from the address"
|
||||
if parseaddr(sender)[1] != parseaddr(from_)[1]:
|
||||
if _domainaddr(sender) == _domainaddr(from_):
|
||||
message['From'] = from_
|
||||
message['Sender'] = sender
|
||||
else:
|
||||
message['From'] = sender
|
||||
message['On-Behalf-Of'] = from_
|
||||
message['Reply-To'] = from_
|
||||
else:
|
||||
message['From'] = from_
|
||||
|
||||
|
||||
def has_rcpt(msg):
|
||||
return any((msg['To'], msg['Cc'], msg['Bcc']))
|
||||
|
||||
|
||||
try:
|
||||
from dns.exception import DNSException
|
||||
from email_validator import EmailNotValidError, caching_resolver
|
||||
from email_validator import validate_email as _validate_email
|
||||
|
||||
try:
|
||||
resolver = caching_resolver()
|
||||
except DNSException:
|
||||
if Pool.test:
|
||||
resolver = None
|
||||
else:
|
||||
raise
|
||||
|
||||
def validate_email(email):
|
||||
emailinfo = _validate_email(
|
||||
email, check_deliverability=True,
|
||||
dns_resolver=resolver,
|
||||
test_environment=Pool.test)
|
||||
return emailinfo.normalized
|
||||
|
||||
def normalize_email(email):
|
||||
try:
|
||||
emailinfo = _validate_email(
|
||||
email, check_deliverability=False,
|
||||
test_environment=Pool.test)
|
||||
return emailinfo.normalized
|
||||
except EmailNotValidError:
|
||||
return email
|
||||
|
||||
def convert_ascii_email(email):
|
||||
try:
|
||||
emailinfo = _validate_email(
|
||||
email, check_deliverability=False,
|
||||
test_environment=Pool.test)
|
||||
return emailinfo.ascii_email or emailinfo.normalized
|
||||
except EmailNotValidError:
|
||||
return email
|
||||
|
||||
except ImportError:
|
||||
|
||||
def validate_email(email):
|
||||
return email
|
||||
|
||||
def normalize_email(email):
|
||||
return email
|
||||
|
||||
def convert_ascii_email(email):
|
||||
return email
|
||||
|
||||
class EmailNotValidError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
# Copy of email.utils.formataddr but without the ASCII enforcement
|
||||
specialsre = re.compile(r'[][\\()<>@,:;".]')
|
||||
escapesre = re.compile(r'[\\"]')
|
||||
|
||||
|
||||
def _formataddr(pair, charset='utf-8'):
|
||||
name, address = pair
|
||||
if name:
|
||||
try:
|
||||
name.encode('ascii')
|
||||
except UnicodeEncodeError:
|
||||
if isinstance(charset, str):
|
||||
charset = Charset(charset)
|
||||
encoded_name = charset.header_encode(name)
|
||||
return "%s <%s>" % (encoded_name, address)
|
||||
else:
|
||||
quotes = ''
|
||||
if specialsre.search(name):
|
||||
quotes = '"'
|
||||
name = escapesre.sub(r'\\\g<0>', name)
|
||||
return '%s%s%s <%s>' % (quotes, name, quotes, address)
|
||||
return address
|
||||
|
||||
|
||||
def format_address(email, name=None):
|
||||
pair = (name, convert_ascii_email(email))
|
||||
try:
|
||||
return formataddr(pair)
|
||||
except UnicodeEncodeError:
|
||||
return _formataddr(pair)
|
||||
Reference in New Issue
Block a user