diff --git a/lms/djangoapps/verify_student/emails.py b/lms/djangoapps/verify_student/emails.py new file mode 100644 index 0000000000..dcbad1b1b1 --- /dev/null +++ b/lms/djangoapps/verify_student/emails.py @@ -0,0 +1,60 @@ +""" +ACE emails for verify_student app +""" +import logging + +from django.contrib.sites.models import Site +from edx_ace import ace +from edx_ace.recipient import Recipient + +from lms.djangoapps.verify_student.message_types import VerificationApproved, VerificationSubmitted +from openedx.core.djangoapps.ace_common.template_context import get_base_template_context +from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY +from openedx.core.djangoapps.user_api.preferences.api import get_user_preference +from openedx.core.lib.celery.task_utils import emulate_http_request + +log = logging.getLogger(__name__) + + +def send_verification_confirmation_email(context): + """Send an email confirming that the user submitted photos for initial verification.""" + site = Site.objects.get_current() + message_context = get_base_template_context(site) + message_context.update(context) + user = context['user'] + try: + with emulate_http_request(site=site, user=user): + msg = VerificationSubmitted(context=message_context).personalize( + recipient=Recipient(user.username, user.email), + language=get_user_preference(user, LANGUAGE_KEY), + user_context={'full_name': user.profile.name} + ) + ace.send(msg) + log.info('Verification confirmation email sent to user: %r', user.username) + return True + except Exception: # pylint: disable=broad-except + log.exception('Could not send email for verification confirmation to user %s', user.username) + return False + + +def send_verification_approved_email(context): + """ + Sends email to a learner when ID verification has been approved. + """ + site = Site.objects.get_current() + message_context = get_base_template_context(site) + message_context.update(context) + user = context['user'] + try: + with emulate_http_request(site=site, user=user): + msg = VerificationApproved(context=message_context).personalize( + recipient=Recipient(user.username, user.email), + language=get_user_preference(user, LANGUAGE_KEY), + user_context={'full_name': user.profile.name} + ) + ace.send(msg) + log.info('Verification approved email sent to user: %r', user.username) + return True + except Exception: # pylint: disable=broad-except + log.exception('Could not send email for verification approved to user %s', user.username) + return False diff --git a/lms/djangoapps/verify_student/message_types.py b/lms/djangoapps/verify_student/message_types.py index 24097b434a..8d5f267425 100644 --- a/lms/djangoapps/verify_student/message_types.py +++ b/lms/djangoapps/verify_student/message_types.py @@ -1,8 +1,6 @@ """ ACE message types for the verify_student module. """ - - from openedx.core.djangoapps.ace_common.message import BaseMessageType @@ -14,3 +12,27 @@ class VerificationExpiry(BaseMessageType): super(VerificationExpiry, self).__init__(*args, **kwargs) self.options['transactional'] = True + + +class VerificationApproved(BaseMessageType): + """ + A message to the learner when his ID verification has been approved. + """ + APP_LABEL = 'verify_student' + Name = 'verificationapproved' + + def __init__(self, *args, **kwargs): + super(VerificationApproved, self).__init__(*args, **kwargs) + self.options['transactional'] = True + + +class VerificationSubmitted(BaseMessageType): + """ + A confirmation message to the learner when his ID verification has been submitted. + """ + APP_LABEL = 'verify_student' + Name = 'verificationsubmitted' + + def __init__(self, *args, **kwargs): + super(VerificationSubmitted, self).__init__(*args, **kwargs) + self.options['transactional'] = True diff --git a/lms/djangoapps/verify_student/toggles.py b/lms/djangoapps/verify_student/toggles.py new file mode 100644 index 0000000000..74f5a42b55 --- /dev/null +++ b/lms/djangoapps/verify_student/toggles.py @@ -0,0 +1,30 @@ +""" +Toggles for verify_student app +""" + +from openedx.core.djangoapps.waffle_utils import WaffleFlagNamespace, WaffleFlag + +# Namespace for verify_students waffle flags. +WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='verify_student') + +# Waffle flag to use new email templates for sending ID verification emails. +# .. toggle_name: verify_student.use_new_email_templates +# .. toggle_implementation: WaffleFlag +# .. toggle_default: False +# .. toggle_description: Supports staged rollout to students for a new email templates implementation for ID verification. +# .. toggle_category: verify student +# .. toggle_use_cases: incremental_release, open_edx +# .. toggle_creation_date: 2020-06-25 +# .. toggle_expiration_date: n/a +# .. toggle_warnings: n/a +# .. toggle_tickets: PROD-1639 +# .. toggle_status: supported +USE_NEW_EMAIL_TEMPLATES = WaffleFlag( + waffle_namespace=WAFFLE_FLAG_NAMESPACE, + flag_name='use_new_email_templates', + flag_undefined_default=False +) + + +def use_new_templates_for_id_verification_emails(): + return USE_NEW_EMAIL_TEMPLATES.is_enabled() diff --git a/lms/djangoapps/verify_student/utils.py b/lms/djangoapps/verify_student/utils.py index 768f6ca9b7..d53bf5fb6f 100644 --- a/lms/djangoapps/verify_student/utils.py +++ b/lms/djangoapps/verify_student/utils.py @@ -8,6 +8,7 @@ import logging from django.conf import settings from django.utils.timezone import now + from six import text_type from lms.djangoapps.verify_student.tasks import send_request_to_ss_for_user diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index ab7e0ed705..b0626e8ed5 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -2,7 +2,6 @@ Views for the verification flow """ - import datetime import decimal import json @@ -28,12 +27,13 @@ from edx_rest_api_client.exceptions import SlumberBaseException from ipware.ip import get_ip from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey -from rest_framework.views import APIView from rest_framework.response import Response +from rest_framework.views import APIView from course_modes.models import CourseMode from edxmako.shortcuts import render_to_response, render_to_string from lms.djangoapps.commerce.utils import EcommerceService, is_account_activation_requirement_disabled +from lms.djangoapps.verify_student.emails import send_verification_approved_email, send_verification_confirmation_email from lms.djangoapps.verify_student.image import InvalidImageData, decode_image_data from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification, VerificationDeadline from lms.djangoapps.verify_student.services import IDVerificationService @@ -51,6 +51,7 @@ from student.models import CourseEnrollment from track import segment from util.db import outer_atomic from util.json_request import JsonResponse +from verify_student.toggles import use_new_templates_for_id_verification_emails from xmodule.modulestore.django import modulestore log = logging.getLogger(__name__) @@ -1031,12 +1032,20 @@ class SubmitPhotosView(View): Send an email confirming that the user submitted photos for initial verification. """ + if use_new_templates_for_id_verification_emails(): + lms_root_url = configuration_helpers.get_value('LMS_ROOT_URL', settings.LMS_ROOT_URL) + new_template_context = { + 'user': user, + 'dashboard_link': '{}{}'.format(lms_root_url, reverse('dashboard')) + } + return send_verification_confirmation_email(new_template_context) + context = { 'full_name': user.profile.name, 'platform_name': configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME) } - subject = _(u"{platform_name} ID Verification Photos Received").format(platform_name=context['platform_name']) + subject = _("{platform_name} ID Verification Photos Received").format(platform_name=context['platform_name']) message = render_to_string('emails/photo_submission_confirmation.txt', context) from_address = configuration_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL) to_address = user.email @@ -1140,22 +1149,27 @@ def results_callback(request): ).update(expiry_date=None, expiry_email_date=None) log.debug(u'Approving verification for {}'.format(receipt_id)) attempt.approve() - status = u"approved" + expiry_date = datetime.date.today() + datetime.timedelta( days=settings.VERIFY_STUDENT["DAYS_GOOD_FOR"] ) - verification_status_email_vars['expiry_date'] = expiry_date.strftime("%m/%d/%Y") - verification_status_email_vars['full_name'] = user.profile.name - subject = _(u"Your {platform_name} ID Verification Approved").format( - platform_name=settings.PLATFORM_NAME - ) - context = { - 'subject': subject, - 'template': 'emails/passed_verification_email.txt', - 'email': user.email, - 'email_vars': verification_status_email_vars - } - send_verification_status_email.delay(context) + + if use_new_templates_for_id_verification_emails(): + context = {'user_id': user, 'expiry_date': expiry_date.strftime("%m/%d/%Y")} + send_verification_approved_email(context=context) + else: + verification_status_email_vars['expiry_date'] = expiry_date.strftime("%m/%d/%Y") + verification_status_email_vars['full_name'] = user.profile.name + subject = _(u"Your {platform_name} ID Verification Approved").format( + platform_name=settings.PLATFORM_NAME + ) + context = { + 'subject': subject, + 'template': 'emails/passed_verification_email.txt', + 'email': user.email, + 'email_vars': verification_status_email_vars + } + send_verification_status_email.delay(context) elif result == "FAIL": log.debug(u"Denying verification for %s", receipt_id) diff --git a/lms/templates/verify_student/edx_ace/verificationapproved/email/body.html b/lms/templates/verify_student/edx_ace/verificationapproved/email/body.html new file mode 100644 index 0000000000..83ff7a5cbd --- /dev/null +++ b/lms/templates/verify_student/edx_ace/verificationapproved/email/body.html @@ -0,0 +1,39 @@ +{% extends 'ace_common/edx_ace/common/base_body.html' %} + +{% load i18n %} +{% load static %} +{% block content %} + + + + +
+

+ {% trans "ID Verification Approved" as tmsg %}{{ tmsg | force_escape }} +

+

+ {% filter force_escape %} + {% blocktrans %}Hello {{ full_name }},{% endblocktrans %} + {% endfilter %} +

+

+ {% filter force_escape %} + {% blocktrans %}Your {{ platform_name }} ID verification photos have been approved.{% endblocktrans %} + {% endfilter %} + + {% filter force_escape %} + {% blocktrans %}Your approval status remains valid for one year, and it will expire {{ expiry_date }}.{% endblocktrans %} + {% endfilter %} +
+

+ +

+ {% trans "Enjoy your studies," as tmsg %}{{ tmsg | force_escape }} +
+ {% filter force_escape %} + {% blocktrans %}The {{ platform_name }} Team {% endblocktrans %} + {% endfilter %} +

+ +
+{% endblock %} diff --git a/lms/templates/verify_student/edx_ace/verificationapproved/email/body.txt b/lms/templates/verify_student/edx_ace/verificationapproved/email/body.txt new file mode 100644 index 0000000000..f3ffad937d --- /dev/null +++ b/lms/templates/verify_student/edx_ace/verificationapproved/email/body.txt @@ -0,0 +1,8 @@ +{% load i18n %}{% autoescape off %} +{% blocktrans %}Hello {{full_name}}, {% endblocktrans %} +{% blocktrans %}Your {{ platform_name }} ID verification photos have been approved.{% endblocktrans %} +{% blocktrans %}Your approval status remains valid for one year, and it will expire {{ expiry_date }}.{% endblocktrans %} + +{% trans "Enjoy your studies," %} +{% blocktrans %}The {{ platform_name }} Team {% endblocktrans %} +{% endautoescape %} diff --git a/lms/templates/verify_student/edx_ace/verificationapproved/email/from_name.txt b/lms/templates/verify_student/edx_ace/verificationapproved/email/from_name.txt new file mode 100644 index 0000000000..dcbc23c004 --- /dev/null +++ b/lms/templates/verify_student/edx_ace/verificationapproved/email/from_name.txt @@ -0,0 +1 @@ +{{ platform_name }} diff --git a/lms/templates/verify_student/edx_ace/verificationapproved/email/head.html b/lms/templates/verify_student/edx_ace/verificationapproved/email/head.html new file mode 100644 index 0000000000..366ada7ad9 --- /dev/null +++ b/lms/templates/verify_student/edx_ace/verificationapproved/email/head.html @@ -0,0 +1 @@ +{% extends 'ace_common/edx_ace/common/base_head.html' %} diff --git a/lms/templates/verify_student/edx_ace/verificationapproved/email/subject.txt b/lms/templates/verify_student/edx_ace/verificationapproved/email/subject.txt new file mode 100644 index 0000000000..9fa8994a9d --- /dev/null +++ b/lms/templates/verify_student/edx_ace/verificationapproved/email/subject.txt @@ -0,0 +1,4 @@ +{% load i18n %} +{% autoescape off %} +{% blocktrans trimmed %}Your {{ platform_name }} ID verification was approved!{% endblocktrans %} +{% endautoescape %} diff --git a/lms/templates/verify_student/edx_ace/verificationsubmitted/email/body.html b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/body.html new file mode 100644 index 0000000000..819c36c39b --- /dev/null +++ b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/body.html @@ -0,0 +1,42 @@ +{% extends 'ace_common/edx_ace/common/base_body.html' %} + +{% load i18n %} +{% load static %} +{% block content %} + + + + +
+

+ {% trans "ID Verification Submitted" as tmsg %}{{ tmsg | force_escape }} +

+

+ {% filter force_escape %} + {% blocktrans %}Hello {{ full_name }},{% endblocktrans %} + {% endfilter %} +

+

+ {% filter force_escape %} + {% blocktrans %}Thank you for submitting your photos for identity verification with {{ platform_name }}. {% endblocktrans %} + {% endfilter %} +

+ +

+ {% trans "We have received your photos and they will be reviewed within 5-7 days." as tmsg %}{{ tmsg | force_escape }} + + {% filter force_escape %} + {% blocktrans %}You may check the status on your dashboard: {{ dashboard_link }} {% endblocktrans %} + {% endfilter %} +

+ +

+ {% trans "Best regards," as tmsg %}{{ tmsg | force_escape }} +
+ {% filter force_escape %} + {% blocktrans %}The {{ platform_name }} Team {% endblocktrans %} + {% endfilter %} +

+ +
+{% endblock %} diff --git a/lms/templates/verify_student/edx_ace/verificationsubmitted/email/body.txt b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/body.txt new file mode 100644 index 0000000000..1c987e8b65 --- /dev/null +++ b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/body.txt @@ -0,0 +1,9 @@ +{% load i18n %}{% autoescape off %} +{% blocktrans %}Hello {{full_name}}, {% endblocktrans %} +{% blocktrans %}Thank you for submitting your photos for identity verification with {{ platform_name }}. {% endblocktrans %} +{% trans "We have received your photos and they will be reviewed within 5-7 days." %} +{% blocktrans %}You may check the status on your dashboard: {{ dashboard_link }} {% endblocktrans %} + +{% trans "Best regards," %} +{% blocktrans %}The {{ platform_name }} Team {% endblocktrans %} +{% endautoescape %} diff --git a/lms/templates/verify_student/edx_ace/verificationsubmitted/email/from_name.txt b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/from_name.txt new file mode 100644 index 0000000000..dcbc23c004 --- /dev/null +++ b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/from_name.txt @@ -0,0 +1 @@ +{{ platform_name }} diff --git a/lms/templates/verify_student/edx_ace/verificationsubmitted/email/head.html b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/head.html new file mode 100644 index 0000000000..366ada7ad9 --- /dev/null +++ b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/head.html @@ -0,0 +1 @@ +{% extends 'ace_common/edx_ace/common/base_head.html' %} diff --git a/lms/templates/verify_student/edx_ace/verificationsubmitted/email/subject.txt b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/subject.txt new file mode 100644 index 0000000000..3ee6c9c8a6 --- /dev/null +++ b/lms/templates/verify_student/edx_ace/verificationsubmitted/email/subject.txt @@ -0,0 +1,4 @@ +{% load i18n %} +{% autoescape off %} +{% blocktrans trimmed %}Thank you for submitting your photos!{% endblocktrans %} +{% endautoescape %}