From 7829de986204b8b6dfe35003e2fdf771347304e8 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Tue, 1 Feb 2022 06:22:39 +0530 Subject: [PATCH 01/23] fix: auto creation of append to doctype ref while receiving mail --- .../doctype/email_account/email_account.py | 7 +++-- frappe/email/receive.py | 30 ++++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index a05e20da24..7374fe861a 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -463,11 +463,11 @@ class EmailAccount(Document): """ mails = [] - def process_mail(messages): + def process_mail(messages, append_to=None): for index, message in enumerate(messages.get("latest_messages", [])): uid = messages['uid_list'][index] if messages.get('uid_list') else None seen_status = 1 if messages.get('seen_status', {}).get(uid) == 'SEEN' else 0 - mails.append(InboundMail(message, self, uid, seen_status)) + mails.append(InboundMail(message, self, uid, append_to, seen_status)) if frappe.local.flags.in_test: return [InboundMail(msg, self) for msg in test_mails or []] @@ -484,7 +484,8 @@ class EmailAccount(Document): email_server.select_imap_folder(folder.folder_name) email_server.settings['uid_validity'] = folder.uidvalidity messages = email_server.get_messages(folder=folder.folder_name) or {} - process_mail(messages) + append_to = folder.append_to + process_mail(messages, append_to) else: # process the pop3 account messages = email_server.get_messages() or {} diff --git a/frappe/email/receive.py b/frappe/email/receive.py index dd64d0df80..16119ae25e 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -582,10 +582,11 @@ class Email: class InboundMail(Email): """Class representation of incoming mail along with mail handlers. """ - def __init__(self, content, email_account, uid=None, seen_status=None): + def __init__(self, content, email_account, uid=None, append_to=None, seen_status=None): super().__init__(content) self.email_account = email_account self.uid = uid or -1 + self.append_to = append_to or -1 self.seen_status = seen_status or 0 # System documents related to this mail @@ -623,15 +624,24 @@ class InboundMail(Email): if self.parent_communication(): data['in_reply_to'] = self.parent_communication().name - if self.reference_document(): - data['reference_doctype'] = self.reference_document().doctype - data['reference_name'] = self.reference_document().name - elif self.email_account.append_to and self.email_account.append_to != 'Communication': - reference_doc = self._create_reference_document(self.email_account.append_to) - if reference_doc: - data['reference_doctype'] = reference_doc.doctype - data['reference_name'] = reference_doc.name - data['is_first'] = True + if self.email_account.use_imap and self.append_to: + if self.append_to != 'Communication': + reference_doc = self._create_reference_document(self.append_to) + if reference_doc: + data['reference_doctype'] = reference_doc.doctype + data['reference_name'] = reference_doc.name + data['is_first'] = True + else: + if self.reference_document(): + data['reference_doctype'] = self.reference_document().doctype + data['reference_name'] = self.reference_document().name + elif self.email_account.append_to and self.email_account.append_to != 'Communication': + reference_doc = self._create_reference_document(self.email_account.append_to) + # TODO: here instead of using email_account.append_to, the imap_folder.append_to should be used + if reference_doc: + data['reference_doctype'] = reference_doc.doctype + data['reference_name'] = reference_doc.name + data['is_first'] = True if self.is_notification(): # Disable notifications for notification. From 57a6ee392a0fc94ac54188ffbf0f5943c7c859b0 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Tue, 1 Feb 2022 11:00:50 +0530 Subject: [PATCH 02/23] fix: append_to parameter order in InboundMail --- frappe/email/doctype/email_account/email_account.py | 2 +- frappe/email/receive.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 7374fe861a..ee230d33f0 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -467,7 +467,7 @@ class EmailAccount(Document): for index, message in enumerate(messages.get("latest_messages", [])): uid = messages['uid_list'][index] if messages.get('uid_list') else None seen_status = 1 if messages.get('seen_status', {}).get(uid) == 'SEEN' else 0 - mails.append(InboundMail(message, self, uid, append_to, seen_status)) + mails.append(InboundMail(message, self, uid, seen_status, append_to)) if frappe.local.flags.in_test: return [InboundMail(msg, self) for msg in test_mails or []] diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 16119ae25e..cc4ec23e4e 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -582,7 +582,7 @@ class Email: class InboundMail(Email): """Class representation of incoming mail along with mail handlers. """ - def __init__(self, content, email_account, uid=None, append_to=None, seen_status=None): + def __init__(self, content, email_account, uid=None, seen_status=None, append_to=None): super().__init__(content) self.email_account = email_account self.uid = uid or -1 From eb574ca9f1f39c54d96105a94e0e8a3a4a12964b Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Tue, 1 Feb 2022 19:01:41 +0530 Subject: [PATCH 03/23] feat: add filter for append_to wrt imap_folder --- frappe/email/doctype/email_account/email_account.py | 10 +++++----- frappe/email/receive.py | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index ee230d33f0..772173fcd2 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -481,11 +481,11 @@ class EmailAccount(Document): if self.use_imap: # process all given imap folder for folder in self.imap_folder: - email_server.select_imap_folder(folder.folder_name) - email_server.settings['uid_validity'] = folder.uidvalidity - messages = email_server.get_messages(folder=folder.folder_name) or {} - append_to = folder.append_to - process_mail(messages, append_to) + if email_server.select_imap_folder(folder.folder_name): + frappe.log_error(f'FOLDER NAME: {folder.folder_name} PRESENT') + email_server.settings['uid_validity'] = folder.uidvalidity + messages = email_server.get_messages(folder=f'"{folder.folder_name}"') or {} + process_mail(messages, folder.append_to) else: # process the pop3 account messages = email_server.get_messages() or {} diff --git a/frappe/email/receive.py b/frappe/email/receive.py index cc4ec23e4e..30dd146fa7 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -108,7 +108,8 @@ class EmailServer: raise def select_imap_folder(self, folder): - self.imap.select(folder) + res = self.imap.select(f'"{folder}"') + return res[0] == 'OK' # The folder exsits TODO: handle other resoponses too def logout(self): if cint(self.settings.use_imap): From 43ac81be5ddd00a4352a089d0571a1075595b521 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Tue, 1 Feb 2022 19:04:18 +0530 Subject: [PATCH 04/23] refactor: remove debug logs --- frappe/email/doctype/email_account/email_account.py | 1 - 1 file changed, 1 deletion(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 772173fcd2..1c53ae9faf 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -482,7 +482,6 @@ class EmailAccount(Document): # process all given imap folder for folder in self.imap_folder: if email_server.select_imap_folder(folder.folder_name): - frappe.log_error(f'FOLDER NAME: {folder.folder_name} PRESENT') email_server.settings['uid_validity'] = folder.uidvalidity messages = email_server.get_messages(folder=f'"{folder.folder_name}"') or {} process_mail(messages, folder.append_to) From 58db3765098ad6ea9f6572ebc0fc286eb9b05251 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Tue, 1 Feb 2022 20:06:26 +0530 Subject: [PATCH 05/23] fix: email syncing with "seen" emails even if email_sync filter set to "unseen" issue --- frappe/email/doctype/email_account/email_account.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 1c53ae9faf..c3ab11d2e9 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -467,7 +467,9 @@ class EmailAccount(Document): for index, message in enumerate(messages.get("latest_messages", [])): uid = messages['uid_list'][index] if messages.get('uid_list') else None seen_status = 1 if messages.get('seen_status', {}).get(uid) == 'SEEN' else 0 - mails.append(InboundMail(message, self, uid, seen_status, append_to)) + if not (self.email_sync_option == 'UNSEEN' and seen_status): + # only append the emails with status != 'SEEN' if sync option is set to 'UNSEEN' + mails.append(InboundMail(message, self, uid, seen_status, append_to)) if frappe.local.flags.in_test: return [InboundMail(msg, self) for msg in test_mails or []] From 18820bf44e56cbfee380bcc2b037f46ea87ec487 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Wed, 2 Feb 2022 09:08:03 +0530 Subject: [PATCH 06/23] feat: add test --- .../email/doctype/email_account/test_email_account.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index 6d26f9f070..d59de050c4 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -246,6 +246,16 @@ class TestEmailAccount(unittest.TestCase): with self.assertRaises(Exception): email_account.validate() + def test_append_to(self): + email_aacount = frappe.get_doc("Email Account", "_Test Email Account 1") + mail_content = self.get_test_mail(fname="incoming-2.raw") + + inbound_mail = InboundMail(mail_content, email_aacount, 12345, 1, 'ToDo') + communication = inbound_mail.process() + if inbound_mail.append_to == 'ToDo': + self.assertEqual(communication.reference_doctype, 'ToDo') + self.assertTrue(communication.reference_name) + class TestInboundMail(unittest.TestCase): @classmethod def setUpClass(cls): From f960fb70dcc49f6a9ceab7edeeab8b66dc04aa44 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Wed, 2 Feb 2022 10:14:46 +0530 Subject: [PATCH 07/23] fix: append_to in case of not passed issue --- frappe/email/receive.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 30dd146fa7..7b006c32b0 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -587,7 +587,7 @@ class InboundMail(Email): super().__init__(content) self.email_account = email_account self.uid = uid or -1 - self.append_to = append_to or -1 + self.append_to = append_to self.seen_status = seen_status or 0 # System documents related to this mail @@ -625,8 +625,8 @@ class InboundMail(Email): if self.parent_communication(): data['in_reply_to'] = self.parent_communication().name - if self.email_account.use_imap and self.append_to: - if self.append_to != 'Communication': + if self.email_account.use_imap: + if self.append_to and self.append_to != 'Communication': reference_doc = self._create_reference_document(self.append_to) if reference_doc: data['reference_doctype'] = reference_doc.doctype From 12442726c6e6627523d2ad1430fb5cc4c72f8efc Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Wed, 2 Feb 2022 11:00:39 +0530 Subject: [PATCH 08/23] fix: reply emails get_reference_doc from communication issue --- frappe/email/receive.py | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 7b006c32b0..8bbc4611ff 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -624,25 +624,18 @@ class InboundMail(Email): if self.parent_communication(): data['in_reply_to'] = self.parent_communication().name - - if self.email_account.use_imap: - if self.append_to and self.append_to != 'Communication': - reference_doc = self._create_reference_document(self.append_to) - if reference_doc: - data['reference_doctype'] = reference_doc.doctype - data['reference_name'] = reference_doc.name - data['is_first'] = True - else: - if self.reference_document(): - data['reference_doctype'] = self.reference_document().doctype - data['reference_name'] = self.reference_document().name - elif self.email_account.append_to and self.email_account.append_to != 'Communication': - reference_doc = self._create_reference_document(self.email_account.append_to) - # TODO: here instead of using email_account.append_to, the imap_folder.append_to should be used - if reference_doc: - data['reference_doctype'] = reference_doc.doctype - data['reference_name'] = reference_doc.name - data['is_first'] = True + + append_to = self.append_to if self.email_account.use_imap else self.email_account.append_to + + if self.reference_document(): + data['reference_doctype'] = self.reference_document().doctype + data['reference_name'] = self.reference_document().name + elif append_to and append_to != 'Communication': + reference_doc = self._create_reference_document(append_to) + if reference_doc: + data['reference_doctype'] = reference_doc.doctype + data['reference_name'] = reference_doc.name + data['is_first'] = True if self.is_notification(): # Disable notifications for notification. From ffbf215070b07439f80e78a70a817ef69066c48b Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Wed, 2 Feb 2022 11:29:43 +0530 Subject: [PATCH 09/23] fix: communication if is_first and no append_to issue --- frappe/email/receive.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 8bbc4611ff..b8156d5d9b 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -624,18 +624,19 @@ class InboundMail(Email): if self.parent_communication(): data['in_reply_to'] = self.parent_communication().name - + append_to = self.append_to if self.email_account.use_imap else self.email_account.append_to if self.reference_document(): data['reference_doctype'] = self.reference_document().doctype data['reference_name'] = self.reference_document().name - elif append_to and append_to != 'Communication': - reference_doc = self._create_reference_document(append_to) - if reference_doc: - data['reference_doctype'] = reference_doc.doctype - data['reference_name'] = reference_doc.name - data['is_first'] = True + else: + if append_to and append_to != 'Communication': + reference_doc = self._create_reference_document(append_to) + if reference_doc: + data['reference_doctype'] = reference_doc.doctype + data['reference_name'] = reference_doc.name + data['is_first'] = True if self.is_notification(): # Disable notifications for notification. From 3734dc792711097e5a7e4077f68e5c4c7f3f6edc Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Fri, 4 Feb 2022 15:07:18 +0530 Subject: [PATCH 10/23] feat: add tests for imap folders email syncing with multiple folders --- .../doctype/email_account/email_account.py | 10 ++- .../email_account/test_email_account.py | 60 ++++++++++++-- .../email_account/test_mails/messages-1.raw | 81 +++++++++++++++++++ .../doctype/email_account/test_records.json | 2 +- 4 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 frappe/email/doctype/email_account/test_mails/messages-1.raw diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index c3ab11d2e9..6d84cbb270 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -457,7 +457,7 @@ class EmailAccount(Document): if exceptions: raise Exception(frappe.as_json(exceptions)) - def get_inbound_mails(self, test_mails=None) -> List[InboundMail]: + def get_inbound_mails(self, test_mails=None, messages=None) -> List[InboundMail]: """retrive and return inbound mails. """ @@ -472,7 +472,13 @@ class EmailAccount(Document): mails.append(InboundMail(message, self, uid, seen_status, append_to)) if frappe.local.flags.in_test: - return [InboundMail(msg, self) for msg in test_mails or []] + if self.enable_incoming: + for folder in self.imap_folder: + _messages = messages[folder.folder_name] if folder.folder_name in messages and ( messages[folder.folder_name] is not None) else {} + process_mail(_messages, folder.append_to) + return mails + else: + return [InboundMail(msg, self) for msg in test_mails or []] if not self.enable_incoming: return [] diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index d59de050c4..3555353259 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -247,14 +247,64 @@ class TestEmailAccount(unittest.TestCase): email_account.validate() def test_append_to(self): - email_aacount = frappe.get_doc("Email Account", "_Test Email Account 1") + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") mail_content = self.get_test_mail(fname="incoming-2.raw") - inbound_mail = InboundMail(mail_content, email_aacount, 12345, 1, 'ToDo') + inbound_mail = InboundMail(mail_content, email_account, 12345, 1, 'ToDo') communication = inbound_mail.process() - if inbound_mail.append_to == 'ToDo': - self.assertEqual(communication.reference_doctype, 'ToDo') - self.assertTrue(communication.reference_name) + # the append_to for the email is set to ToDO in "_Test Email Account 1" + self.assertEqual(communication.reference_doctype, 'ToDo') + self.assertTrue(communication.reference_name) + self.assertTrue(frappe.db.exists(communication.reference_doctype, communication.reference_name)) + + def test_append_to_with_imap_folders(self): + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + + mail_content_1 = self.get_test_mail(fname="incoming-1.raw") + mail_content_2 = self.get_test_mail(fname="incoming-2.raw") + mail_content_3 = self.get_test_mail(fname="incoming-3.raw") + + messages = { + 'INBOX': { # append_to = ToDo + 'latest_messages': [ + mail_content_1, + mail_content_2 + ], + 'seen_status': { + 0: 'UNSEEN', + 1: 'UNSEEN' + }, + 'uid_list': [0,1] + }, + 'Test Folder': { # append_to = Communication + 'latest_messages': [ + mail_content_3 + ], + 'seen_status': { + 2: 'UNSEEN' + }, + 'uid_list': [2] + } + } + mails = email_account.get_inbound_mails(messages=messages) + self.assertEqual(len(mails), 3) + + inbox_mails = 0 + test_folder_mails = 0 + + for mail in mails: + communication = mail.process() + if mail.append_to == 'ToDo': + inbox_mails += 1 + self.assertEqual(communication.reference_doctype, 'ToDo') + self.assertTrue(communication.reference_name) + self.assertTrue(frappe.db.exists(communication.reference_doctype, communication.reference_name)) + else: + test_folder_mails += 1 + self.assertEqual(communication.reference_doctype, None) + + self.assertEqual(inbox_mails, 2) + self.assertEqual(test_folder_mails, 1) class TestInboundMail(unittest.TestCase): @classmethod diff --git a/frappe/email/doctype/email_account/test_mails/messages-1.raw b/frappe/email/doctype/email_account/test_mails/messages-1.raw new file mode 100644 index 0000000000..d0ac914371 --- /dev/null +++ b/frappe/email/doctype/email_account/test_mails/messages-1.raw @@ -0,0 +1,81 @@ +Delivered-To: kamal@frappe.io +Received: by 2002:a59:bcaf:0:b0:283:bf56:ecc6 with SMTP id q15csp1608707vqy; + Tue, 1 Feb 2022 18:36:19 -0800 (PST) +X-Received: by 2002:a05:6638:d06:: with SMTP id q6mr5074243jaj.197.1643769379814; + Tue, 01 Feb 2022 18:36:19 -0800 (PST) +ARC-Seal: i=1; a=rsa-sha256; t=1643769379; cv=none; + d=google.com; s=arc-20160816; + b=V0+D/66dKKmy7d5BdoHKohecWHF6PhMgtgarnemPm8UaOL5S5WyGUWt+azZZLK0HcU + TkxA3HY+/UlO3BjdmvY9hHtprPzTgK0U27S7sboIEQJXLblKfx9OOL2Wq0cS6YSlTcXQ + OIZaDepuJ9u7KUhRiHbmQCYXWmDdG0syALsONwjfXVBwqHn9wGizHbkp7tBCrgGbSfiF + NQgNOiwnau1jC48T+IKm7+9/1gqSWpU5c+4iWEDzmDaUTyE69XrHoAsThPXQ1FTn7beC + taVnDkMXIpJcOBJZLIWJLCKhju2oBz5EkX4j/IkNAnOIw40RAV/s9HT5DZUDjPoMd8g+ + IrGw== +ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; + h=to:subject:message-id:date:from:mime-version:dkim-signature; + bh=8ECAAGQ3yaTI5Xt9rqRpk+teGEit3tpBNmAS2780QKw=; + b=OjYxw0kvdSTP3Z+jAiU8LQJ65Ej6FAdZxEpUb8xvpFiP96kvRKkGEGhMFabPXDUXMn + mEeKI1Ocqm55b1XUWY44EK5E/eecA651SbIKvR/ihOXzrnPD3hItfj9S2PsgjyQp+rX1 + +vREp5o1A+tWbFI3smRYPqWUv1g7J5hRzCXjI1FyNI1OdkJn7K9PlEsR1xqjflGDmOif + nfglNmrkjCMIw9XHQ91rMY1ta+yrVvVeDFVLLBV4R0yCL/DrpmozSDViZPNzMmo6ITRQ + T+/qkuku9aBReM1XebA7mLKPrPGuU27l2GJX4hpsz0gEYDpItf53MEaO5XIkoELo0b8s + AxRQ== +ARC-Authentication-Results: i=1; mx.google.com; + dkim=pass header.i=@gmail.com header.s=20210112 header.b=J6sQ2r3s; + spf=pass (google.com: domain of kamaljohnson12345@gmail.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=kamaljohnson12345@gmail.com; + dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com +Return-Path: +Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41]) + by mx.google.com with SMTPS id 1sor6796918jao.124.2022.02.01.18.36.19 + for + (Google Transport Security); + Tue, 01 Feb 2022 18:36:19 -0800 (PST) +Received-SPF: pass (google.com: domain of kamaljohnson12345@gmail.com designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41; +Authentication-Results: mx.google.com; + dkim=pass header.i=@gmail.com header.s=20210112 header.b=J6sQ2r3s; + spf=pass (google.com: domain of kamaljohnson12345@gmail.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=kamaljohnson12345@gmail.com; + dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20210112; + h=mime-version:from:date:message-id:subject:to; + bh=8ECAAGQ3yaTI5Xt9rqRpk+teGEit3tpBNmAS2780QKw=; + b=J6sQ2r3s24Gj5ATpKCyjleWOaF9+9rvwKg/NJ979EpEvy13v4rRX4gL7xbX8GIVkZ4 + QoOl3xUNtRItJPYWuW984GXsmL5v8YrakCb0JzS5iWk3VC+Q+orhk95giHDLx/1UrTeK + KFhLQ632i23M2IutOA4vRVet3n4wnmYwXiJZ1G/HoE70h+1Jn+E0nsvBsz8IU5eWHve7 + SKWAaEtUOwcyuLi9SncQh62bM9ZW6V034LEb0MXz/suAJ+sPIvjSSNJwehKpvYfg1AUt + CkzuAxJt17MThTwz+/YCZkttN7LKDeBAUJWh2+JB+BfyvzYR1pUyJfwLhRMNYoeWZpGK + L/6g== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20210112; + h=x-gm-message-state:mime-version:from:date:message-id:subject:to; + bh=8ECAAGQ3yaTI5Xt9rqRpk+teGEit3tpBNmAS2780QKw=; + b=CyVqLYduXIsBE7f62ti9wFFkTv/Vn6anf1UtnakmhgeWksW0nvjOjnAdytXHiD5Phl + vtTpmCGgLVcTZBI8wUaKdjsGDVWnpG8zYRQljytyrptyi+M4ShnUMq2WbyceeFFop+Ta + 5z/0PE3wva+H45uj2ICRu2l0o1nvjNKxt14zzbaCYgUyx2ZF24MLgIO2ko1xnTXS6M5g + ASnc4ia+9r3MhLa3y3Ss97KYRcLXeVzbqEXS4X3DB1h+/tHLogLTAX5D8w5LME7M0MfR + uy4dC0K4VmhhDJTzoFHzgBqWw1vqNU/G92Fr/kZdVzMiSegt0Up76ePA8mwpeEKzaNdP + e4wg== +X-Gm-Message-State: AOAM532tem+DamkNGjOKo5Ayzg9Gdh0clTzSw+ajeLwzgcNy/fNYBVhC + YHvVK8Ylvd0Jr8XjwshuyN/hz8UOoV2fkjOij9CED3Vo +X-Google-Smtp-Source: ABdhPJwB/h4hp6eiaPL7IIkokMwriJ92sqjBOp3ptJnp+mtkZNAr8JNrt86gahMU24MuTsB8HUnK9oEXGRKV+55XO5U= +X-Received: by 2002:a02:c916:: with SMTP id t22mr15608489jao.300.1643769379473; + Tue, 01 Feb 2022 18:36:19 -0800 (PST) +MIME-Version: 1.0 +From: Kamal Johnson +Date: Wed, 2 Feb 2022 08:06:06 +0530 +Message-ID: +Subject: Hfruuhhs +To: Kamal Johnson +Content-Type: multipart/alternative; boundary="000000000000f4cb7505d6ffe106" + +--000000000000f4cb7505d6ffe106 +Content-Type: text/plain; charset="UTF-8" + +Yysjtshsg + +--000000000000f4cb7505d6ffe106 +Content-Type: text/html; charset="UTF-8" + +
Yysjtshsg
+ +--000000000000f4cb7505d6ffe106-- \ No newline at end of file diff --git a/frappe/email/doctype/email_account/test_records.json b/frappe/email/doctype/email_account/test_records.json index 450895d7a6..66eb5a9b2e 100644 --- a/frappe/email/doctype/email_account/test_records.json +++ b/frappe/email/doctype/email_account/test_records.json @@ -20,7 +20,7 @@ "pop3_server": "pop.test.example.com", "no_remaining":"0", "append_to": "ToDo", - "imap_folder": [{"folder_name": "INBOX", "append_to": "ToDo"}], + "imap_folder": [{"folder_name": "INBOX", "append_to": "ToDo"}, {"folder_name": "Test Folder", "append_to": "Communication"}], "track_email_status": 1 }, { From 8cc26af272c103d3f984707e11d635d95f7430a6 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Fri, 4 Feb 2022 15:28:16 +0530 Subject: [PATCH 11/23] fix: remove messages-1.raw --- .../email_account/test_mails/messages-1.raw | 81 ------------------- 1 file changed, 81 deletions(-) delete mode 100644 frappe/email/doctype/email_account/test_mails/messages-1.raw diff --git a/frappe/email/doctype/email_account/test_mails/messages-1.raw b/frappe/email/doctype/email_account/test_mails/messages-1.raw deleted file mode 100644 index d0ac914371..0000000000 --- a/frappe/email/doctype/email_account/test_mails/messages-1.raw +++ /dev/null @@ -1,81 +0,0 @@ -Delivered-To: kamal@frappe.io -Received: by 2002:a59:bcaf:0:b0:283:bf56:ecc6 with SMTP id q15csp1608707vqy; - Tue, 1 Feb 2022 18:36:19 -0800 (PST) -X-Received: by 2002:a05:6638:d06:: with SMTP id q6mr5074243jaj.197.1643769379814; - Tue, 01 Feb 2022 18:36:19 -0800 (PST) -ARC-Seal: i=1; a=rsa-sha256; t=1643769379; cv=none; - d=google.com; s=arc-20160816; - b=V0+D/66dKKmy7d5BdoHKohecWHF6PhMgtgarnemPm8UaOL5S5WyGUWt+azZZLK0HcU - TkxA3HY+/UlO3BjdmvY9hHtprPzTgK0U27S7sboIEQJXLblKfx9OOL2Wq0cS6YSlTcXQ - OIZaDepuJ9u7KUhRiHbmQCYXWmDdG0syALsONwjfXVBwqHn9wGizHbkp7tBCrgGbSfiF - NQgNOiwnau1jC48T+IKm7+9/1gqSWpU5c+4iWEDzmDaUTyE69XrHoAsThPXQ1FTn7beC - taVnDkMXIpJcOBJZLIWJLCKhju2oBz5EkX4j/IkNAnOIw40RAV/s9HT5DZUDjPoMd8g+ - IrGw== -ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; - h=to:subject:message-id:date:from:mime-version:dkim-signature; - bh=8ECAAGQ3yaTI5Xt9rqRpk+teGEit3tpBNmAS2780QKw=; - b=OjYxw0kvdSTP3Z+jAiU8LQJ65Ej6FAdZxEpUb8xvpFiP96kvRKkGEGhMFabPXDUXMn - mEeKI1Ocqm55b1XUWY44EK5E/eecA651SbIKvR/ihOXzrnPD3hItfj9S2PsgjyQp+rX1 - +vREp5o1A+tWbFI3smRYPqWUv1g7J5hRzCXjI1FyNI1OdkJn7K9PlEsR1xqjflGDmOif - nfglNmrkjCMIw9XHQ91rMY1ta+yrVvVeDFVLLBV4R0yCL/DrpmozSDViZPNzMmo6ITRQ - T+/qkuku9aBReM1XebA7mLKPrPGuU27l2GJX4hpsz0gEYDpItf53MEaO5XIkoELo0b8s - AxRQ== -ARC-Authentication-Results: i=1; mx.google.com; - dkim=pass header.i=@gmail.com header.s=20210112 header.b=J6sQ2r3s; - spf=pass (google.com: domain of kamaljohnson12345@gmail.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=kamaljohnson12345@gmail.com; - dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com -Return-Path: -Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41]) - by mx.google.com with SMTPS id 1sor6796918jao.124.2022.02.01.18.36.19 - for - (Google Transport Security); - Tue, 01 Feb 2022 18:36:19 -0800 (PST) -Received-SPF: pass (google.com: domain of kamaljohnson12345@gmail.com designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41; -Authentication-Results: mx.google.com; - dkim=pass header.i=@gmail.com header.s=20210112 header.b=J6sQ2r3s; - spf=pass (google.com: domain of kamaljohnson12345@gmail.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=kamaljohnson12345@gmail.com; - dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=gmail.com; s=20210112; - h=mime-version:from:date:message-id:subject:to; - bh=8ECAAGQ3yaTI5Xt9rqRpk+teGEit3tpBNmAS2780QKw=; - b=J6sQ2r3s24Gj5ATpKCyjleWOaF9+9rvwKg/NJ979EpEvy13v4rRX4gL7xbX8GIVkZ4 - QoOl3xUNtRItJPYWuW984GXsmL5v8YrakCb0JzS5iWk3VC+Q+orhk95giHDLx/1UrTeK - KFhLQ632i23M2IutOA4vRVet3n4wnmYwXiJZ1G/HoE70h+1Jn+E0nsvBsz8IU5eWHve7 - SKWAaEtUOwcyuLi9SncQh62bM9ZW6V034LEb0MXz/suAJ+sPIvjSSNJwehKpvYfg1AUt - CkzuAxJt17MThTwz+/YCZkttN7LKDeBAUJWh2+JB+BfyvzYR1pUyJfwLhRMNYoeWZpGK - L/6g== -X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; - d=1e100.net; s=20210112; - h=x-gm-message-state:mime-version:from:date:message-id:subject:to; - bh=8ECAAGQ3yaTI5Xt9rqRpk+teGEit3tpBNmAS2780QKw=; - b=CyVqLYduXIsBE7f62ti9wFFkTv/Vn6anf1UtnakmhgeWksW0nvjOjnAdytXHiD5Phl - vtTpmCGgLVcTZBI8wUaKdjsGDVWnpG8zYRQljytyrptyi+M4ShnUMq2WbyceeFFop+Ta - 5z/0PE3wva+H45uj2ICRu2l0o1nvjNKxt14zzbaCYgUyx2ZF24MLgIO2ko1xnTXS6M5g - ASnc4ia+9r3MhLa3y3Ss97KYRcLXeVzbqEXS4X3DB1h+/tHLogLTAX5D8w5LME7M0MfR - uy4dC0K4VmhhDJTzoFHzgBqWw1vqNU/G92Fr/kZdVzMiSegt0Up76ePA8mwpeEKzaNdP - e4wg== -X-Gm-Message-State: AOAM532tem+DamkNGjOKo5Ayzg9Gdh0clTzSw+ajeLwzgcNy/fNYBVhC - YHvVK8Ylvd0Jr8XjwshuyN/hz8UOoV2fkjOij9CED3Vo -X-Google-Smtp-Source: ABdhPJwB/h4hp6eiaPL7IIkokMwriJ92sqjBOp3ptJnp+mtkZNAr8JNrt86gahMU24MuTsB8HUnK9oEXGRKV+55XO5U= -X-Received: by 2002:a02:c916:: with SMTP id t22mr15608489jao.300.1643769379473; - Tue, 01 Feb 2022 18:36:19 -0800 (PST) -MIME-Version: 1.0 -From: Kamal Johnson -Date: Wed, 2 Feb 2022 08:06:06 +0530 -Message-ID: -Subject: Hfruuhhs -To: Kamal Johnson -Content-Type: multipart/alternative; boundary="000000000000f4cb7505d6ffe106" - ---000000000000f4cb7505d6ffe106 -Content-Type: text/plain; charset="UTF-8" - -Yysjtshsg - ---000000000000f4cb7505d6ffe106 -Content-Type: text/html; charset="UTF-8" - -
Yysjtshsg
- ---000000000000f4cb7505d6ffe106-- \ No newline at end of file From 8f8bafbdde33acbb0b71acb999ab683d40fdbe2b Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Fri, 4 Feb 2022 15:29:12 +0530 Subject: [PATCH 12/23] fix: sider styling issue --- frappe/email/doctype/email_account/email_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 6d84cbb270..2aa409628b 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -474,7 +474,7 @@ class EmailAccount(Document): if frappe.local.flags.in_test: if self.enable_incoming: for folder in self.imap_folder: - _messages = messages[folder.folder_name] if folder.folder_name in messages and ( messages[folder.folder_name] is not None) else {} + _messages = messages[folder.folder_name] if folder.folder_name in messages and (messages[folder.folder_name] is not None) else {} process_mail(_messages, folder.append_to) return mails else: From 1cc0f88d0b0194f73194cce7e99fddba017b7731 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Fri, 4 Feb 2022 15:47:27 +0530 Subject: [PATCH 13/23] fix: issue when test_mails are passed while testing --- frappe/email/doctype/email_account/email_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 2aa409628b..ddc3e349cd 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -472,7 +472,7 @@ class EmailAccount(Document): mails.append(InboundMail(message, self, uid, seen_status, append_to)) if frappe.local.flags.in_test: - if self.enable_incoming: + if self.enable_incoming and not test_mails: for folder in self.imap_folder: _messages = messages[folder.folder_name] if folder.folder_name in messages and (messages[folder.folder_name] is not None) else {} process_mail(_messages, folder.append_to) From c80c81ed329937f3295605b451f7d58a71b99cf6 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Fri, 4 Feb 2022 18:20:07 +0530 Subject: [PATCH 14/23] fix: messages and test_mail not passed issue while running test --- frappe/email/doctype/email_account/email_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index ddc3e349cd..cc7a1352cf 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -472,7 +472,7 @@ class EmailAccount(Document): mails.append(InboundMail(message, self, uid, seen_status, append_to)) if frappe.local.flags.in_test: - if self.enable_incoming and not test_mails: + if self.enable_incoming and not test_mails and messages: for folder in self.imap_folder: _messages = messages[folder.folder_name] if folder.folder_name in messages and (messages[folder.folder_name] is not None) else {} process_mail(_messages, folder.append_to) From ae2dd3f6b87d51e9446bd413667b0b82f83ee3da Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Mon, 7 Feb 2022 11:59:06 +0530 Subject: [PATCH 15/23] fix: Remove `in_test` flag inside `get_inbound_mails` - Use mocked data instead for testing --- .../doctype/email_account/email_account.py | 17 +++++----- .../email_account/test_email_account.py | 33 +++++++++++-------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index cc7a1352cf..424690e797 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -471,14 +471,14 @@ class EmailAccount(Document): # only append the emails with status != 'SEEN' if sync option is set to 'UNSEEN' mails.append(InboundMail(message, self, uid, seen_status, append_to)) - if frappe.local.flags.in_test: - if self.enable_incoming and not test_mails and messages: - for folder in self.imap_folder: - _messages = messages[folder.folder_name] if folder.folder_name in messages and (messages[folder.folder_name] is not None) else {} - process_mail(_messages, folder.append_to) - return mails - else: - return [InboundMail(msg, self) for msg in test_mails or []] + # if frappe.local.flags.in_test: + # if self.enable_incoming and not test_mails and messages: + # for folder in self.imap_folder: + # _messages = messages[folder.folder_name] if folder.folder_name in messages and (messages[folder.folder_name] is not None) else {} + # process_mail(_messages, folder.append_to) + # return mails + # else: + # return [InboundMail(msg, self) for msg in test_mails or []] if not self.enable_incoming: return [] @@ -502,7 +502,6 @@ class EmailAccount(Document): except Exception: frappe.log_error(title=_("Error while connecting to email account {0}").format(self.name)) return [] - return mails def handle_bad_emails(self, uid, raw, reason): diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index 3555353259..4c1acf091b 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -14,11 +14,11 @@ from frappe.core.doctype.communication.email import make from frappe.desk.form.load import get_attachments from frappe.email.doctype.email_account.email_account import notify_unreplied +from unittest.mock import patch + make_test_records("User") make_test_records("Email Account") - - class TestEmailAccount(unittest.TestCase): @classmethod def setUpClass(cls): @@ -257,15 +257,16 @@ class TestEmailAccount(unittest.TestCase): self.assertTrue(communication.reference_name) self.assertTrue(frappe.db.exists(communication.reference_doctype, communication.reference_name)) - def test_append_to_with_imap_folders(self): - email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - + @patch("frappe.email.receive.EmailServer.select_imap_folder", return_value=True) + @patch("frappe.email.receive.EmailServer.logout", side_effect=lambda: None) + # @patch("frappe.email.receive.EmailServer.get_messages", side_effect=get_mocked_messages) + def test_append_to_with_imap_folders(self, mocked_logout, mocked_select_imap_folder): mail_content_1 = self.get_test_mail(fname="incoming-1.raw") mail_content_2 = self.get_test_mail(fname="incoming-2.raw") mail_content_3 = self.get_test_mail(fname="incoming-3.raw") messages = { - 'INBOX': { # append_to = ToDo + '"INBOX"': { # append_to = ToDo 'latest_messages': [ mail_content_1, mail_content_2 @@ -276,7 +277,7 @@ class TestEmailAccount(unittest.TestCase): }, 'uid_list': [0,1] }, - 'Test Folder': { # append_to = Communication + '"Test Folder"': { # append_to = Communication 'latest_messages': [ mail_content_3 ], @@ -286,9 +287,15 @@ class TestEmailAccount(unittest.TestCase): 'uid_list': [2] } } - mails = email_account.get_inbound_mails(messages=messages) - self.assertEqual(len(mails), 3) - + from frappe.email.receive import EmailServer + def get_mocked_messages(**args): + return messages[args["folder"]] + + with patch.object(EmailServer, "get_messages", side_effect=get_mocked_messages): + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + mails = email_account.get_inbound_mails(messages=messages) + self.assertEqual(len(mails), 3) + inbox_mails = 0 test_folder_mails = 0 @@ -373,11 +380,11 @@ class TestInboundMail(unittest.TestCase): email_account = frappe.get_doc("Email Account", "_Test Email Account 1") inbound_mail = InboundMail(mail_content, email_account, 12345, 1) - new_communiction = inbound_mail.process() + new_communication = inbound_mail.process() # Make sure that uid is changed to new uid - self.assertEqual(new_communiction.uid, 12345) - self.assertEqual(communication.name, new_communiction.name) + self.assertEqual(new_communication.uid, 12345) + self.assertEqual(communication.name, new_communication.name) def test_find_parent_email_queue(self): """If the mail is reply to the already sent mail, there will be a email queue record. From caab903edb79fac0420656416cf39584c33a87e6 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Mon, 7 Feb 2022 15:49:59 +0530 Subject: [PATCH 16/23] fix: add back `in_test` override for `imap_folders` test Since a lot of tests still uses the old way i.e, use `in_test` and execute custome (non-production) code to get results. Kept the same code for now else as a major test refactor needs to be done. --- .../doctype/email_account/email_account.py | 12 ++------ .../email_account/test_email_account.py | 29 ++++++++++++------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 424690e797..feef9dc234 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -457,7 +457,7 @@ class EmailAccount(Document): if exceptions: raise Exception(frappe.as_json(exceptions)) - def get_inbound_mails(self, test_mails=None, messages=None) -> List[InboundMail]: + def get_inbound_mails(self, test_mails=None) -> List[InboundMail]: """retrive and return inbound mails. """ @@ -471,14 +471,8 @@ class EmailAccount(Document): # only append the emails with status != 'SEEN' if sync option is set to 'UNSEEN' mails.append(InboundMail(message, self, uid, seen_status, append_to)) - # if frappe.local.flags.in_test: - # if self.enable_incoming and not test_mails and messages: - # for folder in self.imap_folder: - # _messages = messages[folder.folder_name] if folder.folder_name in messages and (messages[folder.folder_name] is not None) else {} - # process_mail(_messages, folder.append_to) - # return mails - # else: - # return [InboundMail(msg, self) for msg in test_mails or []] + if frappe.local.flags.in_test: + return [InboundMail(msg, self) for msg in test_mails or []] if not self.enable_incoming: return [] diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index 4c1acf091b..c53f8fa1ab 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -257,10 +257,7 @@ class TestEmailAccount(unittest.TestCase): self.assertTrue(communication.reference_name) self.assertTrue(frappe.db.exists(communication.reference_doctype, communication.reference_name)) - @patch("frappe.email.receive.EmailServer.select_imap_folder", return_value=True) - @patch("frappe.email.receive.EmailServer.logout", side_effect=lambda: None) - # @patch("frappe.email.receive.EmailServer.get_messages", side_effect=get_mocked_messages) - def test_append_to_with_imap_folders(self, mocked_logout, mocked_select_imap_folder): + def test_append_to_with_imap_folders(self): mail_content_1 = self.get_test_mail(fname="incoming-1.raw") mail_content_2 = self.get_test_mail(fname="incoming-2.raw") mail_content_3 = self.get_test_mail(fname="incoming-3.raw") @@ -287,14 +284,10 @@ class TestEmailAccount(unittest.TestCase): 'uid_list': [2] } } - from frappe.email.receive import EmailServer - def get_mocked_messages(**args): - return messages[args["folder"]] - with patch.object(EmailServer, "get_messages", side_effect=get_mocked_messages): - email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - mails = email_account.get_inbound_mails(messages=messages) - self.assertEqual(len(mails), 3) + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + mails = TestEmailAccount.mocked_get_inbound_mails(email_account, messages) + self.assertEqual(len(mails), 3) inbox_mails = 0 test_folder_mails = 0 @@ -313,6 +306,20 @@ class TestEmailAccount(unittest.TestCase): self.assertEqual(inbox_mails, 2) self.assertEqual(test_folder_mails, 1) + @patch("frappe.local.flags.in_test", False) + @patch("frappe.email.receive.EmailServer.select_imap_folder", return_value=True) + @patch("frappe.email.receive.EmailServer.logout", side_effect=lambda: None) + def mocked_get_inbound_mails(email_account, messages={}, mocked_logout=None, mocked_select_imap_folder=None): + from frappe.email.receive import EmailServer + + def get_mocked_messages(**kwargs): + return messages[kwargs["folder"]] + + with patch.object(EmailServer, "get_messages", side_effect=get_mocked_messages): + mails = email_account.get_inbound_mails() + + return mails + class TestInboundMail(unittest.TestCase): @classmethod def setUpClass(cls): From 7c51c6a9ea1866ab9e19ed8a60fef235fa716782 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Mon, 7 Feb 2022 18:25:36 +0530 Subject: [PATCH 17/23] fix: add in_test parameter from frappe.local.flags.in_test mock --- frappe/email/doctype/email_account/test_email_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index c53f8fa1ab..46cc3d03af 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -309,7 +309,7 @@ class TestEmailAccount(unittest.TestCase): @patch("frappe.local.flags.in_test", False) @patch("frappe.email.receive.EmailServer.select_imap_folder", return_value=True) @patch("frappe.email.receive.EmailServer.logout", side_effect=lambda: None) - def mocked_get_inbound_mails(email_account, messages={}, mocked_logout=None, mocked_select_imap_folder=None): + def mocked_get_inbound_mails(email_account, messages={}, mocked_logout=None, mocked_select_imap_folder=None, mocked_in_test=None): from frappe.email.receive import EmailServer def get_mocked_messages(**kwargs): From 7b0e646e10445c5bca6dcb5c0848a0045581e06e Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Tue, 8 Feb 2022 01:04:44 +0530 Subject: [PATCH 18/23] fix: none type issue in email test, add more coverage to `test_auto_reply` --- .../email_account/test_email_account.py | 26 ++++++++++++++-- .../email/doctype/email_queue/email_queue.py | 31 ++++++++++--------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index 46cc3d03af..2c5f69333b 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -213,10 +213,20 @@ class TestEmailAccount(unittest.TestCase): def test_auto_reply(self): cleanup("test_sender@example.com") - test_mails = [self.get_test_mail('incoming-1.raw')] + messages = { + '"INBOX"': { # append_to = ToDo + 'latest_messages': [ + self.get_test_mail('incoming-1.raw') + ], + 'seen_status': { + 2: 'UNSEEN' + }, + 'uid_list': [2] + } + } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - email_account.receive(test_mails=test_mails) + TestEmailAccount.mocked_email_receive(email_account, messages) comm = frappe.get_doc("Communication", {"sender": "test_sender@example.com"}) self.assertTrue(frappe.db.get_value("Email Queue", {"reference_doctype": comm.reference_doctype, @@ -319,6 +329,18 @@ class TestEmailAccount(unittest.TestCase): mails = email_account.get_inbound_mails() return mails + + @patch("frappe.local.flags.in_test", False) + @patch("frappe.email.receive.EmailServer.select_imap_folder", return_value=True) + @patch("frappe.email.receive.EmailServer.logout", side_effect=lambda: None) + def mocked_email_receive(email_account, messages={}, mocked_logout=None, mocked_select_imap_folder=None, mocked_in_test=None): + def get_mocked_messages(**kwargs): + return messages[kwargs["folder"]] + + from frappe.email.receive import EmailServer + with patch.object(EmailServer, "get_messages", side_effect=get_mocked_messages): + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + email_account.receive() class TestInboundMail(unittest.TestCase): @classmethod diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index 4da83bd0d2..9b4f3b984c 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -479,21 +479,24 @@ class QueueBuilder: EmailUnsubscribe = DocType("Email Unsubscribe") - unsubscribed = ( - frappe.qb.from_(EmailUnsubscribe).select( - EmailUnsubscribe.email - ).where( - EmailUnsubscribe.email.isin(all_ids) - & ( - ( - (EmailUnsubscribe.reference_doctype == self.reference_doctype) - & (EmailUnsubscribe.reference_name == self.reference_name) - ) | ( - EmailUnsubscribe.global_unsubscribe == 1 + if len(all_ids) > 0: + unsubscribed = ( + frappe.qb.from_(EmailUnsubscribe).select( + EmailUnsubscribe.email + ).where( + EmailUnsubscribe.email.isin(all_ids) + & ( + ( + (EmailUnsubscribe.reference_doctype == self.reference_doctype) + & (EmailUnsubscribe.reference_name == self.reference_name) + ) | ( + EmailUnsubscribe.global_unsubscribe == 1 + ) ) - ) - ).distinct() - ).run(pluck=True) + ).distinct() + ).run(pluck=True) + else: + unsubscribed = None self._unsubscribed_user_emails = unsubscribed or [] return self._unsubscribed_user_emails From d318675522e3fdfa3e525deae67076769965ed13 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Tue, 8 Feb 2022 01:27:26 +0530 Subject: [PATCH 19/23] feat: add coverage for some more email tests - test_incoming - test_incoming_with_attach - test_incoming_attached_email_from_outlook_plain_text_only - test_incoming_attached_email_from_outlook_layers --- .../email_account/test_email_account.py | 59 +++++++++++++++---- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index 2c5f69333b..d9f47a6026 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -45,10 +45,20 @@ class TestEmailAccount(unittest.TestCase): def test_incoming(self): cleanup("test_sender@example.com") - test_mails = [self.get_test_mail('incoming-1.raw')] + messages = { + '"INBOX"': { # append_to = ToDo + 'latest_messages': [ + self.get_test_mail('incoming-1.raw') + ], + 'seen_status': { + 2: 'UNSEEN' + }, + 'uid_list': [2] + } + } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - email_account.receive(test_mails=test_mails) + TestEmailAccount.mocked_email_receive(email_account, messages) comm = frappe.get_doc("Communication", {"sender": "test_sender@example.com"}) self.assertTrue("test_receiver@example.com" in comm.recipients) @@ -72,11 +82,20 @@ class TestEmailAccount(unittest.TestCase): existing_file = frappe.get_doc({'doctype': 'File', 'file_name': 'erpnext-conf-14.png'}) frappe.delete_doc("File", existing_file.name) - with open(os.path.join(os.path.dirname(__file__), "test_mails", "incoming-2.raw"), "r") as testfile: - test_mails = [testfile.read()] + messages = { + '"INBOX"': { # append_to = ToDo + 'latest_messages': [ + self.get_test_mail('incoming-2.raw') + ], + 'seen_status': { + 2: 'UNSEEN' + }, + 'uid_list': [2] + } + } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - email_account.receive(test_mails=test_mails) + TestEmailAccount.mocked_email_receive(email_account, messages) comm = frappe.get_doc("Communication", {"sender": "test_sender@example.com"}) self.assertTrue("test_receiver@example.com" in comm.recipients) @@ -93,11 +112,20 @@ class TestEmailAccount(unittest.TestCase): def test_incoming_attached_email_from_outlook_plain_text_only(self): cleanup("test_sender@example.com") - with open(os.path.join(os.path.dirname(__file__), "test_mails", "incoming-3.raw"), "r") as f: - test_mails = [f.read()] + messages = { + '"INBOX"': { # append_to = ToDo + 'latest_messages': [ + self.get_test_mail('incoming-3.raw') + ], + 'seen_status': { + 2: 'UNSEEN' + }, + 'uid_list': [2] + } + } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - email_account.receive(test_mails=test_mails) + TestEmailAccount.mocked_email_receive(email_account, messages) comm = frappe.get_doc("Communication", {"sender": "test_sender@example.com"}) self.assertTrue("From: "Microsoft Outlook" <test_sender@example.com>" in comm.content) @@ -106,11 +134,20 @@ class TestEmailAccount(unittest.TestCase): def test_incoming_attached_email_from_outlook_layers(self): cleanup("test_sender@example.com") - with open(os.path.join(os.path.dirname(__file__), "test_mails", "incoming-4.raw"), "r") as f: - test_mails = [f.read()] + messages = { + '"INBOX"': { # append_to = ToDo + 'latest_messages': [ + self.get_test_mail('incoming-4.raw') + ], + 'seen_status': { + 2: 'UNSEEN' + }, + 'uid_list': [2] + } + } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - email_account.receive(test_mails=test_mails) + TestEmailAccount.mocked_email_receive(email_account, messages) comm = frappe.get_doc("Communication", {"sender": "test_sender@example.com"}) self.assertTrue("From: "Microsoft Outlook" <test_sender@example.com>" in comm.content) From 0e63c9c33e8e92043a87e74c68e7eb874395120d Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Tue, 8 Feb 2022 08:11:43 +0530 Subject: [PATCH 20/23] fix: test fail issue for some email tests - test_threading - test_threading_by_message_id - test_threading_by_subject --- .../email_account/test_email_account.py | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index d9f47a6026..fc8b678fde 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -188,11 +188,22 @@ class TestEmailAccount(unittest.TestCase): with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-1.raw"), "r") as f: raw = f.read() raw = raw.replace("<-- in-reply-to -->", sent_mail.get("Message-Id")) - test_mails = [raw] # parse reply + messages = { + '"INBOX"': { # append_to = ToDo + 'latest_messages': [ + raw + ], + 'seen_status': { + 2: 'UNSEEN' + }, + 'uid_list': [2] + } + } + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - email_account.receive(test_mails=test_mails) + TestEmailAccount.mocked_email_receive(email_account, messages) sent = frappe.get_doc("Communication", sent_name) @@ -210,8 +221,19 @@ class TestEmailAccount(unittest.TestCase): test_mails.append(f.read()) # parse reply + messages = { + '"INBOX"': { # append_to = ToDo + 'latest_messages': test_mails, + 'seen_status': { + 2: 'UNSEEN', + 3: 'UNSEEN' + }, + 'uid_list': [2, 3] + } + } + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - email_account.receive(test_mails=test_mails) + TestEmailAccount.mocked_email_receive(email_account, messages) comm_list = frappe.get_all("Communication", filters={"sender":"test_sender@example.com"}, fields=["name", "reference_doctype", "reference_name"]) @@ -234,11 +256,22 @@ class TestEmailAccount(unittest.TestCase): # get test mail with message-id as in-reply-to with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-4.raw"), "r") as f: - test_mails = [f.read().replace('{{ message_id }}', last_mail.message_id)] + messages = { + '"INBOX"': { # append_to = ToDo + 'latest_messages': [ + f.read().replace('{{ message_id }}', last_mail.message_id) + ], + 'seen_status': { + 2: 'UNSEEN' + }, + 'uid_list': [2] + } + } # pull the mail + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") - email_account.receive(test_mails=test_mails) + TestEmailAccount.mocked_email_receive(email_account, messages) comm_list = frappe.get_all("Communication", filters={"sender":"test_sender@example.com"}, fields=["name", "reference_doctype", "reference_name"]) From 84501c663ea9c30ff3d354915e5df5f0fd4ff1e0 Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Tue, 8 Feb 2022 08:33:09 +0530 Subject: [PATCH 21/23] fix: use new mocked_inbound_mail in test_email - remove in_test block from production code --- .../doctype/email_account/email_account.py | 3 --- .../email_account/test_email_account.py | 6 ++--- frappe/tests/test_email.py | 26 ++++++++++++++++++- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index feef9dc234..f20a25f88f 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -471,9 +471,6 @@ class EmailAccount(Document): # only append the emails with status != 'SEEN' if sync option is set to 'UNSEEN' mails.append(InboundMail(message, self, uid, seen_status, append_to)) - if frappe.local.flags.in_test: - return [InboundMail(msg, self) for msg in test_mails or []] - if not self.enable_incoming: return [] diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index fc8b678fde..06c4323f4e 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -386,10 +386,9 @@ class TestEmailAccount(unittest.TestCase): self.assertEqual(inbox_mails, 2) self.assertEqual(test_folder_mails, 1) - @patch("frappe.local.flags.in_test", False) @patch("frappe.email.receive.EmailServer.select_imap_folder", return_value=True) @patch("frappe.email.receive.EmailServer.logout", side_effect=lambda: None) - def mocked_get_inbound_mails(email_account, messages={}, mocked_logout=None, mocked_select_imap_folder=None, mocked_in_test=None): + def mocked_get_inbound_mails(email_account, messages={}, mocked_logout=None, mocked_select_imap_folder=None): from frappe.email.receive import EmailServer def get_mocked_messages(**kwargs): @@ -400,10 +399,9 @@ class TestEmailAccount(unittest.TestCase): return mails - @patch("frappe.local.flags.in_test", False) @patch("frappe.email.receive.EmailServer.select_imap_folder", return_value=True) @patch("frappe.email.receive.EmailServer.logout", side_effect=lambda: None) - def mocked_email_receive(email_account, messages={}, mocked_logout=None, mocked_select_imap_folder=None, mocked_in_test=None): + def mocked_email_receive(email_account, messages={}, mocked_logout=None, mocked_select_imap_folder=None): def get_mocked_messages(**kwargs): return messages[kwargs["folder"]] diff --git a/frappe/tests/test_email.py b/frappe/tests/test_email.py index ef9515f5ba..34c401b7b0 100644 --- a/frappe/tests/test_email.py +++ b/frappe/tests/test_email.py @@ -3,6 +3,8 @@ import unittest, frappe, re, email +from frappe.email.doctype.email_account.test_email_account import TestEmailAccount + test_dependencies = ['Email Account'] class TestEmail(unittest.TestCase): @@ -173,12 +175,34 @@ class TestEmail(unittest.TestCase): frappe.db.delete("Communication", {"sender": "sukh@yyy.com"}) with open(frappe.get_app_path('frappe', 'tests', 'data', 'email_with_image.txt'), 'r') as raw: - mails = email_account.get_inbound_mails(test_mails=[raw.read()]) + messages = { + '"INBOX"': { # append_to = ToDo + 'latest_messages': [ + raw.read() + ], + 'seen_status': { + 2: 'UNSEEN' + }, + 'uid_list': [2] + } + } + + email_account = frappe.get_doc("Email Account", "_Test Email Account 1") + changed_flag = False + if not email_account.enable_incoming: + email_account.enable_incoming = True + changed_flag = True + mails = TestEmailAccount.mocked_get_inbound_mails(email_account, messages) + + # mails = email_account.get_inbound_mails(test_mails=[raw.read()]) communication = mails[0].process() self.assertTrue(re.search(''']*src=["']/private/files/rtco1.png[^>]*>''', communication.content)) self.assertTrue(re.search(''']*src=["']/private/files/rtco2.png[^>]*>''', communication.content)) + if changed_flag: + email_account.enable_incoming = False + if __name__ == '__main__': frappe.connect() From b978b5a70be3b7c091602fc558fe9588ba3c87ad Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 8 Feb 2022 12:01:11 +0530 Subject: [PATCH 22/23] test: Fix mocked method and formatting issues --- .../email_account/test_email_account.py | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index 06c4323f4e..c0ce177f4b 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -46,7 +46,8 @@ class TestEmailAccount(unittest.TestCase): cleanup("test_sender@example.com") messages = { - '"INBOX"': { # append_to = ToDo + # append_to = ToDo + '"INBOX"': { 'latest_messages': [ self.get_test_mail('incoming-1.raw') ], @@ -54,7 +55,7 @@ class TestEmailAccount(unittest.TestCase): 2: 'UNSEEN' }, 'uid_list': [2] - } + } } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") @@ -83,7 +84,8 @@ class TestEmailAccount(unittest.TestCase): frappe.delete_doc("File", existing_file.name) messages = { - '"INBOX"': { # append_to = ToDo + # append_to = ToDo + '"INBOX"': { 'latest_messages': [ self.get_test_mail('incoming-2.raw') ], @@ -91,7 +93,7 @@ class TestEmailAccount(unittest.TestCase): 2: 'UNSEEN' }, 'uid_list': [2] - } + } } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") @@ -113,7 +115,8 @@ class TestEmailAccount(unittest.TestCase): cleanup("test_sender@example.com") messages = { - '"INBOX"': { # append_to = ToDo + # append_to = ToDo + '"INBOX"': { 'latest_messages': [ self.get_test_mail('incoming-3.raw') ], @@ -121,7 +124,7 @@ class TestEmailAccount(unittest.TestCase): 2: 'UNSEEN' }, 'uid_list': [2] - } + } } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") @@ -135,7 +138,8 @@ class TestEmailAccount(unittest.TestCase): cleanup("test_sender@example.com") messages = { - '"INBOX"': { # append_to = ToDo + # append_to = ToDo + '"INBOX"': { 'latest_messages': [ self.get_test_mail('incoming-4.raw') ], @@ -143,7 +147,7 @@ class TestEmailAccount(unittest.TestCase): 2: 'UNSEEN' }, 'uid_list': [2] - } + } } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") @@ -199,7 +203,7 @@ class TestEmailAccount(unittest.TestCase): 2: 'UNSEEN' }, 'uid_list': [2] - } + } } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") @@ -229,7 +233,7 @@ class TestEmailAccount(unittest.TestCase): 3: 'UNSEEN' }, 'uid_list': [2, 3] - } + } } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") @@ -257,7 +261,8 @@ class TestEmailAccount(unittest.TestCase): # get test mail with message-id as in-reply-to with open(os.path.join(os.path.dirname(__file__), "test_mails", "reply-4.raw"), "r") as f: messages = { - '"INBOX"': { # append_to = ToDo + # append_to = ToDo + '"INBOX"': { 'latest_messages': [ f.read().replace('{{ message_id }}', last_mail.message_id) ], @@ -265,11 +270,10 @@ class TestEmailAccount(unittest.TestCase): 2: 'UNSEEN' }, 'uid_list': [2] - } + } } # pull the mail - email_account = frappe.get_doc("Email Account", "_Test Email Account 1") TestEmailAccount.mocked_email_receive(email_account, messages) @@ -284,7 +288,8 @@ class TestEmailAccount(unittest.TestCase): cleanup("test_sender@example.com") messages = { - '"INBOX"': { # append_to = ToDo + # append_to = ToDo + '"INBOX"': { 'latest_messages': [ self.get_test_mail('incoming-1.raw') ], @@ -292,7 +297,7 @@ class TestEmailAccount(unittest.TestCase): 2: 'UNSEEN' }, 'uid_list': [2] - } + } } email_account = frappe.get_doc("Email Account", "_Test Email Account 1") @@ -343,7 +348,8 @@ class TestEmailAccount(unittest.TestCase): mail_content_3 = self.get_test_mail(fname="incoming-3.raw") messages = { - '"INBOX"': { # append_to = ToDo + # append_to = ToDo + '"INBOX"': { 'latest_messages': [ mail_content_1, mail_content_2 @@ -354,7 +360,8 @@ class TestEmailAccount(unittest.TestCase): }, 'uid_list': [0,1] }, - '"Test Folder"': { # append_to = Communication + # append_to = Communication + '"Test Folder"': { 'latest_messages': [ mail_content_3 ], @@ -392,22 +399,21 @@ class TestEmailAccount(unittest.TestCase): from frappe.email.receive import EmailServer def get_mocked_messages(**kwargs): - return messages[kwargs["folder"]] + return messages.get(kwargs["folder"], {}) with patch.object(EmailServer, "get_messages", side_effect=get_mocked_messages): mails = email_account.get_inbound_mails() return mails - + @patch("frappe.email.receive.EmailServer.select_imap_folder", return_value=True) @patch("frappe.email.receive.EmailServer.logout", side_effect=lambda: None) def mocked_email_receive(email_account, messages={}, mocked_logout=None, mocked_select_imap_folder=None): def get_mocked_messages(**kwargs): - return messages[kwargs["folder"]] + return messages.get(kwargs["folder"], {}) from frappe.email.receive import EmailServer with patch.object(EmailServer, "get_messages", side_effect=get_mocked_messages): - email_account = frappe.get_doc("Email Account", "_Test Email Account 1") email_account.receive() class TestInboundMail(unittest.TestCase): From cb25d894b4c6804a2cbd074ed88267eab2aa0dcc Mon Sep 17 00:00:00 2001 From: kamaljohnson Date: Tue, 8 Feb 2022 12:54:51 +0530 Subject: [PATCH 23/23] refactor: code cleanup --- frappe/email/doctype/email_account/email_account.py | 10 +++++----- .../email/doctype/email_account/test_email_account.py | 6 ++++-- frappe/tests/test_email.py | 3 ++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index f20a25f88f..3a1b683398 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -421,10 +421,10 @@ class EmailAccount(Document): def get_failed_attempts_count(self): return cint(frappe.cache().get('{0}:email-account-failed-attempts'.format(self.name))) - def receive(self, test_mails=None): + def receive(self): """Called by scheduler to receive emails from this EMail account using POP3/IMAP.""" exceptions = [] - inbound_mails = self.get_inbound_mails(test_mails=test_mails) + inbound_mails = self.get_inbound_mails() for mail in inbound_mails: try: communication = mail.process() @@ -457,7 +457,7 @@ class EmailAccount(Document): if exceptions: raise Exception(frappe.as_json(exceptions)) - def get_inbound_mails(self, test_mails=None) -> List[InboundMail]: + def get_inbound_mails(self) -> List[InboundMail]: """retrive and return inbound mails. """ @@ -466,8 +466,8 @@ class EmailAccount(Document): def process_mail(messages, append_to=None): for index, message in enumerate(messages.get("latest_messages", [])): uid = messages['uid_list'][index] if messages.get('uid_list') else None - seen_status = 1 if messages.get('seen_status', {}).get(uid) == 'SEEN' else 0 - if not (self.email_sync_option == 'UNSEEN' and seen_status): + seen_status = messages.get('seen_status', {}).get(uid) + if self.email_sync_option != 'UNSEEN' or seen_status != "SEEN": # only append the emails with status != 'SEEN' if sync option is set to 'UNSEEN' mails.append(InboundMail(message, self, uid, seen_status, append_to)) diff --git a/frappe/email/doctype/email_account/test_email_account.py b/frappe/email/doctype/email_account/test_email_account.py index c0ce177f4b..f609c2947d 100644 --- a/frappe/email/doctype/email_account/test_email_account.py +++ b/frappe/email/doctype/email_account/test_email_account.py @@ -195,7 +195,8 @@ class TestEmailAccount(unittest.TestCase): # parse reply messages = { - '"INBOX"': { # append_to = ToDo + # append_to = ToDo + '"INBOX"': { 'latest_messages': [ raw ], @@ -226,7 +227,8 @@ class TestEmailAccount(unittest.TestCase): # parse reply messages = { - '"INBOX"': { # append_to = ToDo + # append_to = ToDo + '"INBOX"': { 'latest_messages': test_mails, 'seen_status': { 2: 'UNSEEN', diff --git a/frappe/tests/test_email.py b/frappe/tests/test_email.py index 34c401b7b0..ad9f8fdd11 100644 --- a/frappe/tests/test_email.py +++ b/frappe/tests/test_email.py @@ -176,7 +176,8 @@ class TestEmail(unittest.TestCase): with open(frappe.get_app_path('frappe', 'tests', 'data', 'email_with_image.txt'), 'r') as raw: messages = { - '"INBOX"': { # append_to = ToDo + # append_to = ToDo + '"INBOX"': { 'latest_messages': [ raw.read() ],