diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index cc52b1afbd5e35401e11d48fbe13bb8df479e28a..ce2d38212ade3e743c9f489f24873c29e3041b10 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -1668,6 +1668,7 @@ class TestPhotoVerificationResultsCallback(ModuleStoreTestCase): self.attempt.save() self.receipt_id = self.attempt.receipt_id self.client = Client() + self.client.login(username=self.user.username, password='test') def mocked_has_valid_signature(method, headers_dict, body_dict, access_key, secret_key): # pylint: disable=no-self-argument, unused-argument """ @@ -1779,6 +1780,30 @@ class TestPhotoVerificationResultsCallback(ModuleStoreTestCase): attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=self.receipt_id) self.assertEqual(attempt.status, u'approved') self.assertEquals(response.content, 'OK!') + self.assertEqual(len(mail.outbox), 1) + + @mock.patch( + 'lms.djangoapps.verify_student.utils.send_mail', + mock.Mock(side_effect=Exception()) + ) + def test_verification_status_email_not_sent(self): + """ + Test email is not sent in case of exception + """ + data = { + "EdX-ID": self.receipt_id, + "Result": "PASS", + "Reason": "", + "MessageType": "You have been verified." + } + json_data = json.dumps(data) + self.client.post( + reverse('verify_student_results_callback'), data=json_data, + content_type='application/json', + HTTP_AUTHORIZATION='test BBBBBBBBBBBBBBBBBBBB:testing', + HTTP_DATE='testdate' + ) + self.assertEqual(len(mail.outbox), 0) @mock.patch( 'lms.djangoapps.verify_student.ssencrypt.has_valid_signature', diff --git a/lms/djangoapps/verify_student/utils.py b/lms/djangoapps/verify_student/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..0596eb116b6775413e5d98d04b865e226a8b5f7b --- /dev/null +++ b/lms/djangoapps/verify_student/utils.py @@ -0,0 +1,45 @@ +""" +Common Utilities for the verify_student application. +""" + +import datetime +import logging + +from django.conf import settings +from django.core.mail import send_mail +from django.utils.translation import ugettext as _ + +from edxmako.shortcuts import render_to_string +from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers + +log = logging.getLogger(__name__) + + +def send_verification_status_email(context): + """ + Send an email to inform learners about their verification status + """ + current_date = datetime.datetime.now() + date = "{}/{}/{}".format(current_date.month, current_date.day, current_date.year) + email_template_context = { + 'full_name': context['user'].profile.name, + 'platform_name': configuration_helpers.get_value("PLATFORM_NAME", settings.PLATFORM_NAME), + 'date': date + } + + subject = context['subject'] + message = render_to_string(context['message'], email_template_context) + from_address = configuration_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL) + to_address = context['user'].email + + try: + send_mail(subject, message, from_address, [to_address], fail_silently=False) + except: # pylint: disable=bare-except + # We catch all exceptions and log them. + # It would be much, much worse to roll back the transaction due to an uncaught + # exception than to skip sending the notification email. + log.exception( + _("Could not send verification status email having {subject} subject for user {user}").format( + subject=context['subject'], + user=context['user'].id + )) diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index 9d426fe163180311cf8cc570e78acff882c68302..5be64b1581cba2e5fa55f1cc3a17789559065b60 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -35,6 +35,7 @@ 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.image import InvalidImageData, decode_image_data from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification, VerificationDeadline +from lms.djangoapps.verify_student.utils import send_verification_status_email from lms.djangoapps.verify_student.ssencrypt import has_valid_signature from openedx.core.djangoapps.commerce.utils import ecommerce_api_client from openedx.core.djangoapps.embargo import api as embargo_api @@ -1152,10 +1153,16 @@ def results_callback(request): except SoftwareSecurePhotoVerification.DoesNotExist: log.error("Software Secure posted back for receipt_id %s, but not found", receipt_id) return HttpResponseBadRequest("edX ID {} not found".format(receipt_id)) + context = {'user': request.user} if result == "PASS": log.debug("Approving verification for %s", receipt_id) attempt.approve() status = "approved" + context['subject'] = _("Your {platform_name} ID Verification Approved").format( + platform_name=settings.PLATFORM_NAME + ) + context['message'] = 'emails/successfull_verification_email.txt' + send_verification_status_email(context) elif result == "FAIL": log.debug("Denying verification for %s", receipt_id) diff --git a/lms/templates/emails/successfull_verification_email.txt b/lms/templates/emails/successfull_verification_email.txt new file mode 100644 index 0000000000000000000000000000000000000000..915279264383dbf4b4c7e31ee8e5b9eb7561b014 --- /dev/null +++ b/lms/templates/emails/successfull_verification_email.txt @@ -0,0 +1,7 @@ +<%! from django.utils.translation import ugettext as _ %> + +${_("Hi {full_name},").format(full_name=full_name)} + +${_("Congratulations! Your ID verification process was successful.")} + +${_("Your verification is effective for one year. It will expire on {date}").format(date=date)}