diff options
Diffstat (limited to 'odoo/tools/mail.py')
| -rw-r--r-- | odoo/tools/mail.py | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/odoo/tools/mail.py b/odoo/tools/mail.py index c1a14e964fc..1a3e9d80b9f 100644 --- a/odoo/tools/mail.py +++ b/odoo/tools/mail.py @@ -14,6 +14,7 @@ import time from email.utils import getaddresses from lxml import etree from werkzeug import urls +import idna import odoo from odoo.loglevels import ustr @@ -546,13 +547,15 @@ def decode_message_header(message, header, separator=' '): def formataddr(pair, charset='utf-8'): """Pretty format a 2-tuple of the form (realname, email_address). - Set the charset to ascii to get a RFC-2822 compliant email. - - The email address is considered valid and is left unmodified. - If the first element of pair is falsy then only the email address is returned. + Set the charset to ascii to get a RFC-2822 compliant email. The + realname will be base64 encoded (if necessary) and the domain part + of the email will be punycode encoded (if necessary). The local part + is left unchanged thus require the SMTPUTF8 extension when there are + non-ascii characters. + >>> formataddr(('John Doe', 'johndoe@example.com')) '"John Doe" <johndoe@example.com>' @@ -560,21 +563,26 @@ def formataddr(pair, charset='utf-8'): 'johndoe@example.com' """ name, address = pair - address.encode('ascii') + local, _, domain = address.rpartition('@') + + try: + domain.encode(charset) + except UnicodeEncodeError: + # rfc5890 - Internationalized Domain Names for Applications (IDNA) + domain = idna.encode(domain).decode('ascii') + if name: try: name.encode(charset) except UnicodeEncodeError: # charset mismatch, encode as utf-8/base64 # rfc2047 - MIME Message Header Extensions for Non-ASCII Text - return "=?utf-8?b?{name}?= <{addr}>".format( - name=base64.b64encode(name.encode('utf-8')).decode('ascii'), - addr=address) + name = base64.b64encode(name.encode('utf-8')).decode('ascii') + return f"=?utf-8?b?{name}?= <{local}@{domain}>" else: # ascii name, escape it if needed # rfc2822 - Internet Message Format # #section-3.4 - Address Specification - return '"{name}" <{addr}>'.format( - name=email_addr_escapes_re.sub(r'\\\g<0>', name), - addr=address) - return address + name = email_addr_escapes_re.sub(r'\\\g<0>', name) + return f'"{name}" <{local}@{domain}>' + return f"{local}@{domain}" |
