diff --git a/frappe/email/doctype/email_queue/email_queue.py b/frappe/email/doctype/email_queue/email_queue.py index 57ac029d9566..d44688196231 100644 --- a/frappe/email/doctype/email_queue/email_queue.py +++ b/frappe/email/doctype/email_queue/email_queue.py @@ -170,18 +170,13 @@ def send(self, smtp_server_instance: SMTPServer = None, frappe_mail_client: Frap method(self, self.sender, recipient.recipient, message) elif not frappe.flags.in_test or frappe.flags.testing_email: if ctx.email_account_doc.service == "Frappe Mail": - if self.reference_doctype == "Newsletter": - ctx.frappe_mail_client.send_newsletter( - sender=self.sender, - recipients=recipient.recipient, - message=message.decode("utf-8"), - ) - else: - ctx.frappe_mail_client.send_raw( - sender=self.sender, - recipients=recipient.recipient, - message=message.decode("utf-8"), - ) + is_newsletter = self.reference_doctype == "Newsletter" + ctx.frappe_mail_client.send_raw( + sender=self.sender, + recipients=recipient.recipient, + message=message, + is_newsletter=is_newsletter, + ) else: ctx.smtp_server.session.sendmail( from_addr=self.sender, diff --git a/frappe/email/frappemail.py b/frappe/email/frappemail.py index c485fac21510..90223f338d92 100644 --- a/frappe/email/frappemail.py +++ b/frappe/email/frappemail.py @@ -7,7 +7,7 @@ import frappe from frappe import _ from frappe.frappeclient import FrappeClient, FrappeOAuth2Client -from frappe.utils import convert_utc_to_system_timezone, get_datetime, get_datetime_str, get_system_timezone +from frappe.utils import convert_utc_to_system_timezone, get_datetime, get_system_timezone class FrappeMail: @@ -62,9 +62,9 @@ def request( params: dict | None = None, data: dict | None = None, json: dict | None = None, + files: dict | None = None, headers: dict[str, str] | None = None, timeout: int | tuple[int, int] = (60, 120), - raise_exception: bool = True, ) -> Any | None: """Makes a request to the Frappe Mail API.""" @@ -73,8 +73,18 @@ def request( headers = headers or {} headers.update(self.client.headers) + if files: + headers.pop("content-type", None) + response = self.client.session.request( - method=method, url=url, params=params, data=data, json=json, headers=headers, timeout=timeout + method=method, + url=url, + params=params, + data=data, + json=json, + files=files, + headers=headers, + timeout=timeout, ) return self.client.post_process(response) @@ -86,21 +96,16 @@ def validate(self, for_outbound: bool = False, for_inbound: bool = False) -> Non data = {"mailbox": self.mailbox, "for_outbound": for_outbound, "for_inbound": for_inbound} self.request("POST", endpoint=endpoint, data=data) - def send_raw(self, sender: str, recipients: str | list, message: str) -> None: + def send_raw( + self, sender: str, recipients: str | list, message: str | bytes, is_newsletter: bool = False + ) -> None: """Sends an email using the Frappe Mail API.""" endpoint = "/api/method/mail_client.api.outbound.send_raw" - data = {"from_": sender, "to": recipients, "raw_message": message} - self.request("POST", endpoint=endpoint, data=data) - - def send_newsletter(self, sender: str, recipients: str | list, message: str) -> None: - """Sends an newsletter using the Frappe Mail API.""" - - endpoint = "/api/method/mail_client.api.outbound.send_newsletter" - data = {"from_": sender, "to": recipients, "raw_message": message} - self.request("POST", endpoint=endpoint, json=data) + data = {"from_": sender, "to": recipients, "is_newsletter": is_newsletter} + self.request("POST", endpoint=endpoint, data=data, files={"raw_message": message}) - def pull_raw(self, limit: int = 50, last_synced_at: str | None = None) -> dict[str, list[str] | str]: + def pull_raw(self, limit: int = 50, last_synced_at: str | None = None) -> dict[str, str | list[str]]: """Pulls emails from the mailbox using the Frappe Mail API.""" endpoint = "/api/method/mail_client.api.inbound.pull_raw"