Преглед на файлове

chore(typing): Add typing, style fixes

This was going to be a fix at first. Until I realised it couldn't...so I
removed the changes and kept the things back that helped me debug the
issue
version-14
Gavin D'souza преди 3 години
родител
ревизия
5503e18817
променени са 5 файла, в които са добавени 52 реда и са изтрити 39 реда
  1. +17
    -15
      frappe/core/doctype/communication/email.py
  2. +10
    -5
      frappe/core/doctype/communication/mixins.py
  3. +4
    -6
      frappe/email/doctype/email_account/email_account.py
  4. +19
    -12
      frappe/email/doctype/email_queue/email_queue.py
  5. +2
    -1
      frappe/website/utils.py

+ 17
- 15
frappe/core/doctype/communication/email.py Целия файл

@@ -1,29 +1,32 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE # License: MIT. See LICENSE


import frappe
import json import json
from email.utils import formataddr
from frappe.core.utils import get_parent_doc
from frappe.utils import (get_url, get_formatted_email, cint, list_to_str,
validate_email_address, split_emails, parse_addr, get_datetime)
from frappe.email.email_body import get_message_id
from typing import TYPE_CHECKING, Dict

import frappe
import frappe.email.smtp import frappe.email.smtp
import time
from frappe import _ from frappe import _
from frappe.utils.background_jobs import enqueue
from frappe.email.email_body import get_message_id
from frappe.utils import (cint, get_datetime, get_formatted_email,
list_to_str, split_emails, validate_email_address)

if TYPE_CHECKING:
from frappe.core.doctype.communication.communication import Communication



OUTGOING_EMAIL_ACCOUNT_MISSING = _(""" OUTGOING_EMAIL_ACCOUNT_MISSING = _("""
Unable to send mail because of a missing email account. Unable to send mail because of a missing email account.
Please setup default Email Account from Setup > Email > Email Account Please setup default Email Account from Setup > Email > Email Account
""") """)



@frappe.whitelist() @frappe.whitelist()
def make(doctype=None, name=None, content=None, subject=None, sent_or_received = "Sent", def make(doctype=None, name=None, content=None, subject=None, sent_or_received = "Sent",
sender=None, sender_full_name=None, recipients=None, communication_medium="Email", send_email=False, sender=None, sender_full_name=None, recipients=None, communication_medium="Email", send_email=False,
print_html=None, print_format=None, attachments='[]', send_me_a_copy=False, cc=None, bcc=None, print_html=None, print_format=None, attachments='[]', send_me_a_copy=False, cc=None, bcc=None,
flags=None, read_receipt=None, print_letterhead=True, email_template=None, communication_type=None, flags=None, read_receipt=None, print_letterhead=True, email_template=None, communication_type=None,
ignore_permissions=False):
ignore_permissions=False) -> Dict[str, str]:
"""Make a new communication. """Make a new communication.


:param doctype: Reference DocType. :param doctype: Reference DocType.
@@ -56,7 +59,7 @@ def make(doctype=None, name=None, content=None, subject=None, sent_or_received =
cc = list_to_str(cc) if isinstance(cc, list) else cc cc = list_to_str(cc) if isinstance(cc, list) else cc
bcc = list_to_str(bcc) if isinstance(bcc, list) else bcc bcc = list_to_str(bcc) if isinstance(bcc, list) else bcc


comm = frappe.get_doc({
comm: "Communication" = frappe.get_doc({
"doctype":"Communication", "doctype":"Communication",
"subject": subject, "subject": subject,
"content": content, "content": content,
@@ -93,12 +96,13 @@ def make(doctype=None, name=None, content=None, subject=None, sent_or_received =
send_me_a_copy=send_me_a_copy, print_letterhead=print_letterhead) send_me_a_copy=send_me_a_copy, print_letterhead=print_letterhead)


emails_not_sent_to = comm.exclude_emails_list(include_sender=send_me_a_copy) emails_not_sent_to = comm.exclude_emails_list(include_sender=send_me_a_copy)

return { return {
"name": comm.name, "name": comm.name,
"emails_not_sent_to": ", ".join(emails_not_sent_to or [])
"emails_not_sent_to": ", ".join(emails_not_sent_to)
} }


def validate_email(doc):
def validate_email(doc: "Communication") -> None:
"""Validate Email Addresses of Recipients and CC""" """Validate Email Addresses of Recipients and CC"""
if not (doc.communication_type=="Communication" and doc.communication_medium == "Email") or doc.flags.in_receive: if not (doc.communication_type=="Communication" and doc.communication_medium == "Email") or doc.flags.in_receive:
return return
@@ -114,8 +118,6 @@ def validate_email(doc):
for email in split_emails(doc.bcc): for email in split_emails(doc.bcc):
validate_email_address(email, throw=True) validate_email_address(email, throw=True)


# validate sender

def set_incoming_outgoing_accounts(doc): def set_incoming_outgoing_accounts(doc):
from frappe.email.doctype.email_account.email_account import EmailAccount from frappe.email.doctype.email_account.email_account import EmailAccount
incoming_email_account = EmailAccount.find_incoming( incoming_email_account = EmailAccount.find_incoming(


+ 10
- 5
frappe/core/doctype/communication/mixins.py Целия файл

@@ -1,3 +1,4 @@
from typing import List
import frappe import frappe
from frappe import _ from frappe import _
from frappe.core.utils import get_parent_doc from frappe.core.utils import get_parent_doc
@@ -194,14 +195,18 @@ class CommunicationEmailMixin:
return _("Leave this conversation") return _("Leave this conversation")
return '' return ''


def exclude_emails_list(self, is_inbound_mail_communcation=False, include_sender=False):
def exclude_emails_list(self, is_inbound_mail_communcation=False, include_sender=False) -> List:
"""List of mail id's excluded while sending mail. """List of mail id's excluded while sending mail.
""" """
all_ids = self.get_all_email_addresses(exclude_displayname=True) all_ids = self.get_all_email_addresses(exclude_displayname=True)
final_ids = self.mail_recipients(is_inbound_mail_communcation = is_inbound_mail_communcation) + \
self.mail_bcc(is_inbound_mail_communcation = is_inbound_mail_communcation) + \
self.mail_cc(is_inbound_mail_communcation = is_inbound_mail_communcation, include_sender=include_sender)
return set(all_ids) - set(final_ids)

final_ids = (
self.mail_recipients(is_inbound_mail_communcation=is_inbound_mail_communcation)
+ self.mail_bcc(is_inbound_mail_communcation=is_inbound_mail_communcation)
+ self.mail_cc(is_inbound_mail_communcation=is_inbound_mail_communcation, include_sender=include_sender)
)

return list(set(all_ids) - set(final_ids))


def get_assignees(self): def get_assignees(self):
"""Get owners of the reference document. """Get owners of the reference document.


+ 4
- 6
frappe/email/doctype/email_account/email_account.py Целия файл

@@ -1,5 +1,6 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
# License: MIT. See LICENSE # License: MIT. See LICENSE

import email.utils import email.utils
import functools import functools
import imaplib import imaplib
@@ -7,6 +8,7 @@ import socket
import time import time
from datetime import datetime, timedelta from datetime import datetime, timedelta
from poplib import error_proto from poplib import error_proto
from typing import List


import frappe import frappe
from frappe import _, are_emails_muted, safe_encode from frappe import _, are_emails_muted, safe_encode
@@ -82,9 +84,6 @@ class EmailAccount(Document):
if frappe.local.flags.in_patch or frappe.local.flags.in_test: if frappe.local.flags.in_patch or frappe.local.flags.in_test:
return return


#if self.enable_incoming and not self.append_to:
# frappe.throw(_("Append To is mandatory for incoming mails"))

if (not self.awaiting_password and not frappe.local.flags.in_install if (not self.awaiting_password and not frappe.local.flags.in_install
and not frappe.local.flags.in_patch): and not frappe.local.flags.in_patch):
if self.password or self.smtp_server in ('127.0.0.1', 'localhost'): if self.password or self.smtp_server in ('127.0.0.1', 'localhost'):
@@ -458,7 +457,7 @@ class EmailAccount(Document):
if exceptions: if exceptions:
raise Exception(frappe.as_json(exceptions)) raise Exception(frappe.as_json(exceptions))


def get_inbound_mails(self, test_mails=None):
def get_inbound_mails(self, test_mails=None) -> List[InboundMail]:
"""retrive and return inbound mails. """retrive and return inbound mails.


""" """
@@ -625,7 +624,6 @@ class EmailAccount(Document):
if frappe.db.exists("Email Account", {"enable_automatic_linking": 1, "name": ('!=', self.name)}): if frappe.db.exists("Email Account", {"enable_automatic_linking": 1, "name": ('!=', self.name)}):
frappe.throw(_("Automatic Linking can be activated only for one Email Account.")) frappe.throw(_("Automatic Linking can be activated only for one Email Account."))



def append_email_to_sent_folder(self, message): def append_email_to_sent_folder(self, message):
email_server = None email_server = None
try: try:


+ 19
- 12
frappe/email/doctype/email_queue/email_queue.py Целия файл

@@ -20,6 +20,7 @@ from frappe.email.queue import get_unsubcribed_url, get_unsubscribe_message
from frappe.email.email_body import add_attachment, get_formatted_html, get_email from frappe.email.email_body import add_attachment, get_formatted_html, get_email
from frappe.utils import cint, split_emails, add_days, nowdate, cstr, get_hook_method from frappe.utils import cint, split_emails, add_days, nowdate, cstr, get_hook_method
from frappe.email.doctype.email_account.email_account import EmailAccount from frappe.email.doctype.email_account.email_account import EmailAccount
from frappe.query_builder.utils import DocType




MAX_RETRY_COUNT = 3 MAX_RETRY_COUNT = 3
@@ -477,18 +478,24 @@ class QueueBuilder:


all_ids = list(set(self.recipients + self.cc)) all_ids = list(set(self.recipients + self.cc))


EmailUnsubscribe = frappe.qb.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
)
).distinct()
).run(pluck=True)
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
)
)
).distinct()
).run(pluck=True)

self._unsubscribed_user_emails = unsubscribed or [] self._unsubscribed_user_emails = unsubscribed or []
return self._unsubscribed_user_emails return self._unsubscribed_user_emails




+ 2
- 1
frappe/website/utils.py Целия файл

@@ -5,6 +5,7 @@ import mimetypes
import os import os
import re import re
from functools import wraps from functools import wraps
from typing import Dict, Optional


import yaml import yaml
from six import iteritems from six import iteritems
@@ -453,7 +454,7 @@ def cache_html(func):


return cache_html_decorator return cache_html_decorator


def build_response(path, data, http_status_code, headers=None):
def build_response(path, data, http_status_code, headers: Optional[Dict] = None):
# build response # build response
response = Response() response = Response()
response.data = set_content_type(response, data, path) response.data = set_content_type(response, data, path)


Зареждане…
Отказ
Запис