From 32a59e19a6462d6f85ab7bb85f01ec40aa0cfc4a Mon Sep 17 00:00:00 2001 From: Ritwik Puri Date: Sat, 26 Aug 2023 11:22:46 +0530 Subject: [PATCH] docs: email architecture (#22189) * docs: email architecture * chore: remove marking emails as read dead code from EmailAccount controller --- .../email/assets/images/email-pull-flow.png | Bin 0 -> 19057 bytes .../doctype/email_account/email_account.py | 49 ------------- frappe/email/email.md | 65 ++++++++++++++++++ 3 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 frappe/email/assets/images/email-pull-flow.png create mode 100644 frappe/email/email.md diff --git a/frappe/email/assets/images/email-pull-flow.png b/frappe/email/assets/images/email-pull-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..1518f9f6d589be0d5fdeded7b212896b54134cd3 GIT binary patch literal 19057 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 literal 0 HcmV?d00001 diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index bdae8d1d3c..149e42dd80 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -652,55 +652,6 @@ class EmailAccount(Document): else: return self.email_sync_option or "UNSEEN" - def mark_emails_as_read_unread(self, email_server=None, folder_name="INBOX"): - """mark Email Flag Queue of self.email_account mails as read""" - if not self.use_imap: - return - - EmailFlagQ = frappe.qb.DocType("Email Flag Queue") - flags = ( - frappe.qb.from_(EmailFlagQ) - .select(EmailFlagQ.name, EmailFlagQ.communication, EmailFlagQ.uid, EmailFlagQ.action) - .where(EmailFlagQ.is_completed == 0) - .where(EmailFlagQ.email_account == frappe.db.escape(self.name)) - ).run(as_dict=True) - - uid_list = {flag.get("uid", None): flag.get("action", "Read") for flag in flags} - if flags and uid_list: - if not email_server: - email_server = self.get_incoming_server() - if not email_server: - return - email_server.update_flag(folder_name, uid_list=uid_list) - - # mark communication as read - docnames = ",".join( - "'%s'" % flag.get("communication") for flag in flags if flag.get("action") == "Read" - ) - self.set_communication_seen_status(docnames, seen=1) - - # mark communication as unread - docnames = ",".join( - ["'%s'" % flag.get("communication") for flag in flags if flag.get("action") == "Unread"] - ) - self.set_communication_seen_status(docnames, seen=0) - - docnames = ",".join(["'%s'" % flag.get("name") for flag in flags]) - - EmailFlagQueue = frappe.qb.DocType("Email Flag Queue") - frappe.qb.update(EmailFlagQueue).set(EmailFlagQueue.is_completed, 1).where( - EmailFlagQueue.name.isin(docnames) - ).run() - - def set_communication_seen_status(self, docnames, seen=0): - """mark Email Flag Queue of self.email_account mails as read""" - if not docnames: - return - Communication = frappe.qb.from_("Communication") - frappe.qb.update(Communication).set(Communication.seen == seen).where( - Communication.name.isin(docnames) - ).run() - def check_automatic_linking_email_account(self): if self.enable_automatic_linking: if not self.enable_incoming: diff --git a/frappe/email/email.md b/frappe/email/email.md new file mode 100644 index 0000000000..ed8ed5f592 --- /dev/null +++ b/frappe/email/email.md @@ -0,0 +1,65 @@ +# Email Architecture + +This document describes the high-level architecture of how emails work in frappe. + +> NOTE: There are mentions of different types of workers to execute jobs from different types of queues in the explanations below, however only a single type of worker can also be used to do the same. + +### High-Level View + +#### Pulling/Sending: + +![email-pull-flow](assets/images/email-pull-flow.png) + +The same follows for email sending with the only difference being in the jobs queued. + +The scheduler schedules/pushes the `email.pull`/`queue.flush` job into the default queue which is picked up by the default worker and upon execution enqueues `pull_from_email_account`/`send_mail` job into the short queue and the job is then picked up by the short worker and the email is pulled in/sent out of the system. + + +### Code Map + +This section talks briefly about various important directories/files. + +#### `doctype/email_queue` + +Contains all logic about email sending. Every email to be sent is stored in `Email Queue` DocType (Newsletter(s) included). + +#### `receive.py` + +Contains all the logic and classes about email receiving. + +#### `doctype/email_account` + +Contains logic for validating connection/auth for email account(s). + +Also, contains the abstraction for facilitating email receiving. + +#### `doctype/newsletter` + +Contains all the logic about newsletter scheduling, subscribing and unsubscribing. + +Newsletter has a similar design as to how normal emails are sent except for the initial scheduled job (`newsletter.send_scheduled_email`) and the fact that newsletter recipients are batched, primarily for SMTP connection reusing & mitigating any potential timeouts (available as a general feature as well). + +Each batch is queued as a separate job (`QueueBuilder.send_emails`) into the long queue by the default worker which is then picked up by the long worker. + +#### `doctype/notification` + +Contains all logic about handling various types of notifications by the system. + +#### `email_body.py` + +Contains logic about creating the email body. We use Python's email std lib for body generation. + +The email message format/syntax is described in [RFC5322](https://datatracker.ietf.org/doc/html/rfc5322) + + +### Observability + +At the application level, + +`RQ Job` DocType is the most useful in knowing the status of any type of "recent" email job (pull/send). + +`Email Queue` DocType is self-contained and stores all the errored out (along with traceback) as well as the sent/partially sent mails from the system. + +`Communication` DocType stores all the successfully received emails and `Unhandled Email` DocType stores all the "unhandled" ones during receiving. + +Apart from these, the `Error Log` DocType also comes into help from time to time.