From 8adcff938a995f28d4abe5305d1e4b7d34119d30 Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Tue, 29 May 2018 12:17:00 -0400 Subject: [PATCH] Add new notification email. --- .../djangoapps/ace_common/template_context.py | 2 + .../user_api/accounts/tests/test_views.py | 5 +++ .../djangoapps/user_api/accounts/views.py | 22 +++++++++++ .../core/djangoapps/user_api/message_types.py | 21 +++++++++++ .../email/body.html | 37 +++++++++++++++++++ .../email/body.txt | 22 +++++++++++ .../email/from_name.txt | 1 + .../email/head.html | 1 + .../email/subject.txt | 5 +++ 9 files changed, 116 insertions(+) create mode 100644 openedx/core/djangoapps/user_api/message_types.py create mode 100644 openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.html create mode 100644 openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.txt create mode 100644 openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/from_name.txt create mode 100644 openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/head.html create mode 100644 openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/subject.txt diff --git a/openedx/core/djangoapps/ace_common/template_context.py b/openedx/core/djangoapps/ace_common/template_context.py index b86658fb1f..7ae2769823 100644 --- a/openedx/core/djangoapps/ace_common/template_context.py +++ b/openedx/core/djangoapps/ace_common/template_context.py @@ -22,6 +22,8 @@ def get_base_template_context(site): site=site, site_config_name='platform_name', ), + 'contact_email': get_config_value_from_site_or_settings( + 'CONTACT_EMAIL', site=site, site_config_name='contact_email'), 'contact_mailing_address': get_config_value_from_site_or_settings( 'CONTACT_MAILING_ADDRESS', site=site, site_config_name='contact_mailing_address'), 'social_media_urls': get_config_value_from_site_or_settings('SOCIAL_MEDIA_FOOTER_URLS', site=site), diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_views.py index 16c2d98c36..4f99e5a1d5 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_views.py @@ -13,6 +13,7 @@ import ddt from django.conf import settings from django.contrib.auth.models import User from django.contrib.sites.models import Site +from django.core import mail from django.core.cache import cache from django.core.urlresolvers import reverse from django.test import TestCase @@ -1148,6 +1149,10 @@ class TestDeactivateLogout(RetirementTestCase): retirement_utils_mock.retire_dot_oauth2_models.assertCalledWith(self.test_user) # make sure the user cannot log in self.assertFalse(self.client.login(username=self.test_user.username, password=self.test_password)) + # make sure that an email has been sent + self.assertEqual(len(mail.outbox), 1) + # ensure that it's been sent to the correct email address + self.assertIn(self.test_user.email, mail.outbox[0].to) def test_password_mismatch(self): """ diff --git a/openedx/core/djangoapps/user_api/accounts/views.py b/openedx/core/djangoapps/user_api/accounts/views.py index e2404481dc..a1c8df71bf 100644 --- a/openedx/core/djangoapps/user_api/accounts/views.py +++ b/openedx/core/djangoapps/user_api/accounts/views.py @@ -11,9 +11,12 @@ from functools import wraps import pytz from consent.models import DataSharingConsent from django.contrib.auth import authenticate, get_user_model, logout +from django.contrib.sites.models import Site from django.core.cache import cache from django.db import transaction from django.utils.translation import ugettext as _ +from edx_ace import ace +from edx_ace.recipient import Recipient from edx_rest_framework_extensions.authentication import JwtAuthentication from enterprise.models import EnterpriseCourseEnrollment, EnterpriseCustomerUser, PendingEnterpriseCustomerUser from integrated_channels.degreed.models import DegreedLearnerDataTransmissionAudit @@ -31,6 +34,7 @@ from wiki.models.pluginbase import RevisionPluginRevision from entitlements.models import CourseEntitlement from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification +from openedx.core.djangoapps.ace_common.template_context import get_base_template_context from openedx.core.djangoapps.api_admin.models import ApiAccessRequest from openedx.core.djangoapps.credit.models import CreditRequirementStatus, CreditRequest from openedx.core.djangoapps.course_groups.models import UnregisteredLearnerCohortAssignments @@ -67,6 +71,7 @@ from .api import get_account_settings, update_account_settings from .permissions import CanDeactivateUser, CanRetireUser from .serializers import UserRetirementStatusSerializer from .signals import USER_RETIRE_MAILINGS +from ..message_types import DeletionNotificationMessage log = logging.getLogger(__name__) @@ -421,6 +426,7 @@ class DeactivateLogoutView(APIView): # Unlink LMS social auth accounts UserSocialAuth.objects.filter(user_id=request.user.id).delete() # Change LMS password & email + user_email = request.user.email request.user.email = get_retired_email_by_email(request.user.email) request.user.save() _set_unusable_password(request.user) @@ -431,6 +437,22 @@ class DeactivateLogoutView(APIView): # Delete OAuth tokens associated with the user. retire_dop_oauth2_models(request.user) retire_dot_oauth2_models(request.user) + + try: + # Send notification email to user + site = Site.objects.get_current() + notification_context = get_base_template_context(site) + notification_context.update({'full_name': request.user.profile.name}) + notification = DeletionNotificationMessage().personalize( + recipient=Recipient(username='', email_address=user_email), + language=request.user.profile.language, + user_context=notification_context, + ) + ace.send(notification) + except Exception as exc: + log.exception('Error sending out deletion notification email') + raise + # Log the user out. logout(request) return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/openedx/core/djangoapps/user_api/message_types.py b/openedx/core/djangoapps/user_api/message_types.py new file mode 100644 index 0000000000..0249ceca10 --- /dev/null +++ b/openedx/core/djangoapps/user_api/message_types.py @@ -0,0 +1,21 @@ +""" +Message Types for user_api emails +""" + +from django.conf import settings + +from edx_ace import message +from openedx.core.djangoapps.site_configuration import helpers + + +class DeletionNotificationMessage(message.MessageType): + """ + Message to notify learners that their account is queued for deletion. + """ + def __init__(self, *args, **kwargs): + super(DeletionNotificationMessage, self).__init__(*args, **kwargs) + + self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + self.options['from_address'] = helpers.get_value( # pylint: disable=unsupported-assignment-operation + 'email_from_address', settings.DEFAULT_FROM_EMAIL + ) diff --git a/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.html b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.html new file mode 100644 index 0000000000..1ad6cb6aaa --- /dev/null +++ b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.html @@ -0,0 +1,37 @@ +{% extends 'ace_common/edx_ace/common/base_body.html' %} +{% load i18n %} + +{% block content %} + + + + +
+

+ {% blocktrans trimmed %} + Hello {{full_name}}, + {% endblocktrans %} +

+

+ {% blocktrans trimmed %} + We received a deletion request for your account on {{platform_name}}. We're sorry to see you go! + {% endblocktrans %} +

+

+ {% blocktrans trimmed %} + Your account will be deleted shortly. Account deletion, including removal from email lists, may take a few weeks to fully process through our system. If you want to opt-out of emails before then, please unsubscribe from the footer of any email. + {% endblocktrans %} +

+

+ {% blocktrans trimmed %} + This is an informational email only. If you did not initiate this request, please contact {{contact_email}}. + {% endblocktrans %} +

+

+ {% blocktrans trimmed %} + Best, + {{ platform_name }} + {% endblocktrans %} +

+
+{% endblock %} diff --git a/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.txt b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.txt new file mode 100644 index 0000000000..71817c21c8 --- /dev/null +++ b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/body.txt @@ -0,0 +1,22 @@ +{% load i18n %} + +{% blocktrans trimmed %} +Hello {{full_name}}, +{% endblocktrans %} + +{% blocktrans trimmed %} +We received a deletion request for your account on {{platform_name}}. We're sorry to see you go! +{% endblocktrans %} + +{% blocktrans trimmed %} +Your account will be deleted shortly. Account deletion, including removal from email lists, may take a few weeks to fully process through our system. If you want to opt-out of emails before then, please unsubscribe from the footer of any email. +{% endblocktrans %} + +{% blocktrans trimmed %} +This is an informational email only. If you did not initiate this request, please contact {{contact_email}}. +{% endblocktrans %} + +{% blocktrans trimmed %} +Best, +{{platform_name}} +{% endblocktrans %} diff --git a/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/from_name.txt b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/from_name.txt new file mode 100644 index 0000000000..dcbc23c004 --- /dev/null +++ b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/from_name.txt @@ -0,0 +1 @@ +{{ platform_name }} diff --git a/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/head.html b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/head.html new file mode 100644 index 0000000000..366ada7ad9 --- /dev/null +++ b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/head.html @@ -0,0 +1 @@ +{% extends 'ace_common/edx_ace/common/base_head.html' %} diff --git a/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/subject.txt b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/subject.txt new file mode 100644 index 0000000000..6732cb5bc7 --- /dev/null +++ b/openedx/core/djangoapps/user_api/templates/user_api/edx_ace/deletionnotificationmessage/email/subject.txt @@ -0,0 +1,5 @@ +{% autoescape off %} +{% load i18n %} + +{% blocktrans %}Your Account Has Been Queued For Deletion{% endblocktrans %} +{% endautoescape %}