From a758e667827df48f8da07bd9195f1b16ea22fd09 Mon Sep 17 00:00:00 2001 From: Dimas Ciputra Date: Thu, 21 Nov 2024 22:05:59 +0000 Subject: [PATCH] Add resend email backend (#166) --- core/email_backend.py | 94 +++++++++++++++++++++++++++++++++++++++++++ core/settings/core.py | 8 +++- 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 core/email_backend.py diff --git a/core/email_backend.py b/core/email_backend.py new file mode 100644 index 0000000..ccaff86 --- /dev/null +++ b/core/email_backend.py @@ -0,0 +1,94 @@ +import base64 +import mimetypes + +import requests +from django.core.mail.backends.base import BaseEmailBackend +from django.conf import settings + +DEFAULT_FROM_EMAIL = settings.DEFAULT_FROM_EMAIL +RESEND_API_KEY = settings.RESEND_API_KEY + + +class ResendBackend(BaseEmailBackend): + """ + A Django email backend that uses the Resend API. + """ + def send_messages(self, email_messages): + """ + Send a list of email messages using the Resend API. + :param email_messages: List of Django email messages. + :return: The number of successfully sent messages. + """ + count = 0 + + for email in email_messages: + response = self._send_via_resend(email) + + if response.status_code == 200: + count += 1 + + return count + + def _send_via_resend(self, email): + """ + Send a single email via Resend. + :param email: A Django EmailMessage object. + :return: The response from the Resend API. + """ + resend_api_key = RESEND_API_KEY + from_email = ( + DEFAULT_FROM_EMAIL if + DEFAULT_FROM_EMAIL else + email.from_email + ) + + # Prepare the payload for the Resend API request + payload = { + "from": from_email, + "to": email.to, + "subject": email.subject, + "text": email.body, + } + + if email.content_subtype == "html": + payload["html"] = email.body + + # Check for HTML content + if email.alternatives: + for alternative in email.alternatives: + content_type, content = alternative + if content_type == "text/html": + payload["html"] = content + + attachments = [] + + for attachment in email.attachments: + if isinstance(attachment, tuple): + filename, content, mime_type = attachment + encoded_content = base64.b64encode(content).decode("utf-8") + else: + filename = attachment + with open(attachment, "rb") as f: + content = f.read() + mime_type, _ = mimetypes.guess_type(filename) + encoded_content = base64.b64encode(content).decode("utf-8") + + attachments.append({ + "filename": filename, + "content": encoded_content, + "content_type": mime_type, + }) + + if attachments: + payload["attachments"] = attachments + + # Prepare headers + headers = { + "Authorization": f"Bearer {resend_api_key}", + "Content-Type": "application/json", + } + + # Make the request to the Resend API + resend_url = "https://api.resend.com/emails" + response = requests.post(resend_url, json=payload, headers=headers) + return response \ No newline at end of file diff --git a/core/settings/core.py b/core/settings/core.py index c3a3048..ae2d136 100644 --- a/core/settings/core.py +++ b/core/settings/core.py @@ -189,7 +189,7 @@ LOGIN_REDIRECT_URL = '/' -EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +EMAIL_BACKEND = 'core.email_backend.ResendBackend' ACCOUNT_EMAIL_REQUIRED = True DBBACKUP_STORAGE_OPTIONS = {'location': 'backups'} @@ -200,3 +200,9 @@ "LOCATION": absolute_path('core', 'cache'), } } + +DEFAULT_FROM_EMAIL = os.environ.get( + 'DEFAULT_FROM_EMAIL', + 'noreply@noreply.kartoza.com') +RESEND_API_KEY = os.environ.get( + 'RESEND_API_KEY', '')