diff --git a/frappe/email/receive.py b/frappe/email/receive.py index a6c6c00d61..f0b49de7eb 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -190,7 +190,7 @@ class EmailServer: if cint(self.settings.use_imap): self.check_imap_uidvalidity(folder) - readonly = False if self.settings.email_sync_rule == "UNSEEN" else True + readonly = self.settings.email_sync_rule != "UNSEEN" self.imap.select(folder, readonly=readonly) response, message = self.imap.uid("search", None, self.settings.email_sync_rule) @@ -213,27 +213,32 @@ class EmailServer: if not uid_validity or uid_validity != current_uid_validity: # uidvalidity changed & all email uids are reindexed by server - Communication = frappe.qb.DocType("Communication") - frappe.qb.update(Communication).set(Communication.uid, -1).where( - Communication.communication_medium == "Email" - ).where(Communication.email_account == self.settings.email_account).run() + frappe.db.set_value( + "Communication", + {"communication_medium": "Email", "email_account": self.settings.email_account}, + "uid", + -1, + update_modified=False, + ) if self.settings.use_imap: # Remove {"} quotes that are added to handle spaces in IMAP Folder names if folder[0] == folder[-1] == '"': folder = folder[1:-1] - # new update for the IMAP Folder DocType - IMAPFolder = frappe.qb.DocType("IMAP Folder") - frappe.qb.update(IMAPFolder).set(IMAPFolder.uidvalidity, current_uid_validity).set( - IMAPFolder.uidnext, uidnext - ).where(IMAPFolder.parent == self.settings.email_account_name).where( - IMAPFolder.folder_name == folder - ).run() + + frappe.db.set_value( + "IMAP Folder", + {"parent": self.settings.email_account_name, "folder_name": folder}, + {"uidvalidity": current_uid_validity, "uidnext": uidnext}, + update_modified=False, + ) else: - EmailAccount = frappe.qb.DocType("Email Account") - frappe.qb.update(EmailAccount).set(EmailAccount.uidvalidity, current_uid_validity).set( - EmailAccount.uidnext, uidnext - ).where(EmailAccount.name == self.settings.email_account_name).run() + frappe.db.set_value( + "Email Account", + self.settings.email_account_name, + {"uidvalidity": current_uid_validity, "uidnext": uidnext}, + update_modified=False, + ) sync_count = 100 if uid_validity else int(self.settings.initial_sync_count) from_uid = 1 if uidnext < (sync_count + 1) or (uidnext - sync_count) < 1 else uidnext - sync_count @@ -245,10 +250,7 @@ class EmailServer: pattern = rf"(?<={cmd} )[0-9]*" match = re.search(pattern, response.decode("utf-8"), re.U | re.I) - if match: - return match.group(0) - else: - return None + return match[0] if match else None def retrieve_message(self, uid, msg_num): try: @@ -267,7 +269,7 @@ class EmailServer: except Exception as e: if self.has_login_limit_exceeded(e): - raise LoginLimitExceeded(e) + raise LoginLimitExceeded(e) from e frappe.log_error("Unable to fetch email", self.make_error_msg(uid, msg_num)) @@ -295,20 +297,18 @@ class EmailServer: with suppress(Exception): if not cint(self.settings.use_imap): self.pop.dele(msg_num) - else: - # mark as seen if email sync rule is UNSEEN (syncing only unseen mails) - if self.settings.email_sync_rule == "UNSEEN": - self.imap.uid("STORE", uid, "+FLAGS", "(\\SEEN)") + elif self.settings.email_sync_rule == "UNSEEN": + self.imap.uid("STORE", uid, "+FLAGS", "(\\SEEN)") def is_temporary_system_problem(self, e): messages = ( "-ERR [SYS/TEMP] Temporary system problem. Please try again later.", "Connection timed out", ) - for message in messages: - if message in strip(cstr(e)) or message in strip(cstr(getattr(e, "strerror", ""))): - return True - return False + return any( + message in strip(cstr(e)) or message in strip(cstr(getattr(e, "strerror", ""))) + for message in messages + ) def make_error_msg(self, uid, msg_num): traceback = frappe.get_traceback(with_context=True) @@ -322,14 +322,16 @@ class EmailServer: partial_mail = Email(headers) if partial_mail: - return ( - "\nDate: {date}\nFrom: {from_email}\nSubject: {subject}\n\n\nTraceback: \n{traceback}".format( - date=partial_mail.date, - from_email=partial_mail.from_email, - subject=partial_mail.subject, - traceback=traceback, - ) - ) + return f""" +Date: {partial_mail.date} +From: {partial_mail.from_email} +Subject: {partial_mail.subject} + + +Traceback: +{traceback} +""" + return traceback def update_flag(self, folder, uid_list=None): @@ -415,10 +417,7 @@ class Email: # Convert non-string (e.g. None) # Truncate to 140 chars (can be used as a document name) - self.subject = str(self.subject).strip()[:140] - - if not self.subject: - self.subject = "No Subject" + self.subject = str(self.subject).strip()[:140] or "No Subject" def set_from(self): # gmail mailing-list compatibility @@ -499,12 +498,7 @@ class Email: self.html_content += markdown(text_content) def get_charset(self, part): - """Detect charset.""" - charset = part.get_content_charset() - if not charset: - charset = chardet.detect(safe_encode(cstr(part)))["encoding"] - - return charset + return part.get_content_charset() or chardet.detect(safe_encode(cstr(part)))["encoding"] def get_payload(self, part): charset = self.get_charset(part)