summaryrefslogtreecommitdiff
path: root/odoo/tools/mail.py
diff options
context:
space:
mode:
Diffstat (limited to 'odoo/tools/mail.py')
-rw-r--r--odoo/tools/mail.py32
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}"