From a763fd80d27b1d5db3420da46e228f50f6ca8819 Mon Sep 17 00:00:00 2001 From: Muhammad Adeel Tajamul <77053848+muhammadadeeltajamul@users.noreply.github.com> Date: Thu, 4 Jul 2024 11:51:58 +0500 Subject: [PATCH] feat: added email headers for notification cadence email (#35078) --- .../djangoapps/notifications/email/tasks.py | 2 ++ .../notifications/email/tests/test_utils.py | 4 ++- .../djangoapps/notifications/email/utils.py | 28 ++++++++++++++++++- requirements/edx/base.txt | 3 +- requirements/edx/development.txt | 3 +- requirements/edx/doc.txt | 3 +- requirements/edx/testing.txt | 3 +- 7 files changed, 40 insertions(+), 6 deletions(-) diff --git a/openedx/core/djangoapps/notifications/email/tasks.py b/openedx/core/djangoapps/notifications/email/tasks.py index 50e8455af715..dc42be585cc7 100644 --- a/openedx/core/djangoapps/notifications/email/tasks.py +++ b/openedx/core/djangoapps/notifications/email/tasks.py @@ -16,6 +16,7 @@ ) from .message_type import EmailNotificationMessageType from .utils import ( + add_headers_to_email_message, create_app_notifications_dict, create_email_digest_context, filter_notification_with_email_enabled_preferences, @@ -98,6 +99,7 @@ def send_digest_email_to_user(user, cadence_type, course_language='en', courses_ message = EmailNotificationMessageType( app_label="notifications", name="email_digest" ).personalize(recipient, course_language, message_context) + message = add_headers_to_email_message(message, message_context) ace.send(message) logger.info(f' Email sent to {user.username} ==Temp Log==') diff --git a/openedx/core/djangoapps/notifications/email/tests/test_utils.py b/openedx/core/djangoapps/notifications/email/tests/test_utils.py index ee95d7af3991..8d72ffd748b5 100644 --- a/openedx/core/djangoapps/notifications/email/tests/test_utils.py +++ b/openedx/core/djangoapps/notifications/email/tests/test_utils.py @@ -3,7 +3,9 @@ """ import datetime import ddt +import pytest +from django.http.response import Http404 from itertools import product from pytz import utc from waffle import get_waffle_flag_model # pylint: disable=invalid-django-waffle-import @@ -429,5 +431,5 @@ def test_preference_not_updated_if_invalid_username(self): username = f"{self.user.username}-updated" enc_username = encrypt_string(username) enc_patch = encrypt_object({"value": True}) - with self.assertNumQueries(1): + with pytest.raises(Http404): update_user_preferences_from_patch(enc_username, enc_patch) diff --git a/openedx/core/djangoapps/notifications/email/utils.py b/openedx/core/djangoapps/notifications/email/utils.py index 4531cabda0ee..5fb07fc34817 100644 --- a/openedx/core/djangoapps/notifications/email/utils.py +++ b/openedx/core/djangoapps/notifications/email/utils.py @@ -5,10 +5,13 @@ import json from django.conf import settings +from django.contrib.auth import get_user_model +from django.shortcuts import get_object_or_404 from django.urls import reverse from pytz import utc from waffle import get_waffle_flag_model # pylint: disable=invalid-django-waffle-import +from common.djangoapps.student.models import CourseEnrollment from lms.djangoapps.branding.api import get_logo_url_for_email from lms.djangoapps.discussion.notification_prefs.views import UsernameCipher from openedx.core.djangoapps.notifications.base_notification import ( @@ -23,6 +26,9 @@ from .notification_icons import NotificationTypeIcons +User = get_user_model() + + def is_email_notification_flag_enabled(user=None): """ Returns if waffle flag is enabled for user or not @@ -146,6 +152,16 @@ def create_email_digest_context(app_notifications_dict, username, start_date, en return context +def add_headers_to_email_message(message, context): + """ + Add headers to email message + """ + if context.get('unsubscribe_url'): + message.headers['List-Unsubscribe-Post'] = f"<{context['unsubscribe_url']}>" + message.headers['List-Unsubscribe'] = f"<{context['unsubscribe_url']}>" + return message + + def get_start_end_date(cadence_type): """ Returns start_date and end_date for email digest @@ -319,8 +335,9 @@ def update_user_preferences_from_patch(encrypted_username, encrypted_patch): type_value = patch.get("notification_type") channel_value = patch.get("channel") pref_value = bool(patch.get("value", False)) + user = get_object_or_404(User, username=username) - kwargs = {'user__username': username} + kwargs = {'user': user} if 'course_id' in patch.keys(): kwargs['course_id'] = patch['course_id'] @@ -346,7 +363,16 @@ def get_default_cadence_value(app_name, notification_type): return COURSE_NOTIFICATION_APPS[app_name]['core_email_cadence'] return COURSE_NOTIFICATION_TYPES[notification_type]['email_cadence'] + course_ids = CourseEnrollment.objects.filter(user=user).values_list('course_id', flat=True) + CourseNotificationPreference.objects.bulk_create( + [ + CourseNotificationPreference(user=user, course_id=course_id) + for course_id in course_ids + ], + ignore_conflicts=True + ) preferences = CourseNotificationPreference.objects.filter(**kwargs) + # pylint: disable=too-many-nested-blocks for preference in preferences: preference_json = preference.notification_preference_config diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 1d8281ef7a34..56d7babebb1e 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -384,7 +384,7 @@ drf-yasg==1.21.7 # via # django-user-tasks # edx-api-doc-tools -edx-ace==1.8.0 +edx-ace==1.9.1 # via -r requirements/edx/kernel.in edx-api-doc-tools==1.8.0 # via @@ -425,6 +425,7 @@ edx-django-utils==5.14.2 # via # -r requirements/edx/kernel.in # django-config-models + # edx-ace # edx-drf-extensions # edx-enterprise # edx-event-bus-kafka diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index e50c8f12fe9a..5f62c61fbcfa 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -640,7 +640,7 @@ drf-yasg==1.21.7 # -r requirements/edx/testing.txt # django-user-tasks # edx-api-doc-tools -edx-ace==1.8.0 +edx-ace==1.9.1 # via # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt @@ -698,6 +698,7 @@ edx-django-utils==5.14.2 # -r requirements/edx/doc.txt # -r requirements/edx/testing.txt # django-config-models + # edx-ace # edx-drf-extensions # edx-enterprise # edx-event-bus-kafka diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index 8c80ae4fc008..f4ae598faa22 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -456,7 +456,7 @@ drf-yasg==1.21.7 # -r requirements/edx/base.txt # django-user-tasks # edx-api-doc-tools -edx-ace==1.8.0 +edx-ace==1.9.1 # via -r requirements/edx/base.txt edx-api-doc-tools==1.8.0 # via @@ -497,6 +497,7 @@ edx-django-utils==5.14.2 # via # -r requirements/edx/base.txt # django-config-models + # edx-ace # edx-drf-extensions # edx-enterprise # edx-event-bus-kafka diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 75055df3161f..07449a41530a 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -489,7 +489,7 @@ drf-yasg==1.21.7 # -r requirements/edx/base.txt # django-user-tasks # edx-api-doc-tools -edx-ace==1.8.0 +edx-ace==1.9.1 # via -r requirements/edx/base.txt edx-api-doc-tools==1.8.0 # via @@ -530,6 +530,7 @@ edx-django-utils==5.14.2 # via # -r requirements/edx/base.txt # django-config-models + # edx-ace # edx-drf-extensions # edx-enterprise # edx-event-bus-kafka