Merge pull request #18748 from edx/LEARNER-5931/update-learner-verification-emails

Update verification status emails
This commit is contained in:
Uzair Rasheed
2018-08-16 19:25:25 +05:00
committed by GitHub
6 changed files with 125 additions and 60 deletions

View File

@@ -0,0 +1,40 @@
"""
Django Celery tasks for service status app
"""
import logging
from smtplib import SMTPException
from celery import task
from django.conf import settings
from django.core.mail import send_mail
from edxmako.shortcuts import render_to_string
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
ACE_ROUTING_KEY = getattr(settings, 'ACE_ROUTING_KEY', None)
log = logging.getLogger(__name__)
@task(routing_key=ACE_ROUTING_KEY)
def send_verification_status_email(context):
"""
Spins a task to send verification status email to the learner
"""
subject = context.get('subject')
message = render_to_string(context.get('template'), context.get('email_vars'))
from_addr = configuration_helpers.get_value(
'email_from_address',
settings.DEFAULT_FROM_EMAIL
)
dest_addr = context.get('email')
try:
send_mail(
subject,
message,
from_addr,
[dest_addr],
fail_silently=False
)
except SMTPException:
log.warning("Failure in sending verification status e-mail to %s", dest_addr)

View File

@@ -38,8 +38,7 @@ from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
from lms.djangoapps.verify_student.views import (
PayAndVerifyView,
checkout_with_ecommerce_service,
render_to_response,
EmailMarketingConfiguration
render_to_response
)
from openedx.core.djangoapps.embargo.test_utils import restrict_course
from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
@@ -1775,7 +1774,6 @@ class TestPhotoVerificationResultsCallback(ModuleStoreTestCase):
"""
Test for verification passed.
"""
EmailMarketingConfiguration.objects.create(sailthru_verification_passed_template='test_template')
data = {
"EdX-ID": self.receipt_id,
"Result": "PASS",
@@ -1792,8 +1790,7 @@ class TestPhotoVerificationResultsCallback(ModuleStoreTestCase):
attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=self.receipt_id)
self.assertEqual(attempt.status, u'approved')
self.assertEquals(response.content, 'OK!')
self.assertFalse(mock_log_error.called)
self.assertTrue(mock_sailthru_send.call_args[1], 'test_template')
self.assertEqual(len(mail.outbox), 1)
@patch(
'lms.djangoapps.verify_student.ssencrypt.has_valid_signature',
@@ -1805,11 +1802,10 @@ class TestPhotoVerificationResultsCallback(ModuleStoreTestCase):
"""
Test for failed verification.
"""
EmailMarketingConfiguration.objects.create(sailthru_verification_failed_template='test_template')
data = {
"EdX-ID": self.receipt_id,
"Result": 'FAIL',
"Reason": 'Invalid photo',
"Reason": [{"photoIdReasons": ["Not provided"]}],
"MessageType": 'Your photo doesn\'t meet standards.'
}
json_data = json.dumps(data)
@@ -1823,10 +1819,9 @@ class TestPhotoVerificationResultsCallback(ModuleStoreTestCase):
attempt = SoftwareSecurePhotoVerification.objects.get(receipt_id=self.receipt_id)
self.assertEqual(attempt.status, u'denied')
self.assertEqual(attempt.error_code, u'Your photo doesn\'t meet standards.')
self.assertEqual(attempt.error_msg, u'"Invalid photo"')
self.assertEqual(attempt.error_msg, u'[{"photoIdReasons": ["Not provided"]}]')
self.assertEquals(response.content, 'OK!')
self.assertFalse(mock_log_error.called)
self.assertTrue(mock_sailthru_send.call_args[1], 'test_template')
self.assertEqual(len(mail.outbox), 1)
@patch(
'lms.djangoapps.verify_student.ssencrypt.has_valid_signature',

View File

@@ -76,23 +76,6 @@ def verification_for_datetime(deadline, candidates):
return verification
def send_verification_status_email(context):
"""
Send an email to inform learners about their verification status
using sailthru
"""
sailthru_client = SailthruClient(context['email_config'].sailthru_key, context['email_config'].sailthru_secret)
sailthru_response = sailthru_client.send(
email=context['email'], template=context['template'],
_vars=context['template_vars']
)
if not sailthru_response.is_ok():
error = sailthru_response.get_error()
log.error("Error attempting to send verification status email to user: {} via Sailthru: {}".format(
context['email'], error.get_message()
))
def most_recent_verification(photo_id_verifications, sso_id_verifications, manual_id_verifications, most_recent_key):
"""
Return the most recent verification given querysets for photo, sso and manual verifications.

View File

@@ -13,10 +13,10 @@ from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.staticfiles.storage import staticfiles_storage
from django.core.mail import send_mail
from django.urls import reverse
from django.db import transaction
from django.http import Http404, HttpResponse, HttpResponseBadRequest
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy
@@ -32,13 +32,13 @@ from pytz import UTC
from course_modes.models import CourseMode
from edxmako.shortcuts import render_to_response, render_to_string
from email_marketing.models import EmailMarketingConfiguration
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.services import IDVerificationService
from lms.djangoapps.verify_student.ssencrypt import has_valid_signature
from lms.djangoapps.verify_student.utils import is_verification_expiring_soon, send_verification_status_email
from lms.djangoapps.verify_student.tasks import send_verification_status_email
from lms.djangoapps.verify_student.utils import is_verification_expiring_soon
from openedx.core.djangoapps.commerce.utils import ecommerce_api_client
from openedx.core.djangoapps.embargo import api as embargo_api
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
@@ -1162,48 +1162,47 @@ def results_callback(request):
return HttpResponseBadRequest("edX ID {} not found".format(receipt_id))
user = attempt.user
email_config = EmailMarketingConfiguration.current()
verification_status_email_vars = {
'platform_name': settings.PLATFORM_NAME,
}
email_context = {
'email_config': email_config,
'email': user.email
}
if result == "PASS":
log.debug("Approving verification for %s", receipt_id)
attempt.approve()
status = "approved"
if email_config.sailthru_verification_passed_template:
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['subject'] = _("Your {platform_name} ID Verification Approved").format(
platform_name=settings.PLATFORM_NAME
)
verification_status_email_vars['full_name'] = user.profile.name
email_context['template'] = email_config.sailthru_verification_passed_template
email_context['template_vars'] = verification_status_email_vars
send_verification_status_email(email_context)
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 = _("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("Denying verification for %s", receipt_id)
attempt.deny(json.dumps(reason), error_code=error_code)
status = "denied"
if email_config.sailthru_verification_failed_template:
verification_status_email_vars['reason'] = reason
verification_status_email_vars['reverify_url'] = reverse("verify_student_reverify")
verification_status_email_vars['faq_url'] = configuration_helpers.get_value(
'ID_VERIFICATION_SUPPORT_LINK',
settings.SUPPORT_SITE_LINK
)
verification_status_email_vars['subject'] = _("Your {platform_name} Verification Has Been Denied").format(
platform_name=settings.PLATFORM_NAME
)
email_context['template'] = email_config.sailthru_verification_failed_template
email_context['template_vars'] = verification_status_email_vars
send_verification_status_email(email_context)
reverify_url = '{}{}'.format(settings.LMS_ROOT_URL, reverse("verify_student_reverify"))
verification_status_email_vars['reasons'] = reason
verification_status_email_vars['reverify_url'] = reverify_url
verification_status_email_vars['faq_url'] = settings.ID_VERIFICATION_SUPPORT_LINK
subject = _("Your {platform_name} Verification Has Been Denied").format(
platform_name=settings.PLATFORM_NAME
)
context = {
'subject': subject,
'template': 'emails/failed_verification_email.txt',
'email': user.email,
'email_vars': verification_status_email_vars
}
send_verification_status_email.delay(context)
elif result == "SYSTEM FAIL":
log.debug("System failure for %s -- resetting to must_retry", receipt_id)

View File

@@ -0,0 +1,38 @@
<%! from django.utils.translation import ugettext as _ %>
${_("Sorry! The photos you submitted for ID verification were not accepted, for the following reason(s):")}
${_("The photo(s) of you:")}
%for reason in reasons:
%if reason.get('userPhotoReasons'):
${_("The photo of you:")}
<ul>
%for item in reason.get('userPhotoReasons'):
<li>${item}</li>
%endfor
</ul>
%endif
%if reason.get('photoIdReasons'):
${_("The photo of your ID:")}
<ul>
%for item in reason.get('photoIdReasons'):
<li>${item}</li>
%endfor
</ul>
%endif
%if reason.get('generalReasons'):
${_("Other Reasons:")}
<ul>
%for item in reason.get('generalReasons'):
<li>${item}</li>
%endfor
</ul>
%endif
%endfor
${_("Resubmit Verification: {reverify_url}").format(reverify_url=reverify_url)}
${_("ID Verification FAQ: {faq_url}").format(faq_url=faq_url)}
${_("Thank you,")}
${_("The {platform_name} team").format(platform_name=platform_name)}

View File

@@ -0,0 +1,10 @@
<%! 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 {expiry_date}").format(expiry_date=expiry_date)}
${_("Thank you,")}
${_("The {platform_name} team").format(platform_name=platform_name)}