From db0b5adc691f3e05d0b1bec2dba939d79a335270 Mon Sep 17 00:00:00 2001 From: Ahtisham Shahid Date: Wed, 12 Feb 2025 11:33:25 +0500 Subject: [PATCH] fix: resolved issues with ses impl in goal reminder email (#36233) --- .../commands/goal_reminder_email.py | 14 +++-- .../tests/test_goal_reminder_email.py | 55 ++++++++++++++++++- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/lms/djangoapps/course_goals/management/commands/goal_reminder_email.py b/lms/djangoapps/course_goals/management/commands/goal_reminder_email.py index 944a18feff..b6840ca2c0 100644 --- a/lms/djangoapps/course_goals/management/commands/goal_reminder_email.py +++ b/lms/djangoapps/course_goals/management/commands/goal_reminder_email.py @@ -321,20 +321,21 @@ def send_email_using_ses(user, msg): """ Send email using AWS SES """ - msg = presentation.render(DjangoEmailChannel, msg) + render_msg = presentation.render(DjangoEmailChannel, msg) # send rendered email using SES + sender = EmailChannelMixin.get_from_address(msg) - recipient = user.email - subject = EmailChannelMixin.get_subject(msg) - body_text = msg.body - body_html = msg.body_html + + subject = EmailChannelMixin.get_subject(render_msg) + body_text = render_msg.body + body_html = render_msg.body_html try: # Send email response = boto3.client('ses', settings.AWS_SES_REGION_NAME).send_email( Source=sender, Destination={ - 'ToAddresses': [recipient], + 'ToAddresses': [user.email], }, Message={ 'Subject': { @@ -358,3 +359,4 @@ def send_email_using_ses(user, msg): send_ace_message_sent_signal(DjangoEmailChannel, msg) except Exception as e: # pylint: disable=broad-exception-caught log.error(f"Goal Reminder Email: Error sending email using SES: {e}") + raise e diff --git a/lms/djangoapps/course_goals/management/commands/tests/test_goal_reminder_email.py b/lms/djangoapps/course_goals/management/commands/tests/test_goal_reminder_email.py index 3180403791..214fb58219 100644 --- a/lms/djangoapps/course_goals/management/commands/tests/test_goal_reminder_email.py +++ b/lms/djangoapps/course_goals/management/commands/tests/test_goal_reminder_email.py @@ -1,6 +1,10 @@ """Tests for the goal_reminder_email command""" from datetime import datetime + +from botocore.exceptions import NoCredentialsError +from django.contrib.sites.models import Site +from edx_ace import Recipient, Message from pytz import UTC from unittest import mock # lint-amnesty, pylint: disable=wrong-import-order @@ -13,14 +17,17 @@ from freezegun import freeze_time from waffle import get_waffle_flag_model # pylint: disable=invalid-django-waffle-import from common.djangoapps.student.models import CourseEnrollment -from common.djangoapps.student.tests.factories import CourseEnrollmentFactory +from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory +from lms.djangoapps.course_goals.management.commands.goal_reminder_email import send_email_using_ses from lms.djangoapps.course_goals.models import CourseGoalReminderStatus from lms.djangoapps.course_goals.tests.factories import ( CourseGoalFactory, CourseGoalReminderStatusFactory, UserActivityFactory, ) from lms.djangoapps.certificates.data import CertificateStatuses from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory +from openedx.core.djangoapps.ace_common.template_context import get_base_template_context from openedx.core.djangolib.testing.utils import skip_unless_lms +from openedx.core.lib.celery.task_utils import emulate_http_request from openedx.features.course_experience import ENABLE_COURSE_GOALS, ENABLE_SES_FOR_GOALREMINDER # Some constants just for clarity of tests (assuming week starts on a Monday, as March 2021 used below does) @@ -43,6 +50,7 @@ class TestGoalReminderEmailCommand(TestCase): A lot of these methods will hardcode references to March 2021. This is just a convenient anchor point for us because it started on a Monday. Calls to the management command will freeze time so it's during March. """ + def make_valid_goal(self, **kwargs): """Creates a goal that will cause an email to be sent as the goal is valid but has been missed""" kwargs.setdefault('days_per_week', 6) @@ -211,3 +219,48 @@ class TestGoalReminderEmailCommand(TestCase): assert msg.options['transactional'] is True assert 'override_default_channel' not in msg.options assert 'from_address' not in msg.options + + +class TestGoalReminderEmailSES(TestCase): + """ + Tests for the send_email_using_ses function + """ + def test_send_email_using_ses(self): + """ + Test that the send_email_using_ses function sends an email using the SES channel + """ + user = UserFactory() + + options = { + 'transactional': True, + 'from_address': settings.LMS_COMM_DEFAULT_FROM_EMAIL, + 'override_default_channel': 'django_email', + } + site = Site.objects.get_current() + message_context = get_base_template_context(site) + message_context.update({ + 'email': user.email, + 'platform_name': 'edx', + 'course_name': 'zombie survival', + 'course_id': 'course.101', + 'days_per_week': 3, + 'course_url': 'test.com', + 'goals_unsubscribe_url': 'test.com', + 'image_url': 'test', + 'unsubscribe_url': None, + 'omit_unsubscribe_link': True, + 'courses_url': 'course.example.com', + 'programs_url': 'course.example.com', + }) + with emulate_http_request(site, user): + msg = Message( + name="goalreminder", + app_label="course_goals", + recipient=Recipient(user.id, user.email), + language='en', + context=message_context, + options=options, + ) + # expect an exception here + with self.assertRaises(NoCredentialsError): + send_email_using_ses(user, msg)