fix: Fix email sender/recipients decoding

This commit is contained in:
Corentin Forler 2025-03-24 12:04:05 +01:00
parent 5948a4d941
commit 154aff9e98
No known key found for this signature in database
3 changed files with 52 additions and 5 deletions

View file

@ -127,7 +127,7 @@ class EMail:
recipients = split_emails(recipients)
# remove null
recipients = filter(None, (strip(r) for r in recipients))
recipients = list(filter(None, (strip(r) for r in recipients)))
self.sender = sender
self.reply_to = reply_to or sender

View file

@ -448,7 +448,7 @@ class Email:
def decode_email(email: bytes | str | None) -> str | None:
if not email:
return
email = frappe.as_unicode(email).replace('"', " ").replace("'", " ")
email = frappe.as_unicode(email)
try:
parts = decode_header(email)
except HeaderParseError:
@ -899,8 +899,8 @@ class InboundMail(Email):
"sent_or_received": "Received",
"sender_full_name": self.from_real_name,
"sender": self.from_email,
"recipients": self.mail.get("To"),
"cc": self.mail.get("CC"),
"recipients": self.decode_email(self.mail.get("To") or ""),
"cc": self.decode_email(self.mail.get("CC") or ""),
"email_account": self.email_account.name,
"communication_medium": "Email",
"uid": self.uid,

View file

@ -6,6 +6,7 @@ import os
import frappe
from frappe import safe_decode
from frappe.core.doctype.communication.communication import Communication
from frappe.email.doctype.email_queue.email_queue import QueueBuilder, SendMailContext
from frappe.email.email_body import (
get_email,
@ -13,7 +14,7 @@ from frappe.email.email_body import (
inline_style_in_html,
replace_filename_with_cid,
)
from frappe.email.receive import Email
from frappe.email.receive import Email, InboundMail
from frappe.tests import IntegrationTestCase
@ -205,6 +206,52 @@ Reply-To: test2_@erpnext.com
mail = Email.decode_email(" =?UTF-8?B?X\xe0\xe0Y?= <xy@example.com>")
self.assertIn("xy@example.com", mail)
def test_quotes_in_email_sender(self):
content_bytes = rb"""MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
To: "\"fail@example.com\" via ABC" <success@example.com>
From: "\"fail@example.com\" via DEF" <success@example.com>
Reply-To: "\"fail@example.com\" via GHI" <success@example.com>
CC: "\"fail@example.com\" via JKL" <success@example.com>
"""
mail = Email(content_bytes)
self.assertEqual(mail.from_email, "success@example.com")
self.assertEqual(mail.from_real_name, "failexamplecom via DEF")
# https://github.com/frappe/frappe/pull/3371
# self.assertEqual(mail.from_real_name, '"fail@example.com" via DEF')
email_account = frappe._dict({"email_id": "receive@example.com"})
mail = InboundMail(content_bytes, email_account)
communication: Communication = mail.process() # type: ignore
self.assertEqual(communication.sender_full_name, "failexamplecom via DEF")
def test_quotes_in_email_recipients(self):
content_bytes = rb"""MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
From: "=?utf-8?Q?=F0=9F=98=83?="
=?utf-8?Q?=3Ctest=40ex?= =?utf-8?Q?ample=2Eco?= =?utf-8?Q?m=3E?=
To: =?iso-8859-1?Q?X=E9Y=40example=2Ecom?= <xy@example.com>, "fail@example.com" <success@example.com>
"""
# https://ldu2.github.io/rfc2047/
email_account = frappe._dict({"email_id": "receive@example.com"})
mail = InboundMail(content_bytes, email_account)
communication: Communication = mail.process() # type: ignore
self.assertEqual(communication.sender_mailid, "test@example.com")
# self.assertEqual(communication.sender_full_name, "😃")
# # TODO: Fix get_name_from_email_string to accept non-ASCII chars
self.assertEqual(
communication.recipients,
'XéY@example.com <xy@example.com>, "fail@example.com" <success@example.com>',
)
frappe.db.rollback()
def fixed_column_width(string, chunk_size):
parts = [string[0 + i : chunk_size + i] for i in range(0, len(string), chunk_size)]