diff --git a/app/email_utils.py b/app/email_utils.py index 3aacee85..ecb66208 100644 --- a/app/email_utils.py +++ b/app/email_utils.py @@ -1,4 +1,5 @@ import os +from email.header import decode_header from email.message import Message from email.mime.base import MIMEBase from email.mime.multipart import MIMEMultipart @@ -432,3 +433,18 @@ def get_spam_info(msg: Message) -> (bool, str): spamassassin_answer = spamassassin_status[: spamassassin_status.find(",")] return spamassassin_answer.lower() == "yes", spamassassin_status + + +def parseaddr_unicode(addr) -> (str, str): + """Like parseaddr but return name in unicode instead of in RFC 2047 format + '=?UTF-8?B?TmjGoW4gTmd1eeG7hW4=?= ' -> ('Nhơn Nguyễn', "abcd@gmail.com") + """ + name, email = parseaddr(addr) + email = email.lower() + if name: + decoded_string, charset = decode_header(name)[0] + if charset is not None: + return decoded_string.decode(charset), email + else: + return decoded_string, email + diff --git a/tests/test_email_utils.py b/tests/test_email_utils.py index fe013150..ccf0ee64 100644 --- a/tests/test_email_utils.py +++ b/tests/test_email_utils.py @@ -6,7 +6,7 @@ from app.email_utils import ( can_be_used_as_personal_email, delete_header, add_or_replace_header, -) + parseaddr_unicode) from app.extensions import db from app.models import User, CustomDomain @@ -61,3 +61,17 @@ def test_add_or_replace_header(): add_or_replace_header(msg, "H", "new") assert msg._headers == [("H", "new")] + + +def test_parseaddr_unicode(): + # ascii address + assert parseaddr_unicode("First Last ") == ("First Last", "abcd@gmail.com") + + # Handle quote + assert parseaddr_unicode('"First Last" ') == ("First Last", "abcd@gmail.com") + + # UTF-8 charset + assert parseaddr_unicode("=?UTF-8?B?TmjGoW4gTmd1eeG7hW4=?= ") == ('Nhơn Nguyễn', "abcd@gmail.com") + + # iso-8859-1 charset + assert parseaddr_unicode("=?iso-8859-1?q?p=F6stal?= ") == ('pöstal', "abcd@gmail.com")