Skip to content

Commit

Permalink
Merge pull request #57 from kartoza/feature/add-resend
Browse files Browse the repository at this point in the history
Add resend notification
  • Loading branch information
danangmassandy authored Aug 20, 2024
2 parents 665fa3e + 97a1bf7 commit 71e4d45
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 7 deletions.
15 changes: 14 additions & 1 deletion deployment/.template.env
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,17 @@ MINIO_ACCESS_KEY_ID=miniocplus
MINIO_SECRET_ACCESS_KEY=miniocplus
MINIO_ENDPOINT=http://minio:9000
MINIO_BUCKET_NAME=cplus
MINIO_BROWSER_REDIRECT_URL=
MINIO_BROWSER_REDIRECT_URL=

# ---------------------------------
# EMAIL
# ---------------------------------
DEFAULT_FROM_EMAIL=

# SELECT BETWEEN
# - core.resend_email_backend.ResendBackend
# - django.core.mail.backends.smtp.EmailBackend
EMAIL_BACKEND=core.resend_email_backend.ResendBackend

# if core.resend_email_backend.ResendBackend
RESEND_API_KEY=
3 changes: 2 additions & 1 deletion deployment/.template.test.env
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ AWS_S3_BUCKET_NAME=cpluss3
MINIO_ACCESS_KEY_ID=miniocplus
MINIO_SECRET_ACCESS_KEY=miniocplus
MINIO_ENDPOINT=http://minio:9000
MINIO_BUCKET_NAME=cplus
MINIO_BUCKET_NAME=cplus
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
2 changes: 2 additions & 0 deletions deployment/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ x-common-variables: &common-variables
MINIO_ENDPOINT: ${MINIO_ENDPOINT}
MINIO_BUCKET_NAME: ${MINIO_BUCKET_NAME:-cplus}
MINIO_BROWSER_REDIRECT_URL: ${MINIO_BROWSER_REDIRECT_URL}
DEFAULT_FROM_EMAIL: ${DEFAULT_FROM_EMAIL}
RESEND_API_KEY: ${RESEND_API_KEY}


x-common-django:
Expand Down
96 changes: 96 additions & 0 deletions django_project/core/resend_email_backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# coding=utf-8
"""
CPLUS-API.
.. note:: Resend email backend.
"""

import base64
import mimetypes

import requests
from django.conf import settings
from django.core.mail.backends.base import BaseEmailBackend


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 = settings.RESEND_API_KEY
from_email = settings.DEFAULT_FROM_EMAIL
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
try:
if email.alternatives:
for alternative in email.alternatives:
content, content_type = alternative
if content_type == "text/html":
payload["html"] = content
except AttributeError:
pass

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)
if response.status_code != 200:
raise ConnectionError(response.text)
return response
2 changes: 1 addition & 1 deletion django_project/core/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,4 @@
}

LOGIN_URL = '/account/login/'
LOGIN_REDIRECT_URL = '/'
LOGIN_REDIRECT_URL = '/'
5 changes: 3 additions & 2 deletions django_project/core/settings/prod.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@
EMAIL_USE_TLS = ast.literal_eval(os.environ.get('EMAIL_USE_TLS', 'False'))
EMAIL_USE_SSL = ast.literal_eval(os.environ.get('EMAIL_USE_SSL', 'False'))
EMAIL_SUBJECT_PREFIX = os.environ.get('EMAIL_SUBJECT_PREFIX', '')

SERVER_EMAIL = os.environ.get('ADMIN_EMAIL', '[email protected]')
RESEND_API_KEY = os.environ.get('RESEND_API_KEY')
DEFAULT_FROM_EMAIL = os.environ.get(
'DEFAULT_FROM_EMAIL', '[email protected]')
'DEFAULT_FROM_EMAIL', '[email protected]')


LOGGING = {
'version': 1,
Expand Down
1 change: 1 addition & 0 deletions django_project/core/settings/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
},
}

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
29 changes: 29 additions & 0 deletions django_project/cplus_api/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import uuid
import json
import datetime
from unittest.mock import patch
from django.test import TestCase
from django.core.mail import send_mail
from django.conf import settings
from cplus_api.utils.api_helper import (
todict,
CustomJsonEncoder,
Expand Down Expand Up @@ -59,6 +62,32 @@ def test_get_layer_type(self):
filepath = '/tmp/test/file.netcdf'
self.assertEqual(get_layer_type(filepath), -1)

def test_email_send(self):
"""Test email send when scenario is finished."""
self.recipients = []
parent = self

def mock_send_fn(self, fail_silently=False):
"""Mock send messages."""
parent.recipients = self.recipients()
return 0

with patch(
"django.core.mail.EmailMessage.send", mock_send_fn
):
send_mail(
"Test",
None,
settings.DEFAULT_FROM_EMAIL,
['[email protected]', '[email protected]'],
html_message="Test message"
)
parent.assertEqual(len(self.recipients), 2)
parent.assertEqual(
self.recipients,
['[email protected]', '[email protected]']
)


class TestCustomJSONEncoder(TestCase):
def test_uuid(self):
Expand Down
4 changes: 2 additions & 2 deletions django_project/cplus_api/utils/worker_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import logging
import traceback
import subprocess
from django.core.mail import send_mail
from django.conf import settings
from django.utils import timezone
from django.template.loader import render_to_string
from django.core.mail import send_mail
from cplus.models.base import (
Activity,
NcsPathway,
Expand Down Expand Up @@ -784,7 +784,7 @@ def notify_user(self, is_success: bool):
send_mail(
subject,
None,
settings.SERVER_EMAIL,
settings.DEFAULT_FROM_EMAIL,
[self.scenario_task.submitted_by.email],
html_message=message
)
Expand Down

0 comments on commit 71e4d45

Please sign in to comment.