From 6ff3235f84cd572401c45c1707384c981be2f853 Mon Sep 17 00:00:00 2001 From: Omar Al-Ithawi Date: Tue, 18 Sep 2018 09:22:18 +0300 Subject: [PATCH 1/2] Convert instructor email messages to ACE --- .../emails/enroll_email_allowedmessage.txt | 30 -- .../emails/enroll_email_allowedsubject.txt | 5 - .../emails/enroll_email_enrolledmessage.txt | 20 - .../emails/enroll_email_enrolledsubject.txt | 5 - .../emails/unenroll_email_allowedmessage.txt | 13 - .../emails/unenroll_email_enrolledmessage.txt | 17 - .../emails/unenroll_email_subject.txt | 5 - lms/djangoapps/ccx/tests/utils.py | 3 +- lms/djangoapps/instructor/enrollment.py | 96 ++--- lms/djangoapps/instructor/message_types.py | 84 ++++ .../instructor/tests/test_access.py | 3 +- lms/djangoapps/instructor/tests/test_api.py | 380 ++++++++++++------ .../tests/test_api_email_localization.py | 24 +- .../instructor/tests/test_enrollment.py | 65 +-- lms/djangoapps/instructor/views/api.py | 2 +- .../instructor/views/registration_codes.py | 2 +- .../ccx/enroll_email_allowedmessage.txt | 43 -- .../ccx/enroll_email_allowedsubject.txt | 5 - .../ccx/enroll_email_enrolledmessage.txt | 20 - .../ccx/enroll_email_enrolledsubject.txt | 5 - .../ccx/unenroll_email_allowedmessage.txt | 13 - .../ccx/unenroll_email_enrolledmessage.txt | 17 - lms/templates/ccx/unenroll_email_subject.txt | 5 - ...count_creation_and_enroll_emailMessage.txt | 14 - lms/templates/emails/activation_email.txt | 1 + .../emails/activation_email_subject.txt | 1 + .../emails/add_beta_tester_email_message.txt | 25 -- .../emails/add_beta_tester_email_subject.txt | 5 - .../business_order_confirmation_email.txt | 1 + lms/templates/emails/confirm_email_change.txt | 1 + lms/templates/emails/email_change.txt | 1 + lms/templates/emails/email_change_subject.txt | 1 + .../emails/enroll_email_allowedmessage.txt | 43 -- .../emails/enroll_email_allowedsubject.txt | 5 - .../emails/enroll_email_enrolledmessage.txt | 20 - .../emails/enroll_email_enrolledsubject.txt | 5 - .../emails/order_confirmation_email.txt | 1 + .../emails/photo_submission_confirmation.txt | 1 + .../emails/registration_codes_sale_email.txt | 1 + ...stration_codes_sale_invoice_attachment.txt | 1 + lms/templates/emails/reject_name_change.txt | 1 + .../remove_beta_tester_email_message.txt | 18 - .../remove_beta_tester_email_subject.txt | 5 - .../emails/reverification_processed.txt | 1 + .../emails/unenroll_email_allowedmessage.txt | 13 - .../emails/unenroll_email_enrolledmessage.txt | 17 - .../emails/unenroll_email_subject.txt | 5 - .../email/body.html | 41 ++ .../email/body.txt | 11 + .../email/from_name.txt | 1 + .../email/head.html | 1 + .../email/subject.txt | 4 + .../edx_ace/addbetatester/email/body.html | 52 +++ .../edx_ace/addbetatester/email/body.txt | 12 + .../edx_ace/addbetatester/email/from_name.txt | 1 + .../edx_ace/addbetatester/email/head.html | 1 + .../edx_ace/addbetatester/email/subject.txt | 4 + .../edx_ace/allowedenroll/email/body.html | 62 +++ .../edx_ace/allowedenroll/email/body.txt | 14 + .../edx_ace/allowedenroll/email/from_name.txt | 1 + .../edx_ace/allowedenroll/email/head.html | 1 + .../edx_ace/allowedenroll/email/subject.txt | 4 + .../edx_ace/allowedunenroll/email/body.html | 25 ++ .../edx_ace/allowedunenroll/email/body.txt | 6 + .../allowedunenroll/email/from_name.txt | 1 + .../edx_ace/allowedunenroll/email/head.html | 1 + .../edx_ace/allowedunenroll/email/subject.txt | 4 + .../edx_ace/enrolledunenroll/email/body.html | 32 ++ .../edx_ace/enrolledunenroll/email/body.txt | 8 + .../enrolledunenroll/email/from_name.txt | 1 + .../edx_ace/enrolledunenroll/email/head.html | 1 + .../enrolledunenroll/email/subject.txt | 4 + .../edx_ace/enrollenrolled/email/body.html | 30 ++ .../edx_ace/enrollenrolled/email/body.txt | 9 + .../enrollenrolled/email/from_name.txt | 1 + .../edx_ace/enrollenrolled/email/head.html | 1 + .../edx_ace/enrollenrolled/email/subject.txt | 4 + .../edx_ace/removebetatester/email/body.html | 35 ++ .../edx_ace/removebetatester/email/body.txt | 8 + .../removebetatester/email/from_name.txt | 1 + .../edx_ace/removebetatester/email/head.html | 1 + .../removebetatester/email/subject.txt | 4 + .../djangoapps/ace_common/tests/mixins.py | 34 ++ .../ace_common/tests/test_templatetags.py | 33 +- 84 files changed, 864 insertions(+), 639 deletions(-) delete mode 100644 common/test/test_sites/test_site/templates/emails/enroll_email_allowedmessage.txt delete mode 100644 common/test/test_sites/test_site/templates/emails/enroll_email_allowedsubject.txt delete mode 100644 common/test/test_sites/test_site/templates/emails/enroll_email_enrolledmessage.txt delete mode 100644 common/test/test_sites/test_site/templates/emails/enroll_email_enrolledsubject.txt delete mode 100644 common/test/test_sites/test_site/templates/emails/unenroll_email_allowedmessage.txt delete mode 100644 common/test/test_sites/test_site/templates/emails/unenroll_email_enrolledmessage.txt delete mode 100644 common/test/test_sites/test_site/templates/emails/unenroll_email_subject.txt create mode 100644 lms/djangoapps/instructor/message_types.py delete mode 100644 lms/templates/ccx/enroll_email_allowedmessage.txt delete mode 100644 lms/templates/ccx/enroll_email_allowedsubject.txt delete mode 100644 lms/templates/ccx/enroll_email_enrolledmessage.txt delete mode 100644 lms/templates/ccx/enroll_email_enrolledsubject.txt delete mode 100644 lms/templates/ccx/unenroll_email_allowedmessage.txt delete mode 100644 lms/templates/ccx/unenroll_email_enrolledmessage.txt delete mode 100644 lms/templates/ccx/unenroll_email_subject.txt delete mode 100644 lms/templates/emails/account_creation_and_enroll_emailMessage.txt delete mode 100644 lms/templates/emails/add_beta_tester_email_message.txt delete mode 100644 lms/templates/emails/add_beta_tester_email_subject.txt delete mode 100644 lms/templates/emails/enroll_email_allowedmessage.txt delete mode 100644 lms/templates/emails/enroll_email_allowedsubject.txt delete mode 100644 lms/templates/emails/enroll_email_enrolledmessage.txt delete mode 100644 lms/templates/emails/enroll_email_enrolledsubject.txt delete mode 100644 lms/templates/emails/remove_beta_tester_email_message.txt delete mode 100644 lms/templates/emails/remove_beta_tester_email_subject.txt delete mode 100644 lms/templates/emails/unenroll_email_allowedmessage.txt delete mode 100644 lms/templates/emails/unenroll_email_enrolledmessage.txt delete mode 100644 lms/templates/emails/unenroll_email_subject.txt create mode 100644 lms/templates/instructor/edx_ace/accountcreationandenrollment/email/body.html create mode 100644 lms/templates/instructor/edx_ace/accountcreationandenrollment/email/body.txt create mode 100644 lms/templates/instructor/edx_ace/accountcreationandenrollment/email/from_name.txt create mode 100644 lms/templates/instructor/edx_ace/accountcreationandenrollment/email/head.html create mode 100644 lms/templates/instructor/edx_ace/accountcreationandenrollment/email/subject.txt create mode 100644 lms/templates/instructor/edx_ace/addbetatester/email/body.html create mode 100644 lms/templates/instructor/edx_ace/addbetatester/email/body.txt create mode 100644 lms/templates/instructor/edx_ace/addbetatester/email/from_name.txt create mode 100644 lms/templates/instructor/edx_ace/addbetatester/email/head.html create mode 100644 lms/templates/instructor/edx_ace/addbetatester/email/subject.txt create mode 100644 lms/templates/instructor/edx_ace/allowedenroll/email/body.html create mode 100644 lms/templates/instructor/edx_ace/allowedenroll/email/body.txt create mode 100644 lms/templates/instructor/edx_ace/allowedenroll/email/from_name.txt create mode 100644 lms/templates/instructor/edx_ace/allowedenroll/email/head.html create mode 100644 lms/templates/instructor/edx_ace/allowedenroll/email/subject.txt create mode 100644 lms/templates/instructor/edx_ace/allowedunenroll/email/body.html create mode 100644 lms/templates/instructor/edx_ace/allowedunenroll/email/body.txt create mode 100644 lms/templates/instructor/edx_ace/allowedunenroll/email/from_name.txt create mode 100644 lms/templates/instructor/edx_ace/allowedunenroll/email/head.html create mode 100644 lms/templates/instructor/edx_ace/allowedunenroll/email/subject.txt create mode 100644 lms/templates/instructor/edx_ace/enrolledunenroll/email/body.html create mode 100644 lms/templates/instructor/edx_ace/enrolledunenroll/email/body.txt create mode 100644 lms/templates/instructor/edx_ace/enrolledunenroll/email/from_name.txt create mode 100644 lms/templates/instructor/edx_ace/enrolledunenroll/email/head.html create mode 100644 lms/templates/instructor/edx_ace/enrolledunenroll/email/subject.txt create mode 100644 lms/templates/instructor/edx_ace/enrollenrolled/email/body.html create mode 100644 lms/templates/instructor/edx_ace/enrollenrolled/email/body.txt create mode 100644 lms/templates/instructor/edx_ace/enrollenrolled/email/from_name.txt create mode 100644 lms/templates/instructor/edx_ace/enrollenrolled/email/head.html create mode 100644 lms/templates/instructor/edx_ace/enrollenrolled/email/subject.txt create mode 100644 lms/templates/instructor/edx_ace/removebetatester/email/body.html create mode 100644 lms/templates/instructor/edx_ace/removebetatester/email/body.txt create mode 100644 lms/templates/instructor/edx_ace/removebetatester/email/from_name.txt create mode 100644 lms/templates/instructor/edx_ace/removebetatester/email/head.html create mode 100644 lms/templates/instructor/edx_ace/removebetatester/email/subject.txt diff --git a/common/test/test_sites/test_site/templates/emails/enroll_email_allowedmessage.txt b/common/test/test_sites/test_site/templates/emails/enroll_email_allowedmessage.txt deleted file mode 100644 index 07ab2f601e..0000000000 --- a/common/test/test_sites/test_site/templates/emails/enroll_email_allowedmessage.txt +++ /dev/null @@ -1,30 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear student,")} - -${_("You have been invited to join {course_name} at {site_name} by a " - "member of the course staff.").format( - course_name=course.display_name_with_default_escaped, - site_name=site_name - )} - -${_("To finish your registration, please visit {registration_url} and fill " - "out the registration form making sure to use {email_address} in the E-mail field.").format( - registration_url=registration_url, - email_address=email_address - )} -% if auto_enroll: -${_("Once you have registered and activated your account, you will see " - "{course_name} listed on your dashboard.").format( - course_name=course.display_name_with_default_escaped - )} -% else: -${_("Once you have registered and activated your account, visit {course_about_url} " - "to join the course.").format(course_about_url=course_about_url)} -% endif - ----- -${_("This email was automatically sent from {site_name} to " - "{email_address}").format( - site_name=site_name, email_address=email_address - )} \ No newline at end of file diff --git a/common/test/test_sites/test_site/templates/emails/enroll_email_allowedsubject.txt b/common/test/test_sites/test_site/templates/emails/enroll_email_allowedsubject.txt deleted file mode 100644 index bcd58b1b6c..0000000000 --- a/common/test/test_sites/test_site/templates/emails/enroll_email_allowedsubject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been invited to register for {course_name}").format( - course_name=course.display_name_with_default_escaped - )} \ No newline at end of file diff --git a/common/test/test_sites/test_site/templates/emails/enroll_email_enrolledmessage.txt b/common/test/test_sites/test_site/templates/emails/enroll_email_enrolledmessage.txt deleted file mode 100644 index d7fe613f0e..0000000000 --- a/common/test/test_sites/test_site/templates/emails/enroll_email_enrolledmessage.txt +++ /dev/null @@ -1,20 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear {full_name}").format(full_name=full_name)} - -${_("You have been enrolled in {course_name} at {site_name} by a member " - "of the course staff. The course should now appear on your {site_name} " - "dashboard.").format( - course_name=course.display_name_with_default_escaped, - site_name=site_name - )} - -${_("To start accessing course materials, please visit {course_url}").format( - course_url=course_url - )} - ----- -${_("This email was automatically sent from {site_name} to " - "{full_name}").format( - site_name=site_name, full_name=full_name - )} \ No newline at end of file diff --git a/common/test/test_sites/test_site/templates/emails/enroll_email_enrolledsubject.txt b/common/test/test_sites/test_site/templates/emails/enroll_email_enrolledsubject.txt deleted file mode 100644 index 0252b90451..0000000000 --- a/common/test/test_sites/test_site/templates/emails/enroll_email_enrolledsubject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been enrolled in {course_name}").format( - course_name=course.display_name_with_default_escaped - )} \ No newline at end of file diff --git a/common/test/test_sites/test_site/templates/emails/unenroll_email_allowedmessage.txt b/common/test/test_sites/test_site/templates/emails/unenroll_email_allowedmessage.txt deleted file mode 100644 index 17f7afc415..0000000000 --- a/common/test/test_sites/test_site/templates/emails/unenroll_email_allowedmessage.txt +++ /dev/null @@ -1,13 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear Student,")} - -${_("You have been un-enrolled from course {course_name} by a member " - "of the course staff. Please disregard the invitation " - "previously sent.").format(course_name=course.display_name_with_default_escaped)} - ----- -${_("This email was automatically sent from {site_name} " - "to {email_address}").format( - site_name=site_name, email_address=email_address - )} \ No newline at end of file diff --git a/common/test/test_sites/test_site/templates/emails/unenroll_email_enrolledmessage.txt b/common/test/test_sites/test_site/templates/emails/unenroll_email_enrolledmessage.txt deleted file mode 100644 index c9e0463e2a..0000000000 --- a/common/test/test_sites/test_site/templates/emails/unenroll_email_enrolledmessage.txt +++ /dev/null @@ -1,17 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear {full_name}").format(full_name=full_name)} - -${_("You have been un-enrolled in {course_name} at {site_name} by a member " - "of the course staff. The course will no longer appear on your " - "{site_name} dashboard.").format( - course_name=course.display_name_with_default_escaped, site_name=site_name - )} - -${_("Your other courses have not been affected.")} - ----- -${_("This email was automatically sent from {site_name} to " - "{full_name}").format( - full_name=full_name, site_name=site_name - )} diff --git a/common/test/test_sites/test_site/templates/emails/unenroll_email_subject.txt b/common/test/test_sites/test_site/templates/emails/unenroll_email_subject.txt deleted file mode 100644 index 5be3aad439..0000000000 --- a/common/test/test_sites/test_site/templates/emails/unenroll_email_subject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been un-enrolled from {course_name}").format( - course_name=course.display_name_with_default_escaped -)} \ No newline at end of file diff --git a/lms/djangoapps/ccx/tests/utils.py b/lms/djangoapps/ccx/tests/utils.py index b0383fbf56..42e4c718d1 100644 --- a/lms/djangoapps/ccx/tests/utils.py +++ b/lms/djangoapps/ccx/tests/utils.py @@ -8,6 +8,7 @@ from django.conf import settings from lms.djangoapps.ccx.overrides import override_field_for_ccx from lms.djangoapps.ccx.tests.factories import CcxFactory +from openedx.core.djangoapps.ace_common.tests.mixins import EmailTemplateTagMixin from student.roles import CourseCcxCoachRole, CourseInstructorRole, CourseStaffRole from student.tests.factories import UserFactory from xmodule.modulestore.django import modulestore @@ -15,7 +16,7 @@ from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory -class CcxTestCase(SharedModuleStoreTestCase): +class CcxTestCase(EmailTemplateTagMixin, SharedModuleStoreTestCase): """ General test class to be used in other CCX tests classes. diff --git a/lms/djangoapps/instructor/enrollment.py b/lms/djangoapps/instructor/enrollment.py index 3fabe4630f..ed599886c5 100644 --- a/lms/djangoapps/instructor/enrollment.py +++ b/lms/djangoapps/instructor/enrollment.py @@ -12,18 +12,29 @@ import pytz from django.conf import settings from django.contrib.auth.models import User from django.core.mail import send_mail +from django.template.loader import render_to_string from django.urls import reverse from django.utils.translation import override as override_language +from edx_ace import ace +from edx_ace.recipient import Recipient from six import text_type from course_modes.models import CourseMode from courseware.models import StudentModule -from edxmako.shortcuts import render_to_string from eventtracking import tracker from lms.djangoapps.grades.constants import ScoreDatabaseTableEnum from lms.djangoapps.grades.events import STATE_DELETED_EVENT_TYPE from lms.djangoapps.grades.signals.handlers import disconnect_submissions_signal_receiver from lms.djangoapps.grades.signals.signals import PROBLEM_RAW_SCORE_CHANGED +from lms.djangoapps.instructor.message_types import ( + AccountCreationAndEnrollment, + AddBetaTester, + AllowedEnroll, + AllowedUnenroll, + EnrollEnrolled, + EnrolledUnenroll, + RemoveBetaTester, +) from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.user_api.models import UserPreference @@ -146,16 +157,17 @@ def enroll_email(course_id, student_email, auto_enroll=False, email_students=Fal enrollment_obj = CourseEnrollment.enroll_by_email(student_email, course_id, course_mode) if email_students: - email_params['message'] = 'enrolled_enroll' + email_params['message_type'] = 'enrolled_enroll' email_params['email_address'] = student_email email_params['full_name'] = previous_state.full_name send_mail_to_student(student_email, email_params, language=language) + elif not is_email_retired(student_email): cea, _ = CourseEnrollmentAllowed.objects.get_or_create(course_id=course_id, email=student_email) cea.auto_enroll = auto_enroll cea.save() if email_students: - email_params['message'] = 'allowed_enroll' + email_params['message_type'] = 'allowed_enroll' email_params['email_address'] = student_email send_mail_to_student(student_email, email_params, language=language) @@ -180,7 +192,7 @@ def unenroll_email(course_id, student_email, email_students=False, email_params= if previous_state.enrollment: CourseEnrollment.unenroll_by_email(student_email, course_id) if email_students: - email_params['message'] = 'enrolled_unenroll' + email_params['message_type'] = 'enrolled_unenroll' email_params['email_address'] = student_email email_params['full_name'] = previous_state.full_name send_mail_to_student(student_email, email_params, language=language) @@ -188,7 +200,7 @@ def unenroll_email(course_id, student_email, email_students=False, email_params= if previous_state.allowed: CourseEnrollmentAllowed.objects.get(course_id=course_id, email=student_email).delete() if email_students: - email_params['message'] = 'allowed_unenroll' + email_params['message_type'] = 'allowed_unenroll' email_params['email_address'] = student_email # Since no User object exists for this student there is no "full_name" available. send_mail_to_student(student_email, email_params, language=language) @@ -207,7 +219,7 @@ def send_beta_role_email(action, user, email_params): `email_params` parameters used while parsing email templates (a `dict`). """ if action in ('add', 'remove'): - email_params['message'] = '%s_beta_tester' % action + email_params['message_type'] = '%s_beta_tester' % action email_params['email_address'] = user.email email_params['full_name'] = user.profile.name else: @@ -422,7 +434,7 @@ def send_mail_to_student(student, param_dict, language=None): `course_url`: url of course (a `str`) `email_address`: email of student (a `str`) `full_name`: student full name (a `str`) - `message`: type of email to send and template to use (a `str`) + `message_type`: type of email to send and template to use (a `str`) `is_shib_course`: (a `boolean`) ] @@ -433,71 +445,39 @@ def send_mail_to_student(student, param_dict, language=None): Returns a boolean indicating whether the email was sent successfully. """ - # add some helpers and microconfig subsitutions + # Add some helpers and microconfig subsitutions if 'display_name' in param_dict: param_dict['course_name'] = param_dict['display_name'] + elif 'course' in param_dict: + param_dict['course_name'] = param_dict['course'].display_name_with_default param_dict['site_name'] = configuration_helpers.get_value( 'SITE_NAME', param_dict['site_name'] ) - subject = None - message = None - # see if there is an activation email template definition available as configuration, # if so, then render that - message_type = param_dict['message'] + message_type = param_dict['message_type'] - email_template_dict = { - 'allowed_enroll': ( - 'emails/enroll_email_allowedsubject.txt', - 'emails/enroll_email_allowedmessage.txt' - ), - 'enrolled_enroll': ( - 'emails/enroll_email_enrolledsubject.txt', - 'emails/enroll_email_enrolledmessage.txt' - ), - 'allowed_unenroll': ( - 'emails/unenroll_email_subject.txt', - 'emails/unenroll_email_allowedmessage.txt' - ), - 'enrolled_unenroll': ( - 'emails/unenroll_email_subject.txt', - 'emails/unenroll_email_enrolledmessage.txt' - ), - 'add_beta_tester': ( - 'emails/add_beta_tester_email_subject.txt', - 'emails/add_beta_tester_email_message.txt' - ), - 'remove_beta_tester': ( - 'emails/remove_beta_tester_email_subject.txt', - 'emails/remove_beta_tester_email_message.txt' - ), - 'account_creation_and_enrollment': ( - 'emails/enroll_email_enrolledsubject.txt', - 'emails/account_creation_and_enroll_emailMessage.txt' - ), + ace_emails_dict = { + 'account_creation_and_enrollment': AccountCreationAndEnrollment, + 'add_beta_tester': AddBetaTester, + 'allowed_enroll': AllowedEnroll, + 'allowed_unenroll': AllowedUnenroll, + 'enrolled_enroll': EnrollEnrolled, + 'enrolled_unenroll': EnrolledUnenroll, + 'remove_beta_tester': RemoveBetaTester, } - subject_template, message_template = email_template_dict.get(message_type, (None, None)) - if subject_template is not None and message_template is not None: - subject, message = render_message_to_string( - subject_template, message_template, param_dict, language=language - ) + message_class = ace_emails_dict[message_type] + message = message_class().personalize( + recipient=Recipient(username='', email_address=student), + language=language, + user_context=param_dict, + ) - if subject and message: - # Remove leading and trailing whitespace from body - message = message.strip() - - # Email subject *must not* contain newlines - subject = ''.join(subject.splitlines()) - from_address = configuration_helpers.get_value( - 'email_from_address', - settings.DEFAULT_FROM_EMAIL - ) - - send_mail(subject, message, from_address, [student], fail_silently=False) + ace.send(message) def render_message_to_string(subject_template, message_template, param_dict, language=None): diff --git a/lms/djangoapps/instructor/message_types.py b/lms/djangoapps/instructor/message_types.py new file mode 100644 index 0000000000..d229b4d76f --- /dev/null +++ b/lms/djangoapps/instructor/message_types.py @@ -0,0 +1,84 @@ +""" +ACE message types for the instructor module. +""" + +from openedx.core.djangoapps.ace_common.message import BaseMessageType + + +class AccountCreationAndEnrollment(BaseMessageType): + """ + A message for registering and inviting learners into a course. + + This message includes username and password. + """ + APP_LABEL = 'instructor' + + def __init__(self, *args, **kwargs): + super(AccountCreationAndEnrollment, self).__init__(*args, **kwargs) + self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + + +class AddBetaTester(BaseMessageType): + """ + A message for course beta testers when they're invited. + """ + APP_LABEL = 'instructor' + + def __init__(self, *args, **kwargs): + super(AddBetaTester, self).__init__(*args, **kwargs) + self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + + +class AllowedEnroll(BaseMessageType): + """ + A message for _unregistered_ learners who received an invitation to a course. + """ + APP_LABEL = 'instructor' + + def __init__(self, *args, **kwargs): + super(AllowedEnroll, self).__init__(*args, **kwargs) + self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + + +class AllowedUnenroll(BaseMessageType): + """ + A message for _unregistered_ learners who had their invitation to a course cancelled. + """ + APP_LABEL = 'instructor' + + def __init__(self, *args, **kwargs): + super(AllowedUnenroll, self).__init__(*args, **kwargs) + self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + + +class EnrollEnrolled(BaseMessageType): + """ + A message for _registered_ learners who have been both invited and enrolled to a course. + """ + APP_LABEL = 'instructor' + + def __init__(self, *args, **kwargs): + super(EnrollEnrolled, self).__init__(*args, **kwargs) + self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + + +class EnrolledUnenroll(BaseMessageType): + """ + A message for _registered_ learners who have been unenrolled from a course. + """ + APP_LABEL = 'instructor' + + def __init__(self, *args, **kwargs): + super(EnrolledUnenroll, self).__init__(*args, **kwargs) + self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation + + +class RemoveBetaTester(BaseMessageType): + """ + A message for course beta testers when they're removed. + """ + APP_LABEL = 'instructor' + + def __init__(self, *args, **kwargs): + super(RemoveBetaTester, self).__init__(*args, **kwargs) + self.options['transactional'] = True # pylint: disable=unsupported-assignment-operation diff --git a/lms/djangoapps/instructor/tests/test_access.py b/lms/djangoapps/instructor/tests/test_access.py index 2c374bf016..63f9c65a6a 100644 --- a/lms/djangoapps/instructor/tests/test_access.py +++ b/lms/djangoapps/instructor/tests/test_access.py @@ -7,6 +7,7 @@ import pytest from django_comment_common.models import FORUM_ROLE_MODERATOR, Role from lms.djangoapps.instructor.access import allow_access, list_with_level, revoke_access, update_forum_role from openedx.core.lib.tests import attr +from openedx.core.djangoapps.ace_common.tests.mixins import EmailTemplateTagMixin from student.roles import CourseBetaTesterRole, CourseCcxCoachRole, CourseStaffRole from student.tests.factories import UserFactory from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase @@ -40,7 +41,7 @@ class TestInstructorAccessList(SharedModuleStoreTestCase): @attr(shard=1) -class TestInstructorAccessAllow(SharedModuleStoreTestCase): +class TestInstructorAccessAllow(EmailTemplateTagMixin, SharedModuleStoreTestCase): """ Test access allow. """ @classmethod def setUpClass(cls): diff --git a/lms/djangoapps/instructor/tests/test_api.py b/lms/djangoapps/instructor/tests/test_api.py index cd11d51ccd..e4bdcd4554 100644 --- a/lms/djangoapps/instructor/tests/test_api.py +++ b/lms/djangoapps/instructor/tests/test_api.py @@ -1304,18 +1304,26 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest mail.outbox[0].subject, u'You have been enrolled in {}'.format(self.course.display_name) ) - self.assertEqual( - mail.outbox[0].body, - "Dear NotEnrolled Student\n\nYou have been enrolled in {} " - "at edx.org by a member of the course staff. " - "The course should now appear on your edx.org dashboard.\n\n" - "To start accessing course materials, please visit " - "{proto}://{site}{course_path}\n\n----\n" - "This email was automatically sent from edx.org to NotEnrolled Student".format( - self.course.display_name, - proto=protocol, site=self.site_name, course_path=self.course_path - ) - ) + + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + + assert text_body.startswith('Dear NotEnrolled Student\n\n') + + for body in [text_body, html_body]: + self.assertIn('You have been enrolled in {course_name} at edx.org by a member of the course staff.'.format( + course_name=self.course.display_name, + ), body) + + self.assertIn('This course will now appear on your edx.org dashboard.', body) + self.assertIn('{proto}://{site}{course_path}'.format( + proto=protocol, + site=self.site_name, + course_path=self.course_path, + ), body) + + self.assertIn("To start accessing course materials, please visit", text_body) + self.assertIn("This email was automatically sent from edx.org to NotEnrolled Student\n\n", text_body) @ddt.data('http', 'https') def test_enroll_with_email_not_registered(self, protocol): @@ -1334,17 +1342,35 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest mail.outbox[0].subject, u'You have been invited to register for {}'.format(self.course.display_name) ) - self.assertEqual( - mail.outbox[0].body, - "Dear student,\n\nYou have been invited to join {} at edx.org by a member of the course staff.\n\n" - "To finish your registration, please visit {proto}://{site}/register and fill out the " - "registration form making sure to use robot-not-an-email-yet@robot.org in the E-mail field.\n" - "Once you have registered and activated your account, " - "visit {proto}://{site}{about_path} to join the course.\n\n----\n" - "This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org".format( - self.course.display_name, proto=protocol, site=self.site_name, about_path=self.about_path - ) - ) + + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + register_url = '{proto}://{site}/register'.format(proto=protocol, site=self.site_name) + + assert text_body.startswith('Dear student,') + assert 'To finish your registration, please visit {register_url}'.format( + register_url=register_url, + ) in text_body + assert 'Please finish your registration and fill out' in html_body + assert register_url in html_body + + for body in [text_body, html_body]: + assert 'You have been invited to join {course} at edx.org by a member of the course staff.'.format( + course=self.course.display_name + ) in body + + assert ('fill out the registration form making sure to use ' + 'robot-not-an-email-yet@robot.org in the Email field') in body + + assert 'Once you have registered and activated your account,' in body + + assert '{proto}://{site}{about_path}'.format( + proto=protocol, + site=self.site_name, + about_path=self.about_path + ) in body + + assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body @ddt.data('http', 'https') @patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True}) @@ -1358,17 +1384,32 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest self.assertEqual(manual_enrollments.count(), 1) self.assertEqual(manual_enrollments[0].state_transition, UNENROLLED_TO_ALLOWEDTOENROLL) self.assertEqual(response.status_code, 200) - self.assertEqual( - mail.outbox[0].body, - "Dear student,\n\nYou have been invited to join {display_name}" - " at edx.org by a member of the course staff.\n\n" - "To finish your registration, please visit {proto}://{site}/register and fill out the registration form " - "making sure to use robot-not-an-email-yet@robot.org in the E-mail field.\n" - "You can then enroll in {display_name}.\n\n----\n" - "This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org".format( - display_name=self.course.display_name, proto=protocol, site=self.site_name - ) - ) + + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + + assert text_body.startswith('Dear student,') + assert 'To finish your registration, please visit' in text_body + assert 'Please finish your registration and fill' in html_body + + for body in [text_body, html_body]: + assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( + display_name=self.course.display_name + ) in body + + assert '{proto}://{site}/register'.format( + proto=protocol, + site=self.site_name + ) in body + + assert ('fill out the registration form making sure to use ' + 'robot-not-an-email-yet@robot.org in the Email field') in body + + assert 'You can then enroll in {display_name}.'.format( + display_name=self.course.display_name + ) in body + + assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body @ddt.data('http', 'https') def test_enroll_with_email_not_registered_autoenroll(self, protocol): @@ -1389,19 +1430,38 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest manual_enrollments = ManualEnrollmentAudit.objects.all() self.assertEqual(manual_enrollments.count(), 1) self.assertEqual(manual_enrollments[0].state_transition, UNENROLLED_TO_ALLOWEDTOENROLL) - self.assertEqual( - mail.outbox[0].body, - "Dear student,\n\nYou have been invited to join {display_name}" - " at edx.org by a member of the course staff.\n\n" - "To finish your registration, please visit {proto}://{site}/register and fill out the registration form " - "making sure to use robot-not-an-email-yet@robot.org in the E-mail field.\n" - "Once you have registered and activated your account," - " you will see {display_name} listed on your dashboard.\n\n----\n" - "This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org".format( - proto=protocol, site=self.site_name, display_name=self.course.display_name - ) + + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + register_url = '{proto}://{site}/register'.format( + proto=protocol, + site=self.site_name, ) + assert text_body.startswith('Dear student,') + assert 'To finish your registration, please visit {register_url}'.format( + register_url=register_url, + ) in text_body + assert 'Please finish your registration and fill out the registration' in html_body + assert 'Finish Your Registration' in html_body + assert register_url in html_body + + for body in [text_body, html_body]: + assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( + display_name=self.course.display_name + ) in body + + assert (' and fill ' + 'out the registration form making sure to use robot-not-an-email-yet@robot.org ' + 'in the Email field') in body + + assert ('Once you have registered and activated your account, ' + 'you will see {display_name} listed on your dashboard.').format( + display_name=self.course.display_name + ) in body + + assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body + def test_unenroll_without_email(self): url = reverse('students_update_enrollment', kwargs={'course_id': text_type(self.course.id)}) response = self.client.post(url, {'identifiers': self.enrolled_student.email, 'action': 'unenroll', @@ -1489,18 +1549,22 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest self.assertEqual(len(mail.outbox), 1) self.assertEqual( mail.outbox[0].subject, - 'You have been un-enrolled from {display_name}'.format(display_name=self.course.display_name,) + 'You have been unenrolled from {display_name}'.format(display_name=self.course.display_name,) ) - self.assertEqual( - mail.outbox[0].body, - "Dear Enrolled Student\n\nYou have been un-enrolled in {display_name} " - "at edx.org by a member of the course staff. " - "The course will no longer appear on your edx.org dashboard.\n\n" - "Your other courses have not been affected.\n\n----\n" - "This email was automatically sent from edx.org to Enrolled Student".format( + + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + + assert text_body.startswith('Dear Enrolled Student') + + for body in [text_body, html_body]: + assert 'You have been unenrolled from {display_name} at edx.org by a member of the course staff.'.format( display_name=self.course.display_name, - ) - ) + ) in body + + assert 'This course will no longer appear on your edx.org dashboard.' in body + assert 'Your other courses have not been affected.' in body + assert 'This email was automatically sent from edx.org to Enrolled Student' in body def test_unenroll_with_email_allowed_student(self): url = reverse('students_update_enrollment', kwargs={'course_id': text_type(self.course.id)}) @@ -1542,16 +1606,20 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest self.assertEqual(len(mail.outbox), 1) self.assertEqual( mail.outbox[0].subject, - 'You have been un-enrolled from {display_name}'.format(display_name=self.course.display_name,) + 'You have been unenrolled from {display_name}'.format(display_name=self.course.display_name,) ) - self.assertEqual( - mail.outbox[0].body, - "Dear Student,\n\nYou have been un-enrolled from course {display_name} by a member of the course staff. " - "Please disregard the invitation previously sent.\n\n----\n" - "This email was automatically sent from edx.org to robot-allowed@robot.org".format( + + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + assert text_body.startswith('Dear Student,') + + for body in [text_body, html_body]: + assert 'You have been unenrolled from the course {display_name} by a member of the course staff.'.format( display_name=self.course.display_name, - ) - ) + ) in body + + assert 'Please disregard the invitation previously sent.' in body + assert 'This email was automatically sent from edx.org to robot-allowed@robot.org' in body @ddt.data('http', 'https') @patch('lms.djangoapps.instructor.enrollment.uses_shib') @@ -1571,15 +1639,26 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest 'You have been invited to register for {display_name}'.format(display_name=self.course.display_name,) ) - self.assertEqual( - mail.outbox[0].body, - "Dear student,\n\nYou have been invited to join {display_name} at edx.org by a member of the course staff.\n\n" - "To access the course visit {proto}://{site}{about_path} and register for the course.\n\n----\n" - "This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org".format( - proto=protocol, site=self.site_name, about_path=self.about_path, - display_name=self.course.display_name, - ) + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + course_url = '{proto}://{site}{about_path}'.format( + proto=protocol, + site=self.site_name, + about_path=self.about_path, ) + assert text_body.startswith('Dear student,') + assert 'To access this course visit {course_url} and register for this course.'.format( + course_url=course_url, + ) in text_body + assert 'To access this course visit it and register:' in html_body + assert course_url in html_body + + for body in [text_body, html_body]: + assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( + display_name=self.course.display_name, + ) in body + + assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body @patch('lms.djangoapps.instructor.enrollment.uses_shib') @patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True}) @@ -1594,13 +1673,17 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest 'email_students': True}) self.assertEqual(response.status_code, 200) - self.assertEqual( - mail.outbox[0].body, - "Dear student,\n\nYou have been invited to join {} at edx.org by a member of the course staff.\n\n----\n" - "This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org".format( - self.course.display_name, - ) - ) + + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + assert text_body.startswith('Dear student,') + + for body in [text_body, html_body]: + assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( + display_name=self.course.display_name, + ) in body + + assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body @ddt.data('http', 'https') @patch('lms.djangoapps.instructor.enrollment.uses_shib') @@ -1622,17 +1705,24 @@ class TestInstructorAPIEnrollment(SharedModuleStoreTestCase, LoginEnrollmentTest 'You have been invited to register for {display_name}'.format(display_name=self.course.display_name,) ) - self.assertEqual( - mail.outbox[0].body, - "Dear student,\n\nYou have been invited to join {display_name}" - " at edx.org by a member of the course staff.\n\n" - "To access the course visit {proto}://{site}{course_path} and login.\n\n----\n" - "This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org".format( - display_name=self.course.display_name, - proto=protocol, site=self.site_name, course_path=self.course_path - ) + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + course_url = '{proto}://{site}{course_path}'.format( + proto=protocol, site=self.site_name, course_path=self.course_path, ) + assert text_body.startswith('Dear student,') + assert course_url in html_body + assert 'To access this course visit {course_url} and login.'.format(course_url=course_url) in text_body + assert 'To access this course click on the button below and login:' in html_body + + for body in [text_body, html_body]: + assert 'You have been invited to join {display_name} at edx.org by a member of the course staff.'.format( + display_name=self.course.display_name, + ) in body + + assert 'This email was automatically sent from edx.org to robot-not-an-email-yet@robot.org' in body + def test_enroll_already_enrolled_student(self): """ Ensure that already enrolled "verified" students cannot be downgraded @@ -1965,21 +2055,29 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll 'You have been invited to a beta test for {display_name}'.format(display_name=self.course.display_name,) ) - self.assertEqual( - mail.outbox[0].body, - u"Dear {student_name}\n\nYou have been invited to be a beta tester " - "for {display_name} at edx.org by a member of the course staff.\n\n" - "Visit {proto}://{site}{about_path} to join " - "the course and begin the beta test.\n\n----\n" - "This email was automatically sent from edx.org to {student_email}".format( + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + student_name = self.notenrolled_student.profile.name + assert text_body.startswith('Dear {student_name}'.format(student_name=student_name)) + assert 'Visit {display_name}'.format(display_name=self.course.display_name) in html_body + + for body in [text_body, html_body]: + assert 'You have been invited to be a beta tester for {display_name} at edx.org'.format( display_name=self.course.display_name, - student_name=self.notenrolled_student.profile.name, - student_email=self.notenrolled_student.email, + ) in body + + assert 'by a member of the course staff.' in body + assert 'enroll in this course and begin the beta test' in body + + assert '{proto}://{site}{about_path}'.format( proto=protocol, site=self.site_name, - about_path=self.about_path - ) - ) + about_path=self.about_path, + ) in body + + assert 'This email was automatically sent from edx.org to {student_email}'.format( + student_email=self.notenrolled_student.email, + ) in body @ddt.data('http', 'https') def test_add_notenrolled_with_email_autoenroll(self, protocol): @@ -2013,21 +2111,28 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll 'You have been invited to a beta test for {display_name}'.format(display_name=self.course.display_name) ) - self.assertEqual( - mail.outbox[0].body, - u"Dear {student_name}\n\nYou have been invited to be a beta tester " - "for {display_name} at edx.org by a member of the course staff.\n\n" - "To start accessing course materials, please visit " - "{proto}://{site}{course_path}\n\n----\n" - "This email was automatically sent from edx.org to {student_email}".format( + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + student_name = self.notenrolled_student.profile.name + assert text_body.startswith('Dear {student_name}'.format(student_name=student_name)) + + for body in [text_body, html_body]: + assert 'You have been invited to be a beta tester for {display_name} at edx.org'.format( display_name=self.course.display_name, - student_name=self.notenrolled_student.profile.name, - student_email=self.notenrolled_student.email, + ) in body + + assert 'by a member of the course staff' in body + + assert 'To start accessing course materials, please visit' in body + assert '{proto}://{site}{course_path}'.format( proto=protocol, site=self.site_name, course_path=self.course_path ) - ) + + assert 'This email was automatically sent from edx.org to {student_email}'.format( + student_email=self.notenrolled_student.email, + ) in body @patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True}) def test_add_notenrolled_email_mktgsite(self): @@ -2036,17 +2141,23 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll response = self.client.post(url, {'identifiers': self.notenrolled_student.email, 'action': 'add', 'email_students': True}) self.assertEqual(response.status_code, 200) - self.assertEqual( - mail.outbox[0].body, - u"Dear {}\n\nYou have been invited to be a beta tester " - "for {} at edx.org by a member of the course staff.\n\n" - "Visit edx.org to enroll in the course and begin the beta test.\n\n----\n" - "This email was automatically sent from edx.org to {}".format( - self.notenrolled_student.profile.name, - self.course.display_name, - self.notenrolled_student.email, - ) - ) + + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + student_name = self.notenrolled_student.profile.name + assert text_body.startswith('Dear {student_name}'.format(student_name=student_name)) + + for body in [text_body, html_body]: + assert 'You have been invited to be a beta tester for {display_name} at edx.org'.format( + display_name=self.course.display_name, + ) in body + + assert 'by a member of the course staff.' in body + assert 'Visit edx.org' in body + assert 'enroll in this course and begin the beta test' in body + assert 'This email was automatically sent from edx.org to {student_email}'.format( + student_email=self.notenrolled_student.email, + ) in body def test_enroll_with_email_not_registered(self): # User doesn't exist @@ -2137,19 +2248,24 @@ class TestInstructorAPIBulkBetaEnrollment(SharedModuleStoreTestCase, LoginEnroll mail.outbox[0].subject, u'You have been removed from a beta test for {display_name}'.format(display_name=self.course.display_name,) ) - self.assertEqual( - mail.outbox[0].body, - "Dear {full_name}\n\nYou have been removed as a beta tester for " - "{display_name} at edx.org by a member of the course staff. " - "The course will remain on your dashboard, but you will no longer " - "be part of the beta testing group.\n\n" - "Your other courses have not been affected.\n\n----\n" - "This email was automatically sent from edx.org to {email_address}".format( + + text_body = mail.outbox[0].body + html_body = mail.outbox[0].alternatives[0][0] + assert text_body.startswith('Dear {name}'.format(name=self.beta_tester.profile.name)) + + for body in [text_body, html_body]: + assert 'You have been removed as a beta tester for {display_name} at edx.org'.format( display_name=self.course.display_name, - full_name=self.beta_tester.profile.name, - email_address=self.beta_tester.email - ) - ) + ) in body + + assert ('This course will remain on your dashboard, but you will no longer be ' + 'part of the beta testing group.') in body + + assert 'Your other courses have not been affected.' in body + + assert 'This email was automatically sent from edx.org to {email_address}'.format( + email_address=self.beta_tester.email, + ) in body @attr(shard=5) diff --git a/lms/djangoapps/instructor/tests/test_api_email_localization.py b/lms/djangoapps/instructor/tests/test_api_email_localization.py index e4af756a8d..9432473796 100644 --- a/lms/djangoapps/instructor/tests/test_api_email_localization.py +++ b/lms/djangoapps/instructor/tests/test_api_email_localization.py @@ -33,14 +33,14 @@ class TestInstructorAPIEnrollmentEmailLocalization(SharedModuleStoreTestCase): super(TestInstructorAPIEnrollmentEmailLocalization, self).setUp() # Platform language is English, instructor's language is Chinese, - # student's language is French, so the emails should all be sent in - # French. + # student's language is Esperanto, so the emails should all be sent in + # Esperanto. self.instructor = InstructorFactory(course_key=self.course.id) set_user_preference(self.instructor, LANGUAGE_KEY, 'zh-cn') self.client.login(username=self.instructor.username, password='test') self.student = UserFactory.create() - set_user_preference(self.student, LANGUAGE_KEY, 'fr') + set_user_preference(self.student, LANGUAGE_KEY, 'eo') def update_enrollement(self, action, student_email): """ @@ -51,12 +51,12 @@ class TestInstructorAPIEnrollmentEmailLocalization(SharedModuleStoreTestCase): response = self.client.post(url, args) return response - def check_outbox_is_french(self): + def check_outbox_is_esperanto(self): """ Check that the email outbox contains exactly one message for which both - the message subject and body contain a certain French string. + the message subject and body contain a certain Esperanto string. """ - return self.check_outbox(u"Vous avez été") + return self.check_outbox(u"Ýöü hävé ßéén") def check_outbox(self, expected_message): """ @@ -70,7 +70,7 @@ class TestInstructorAPIEnrollmentEmailLocalization(SharedModuleStoreTestCase): def test_enroll(self): self.update_enrollement("enroll", self.student.email) - self.check_outbox_is_french() + self.check_outbox_is_esperanto() def test_unenroll(self): CourseEnrollment.enroll( @@ -79,22 +79,22 @@ class TestInstructorAPIEnrollmentEmailLocalization(SharedModuleStoreTestCase): ) self.update_enrollement("unenroll", self.student.email) - self.check_outbox_is_french() + self.check_outbox_is_esperanto() def test_set_beta_role(self): url = reverse('bulk_beta_modify_access', kwargs={'course_id': text_type(self.course.id)}) self.client.post(url, {'identifiers': self.student.email, 'action': 'add', 'email_students': 'true'}) - self.check_outbox_is_french() + self.check_outbox_is_esperanto() def test_enroll_unsubscribed_student(self): # Student is unknown, so the platform language should be used self.update_enrollement("enroll", "newuser@hotmail.com") self.check_outbox("You have been") - @override_settings(LANGUAGE_CODE="fr") - def test_user_without_preference_receives_email_in_french(self): + @override_settings(LANGUAGE_CODE="eo") + def test_user_without_preference_receives_email_in_esperanto(self): delete_user_preference(self.student, LANGUAGE_KEY) self.update_enrollement("enroll", self.student.email) - self.check_outbox_is_french() + self.check_outbox_is_esperanto() diff --git a/lms/djangoapps/instructor/tests/test_enrollment.py b/lms/djangoapps/instructor/tests/test_enrollment.py index f21b53c1c2..c505e26127 100644 --- a/lms/djangoapps/instructor/tests/test_enrollment.py +++ b/lms/djangoapps/instructor/tests/test_enrollment.py @@ -6,6 +6,7 @@ Unit tests for instructor.enrollment methods. import json from abc import ABCMeta +import ddt import mock from ccx_keys.locator import CCXLocator from django.conf import settings @@ -31,6 +32,7 @@ from lms.djangoapps.instructor.enrollment import ( send_beta_role_email, unenroll_email ) +from openedx.core.djangoapps.ace_common.tests.mixins import EmailTemplateTagMixin from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, get_mock_request from openedx.core.lib.tests import attr from student.models import CourseEnrollment, CourseEnrollmentAllowed, anonymous_id_for_user @@ -762,7 +764,8 @@ class TestGetEmailParams(SharedModuleStoreTestCase): @attr(shard=1) -class TestRenderMessageToString(SharedModuleStoreTestCase): +@ddt.ddt +class TestRenderMessageToString(EmailTemplateTagMixin, SharedModuleStoreTestCase): """ Test that email templates can be rendered in a language chosen manually. Test CCX enrollmet email. @@ -773,8 +776,8 @@ class TestRenderMessageToString(SharedModuleStoreTestCase): def setUpClass(cls): super(TestRenderMessageToString, cls).setUpClass() cls.course = CourseFactory.create() - cls.subject_template = 'emails/enroll_email_allowedsubject.txt' - cls.message_template = 'emails/enroll_email_allowedmessage.txt' + cls.subject_template = 'instructor/edx_ace/allowedenroll/email/subject.txt' + cls.message_template = 'instructor/edx_ace/allowedenroll/email/body.txt' @patch.dict('django.conf.settings.FEATURES', {'CUSTOM_COURSES_EDX': True}) def setUp(self): @@ -792,6 +795,7 @@ class TestRenderMessageToString(SharedModuleStoreTestCase): email_params = get_email_params(self.course, True) email_params["email_address"] = "user@example.com" email_params["full_name"] = "Jean Reno" + email_params["course_name"] = email_params["display_name"] return email_params @@ -807,6 +811,8 @@ class TestRenderMessageToString(SharedModuleStoreTestCase): ) email_params["email_address"] = "user@example.com" email_params["full_name"] = "Jean Reno" + email_params["course_name"] = email_params["display_name"] + email_params.update(self.context) return email_params @@ -832,12 +838,12 @@ class TestRenderMessageToString(SharedModuleStoreTestCase): ) def test_subject_and_message_translation(self): - subject, message = self.get_subject_and_message('fr') + subject, message = self.get_subject_and_message('eo') language_after_rendering = get_language() - you_have_been_invited_in_french = u"Vous avez été invité" - self.assertIn(you_have_been_invited_in_french, subject) - self.assertIn(you_have_been_invited_in_french, message) + you_have_been_invited_in_esperanto = u"Ýöü hävé ßéén" + self.assertIn(you_have_been_invited_in_esperanto, subject) + self.assertIn(you_have_been_invited_in_esperanto, message) self.assertEqual(settings.LANGUAGE_CODE, language_after_rendering) def test_platform_language_is_used_for_logged_in_user(self): @@ -847,15 +853,19 @@ class TestRenderMessageToString(SharedModuleStoreTestCase): self.assertIn("You have been", message) @patch.dict('django.conf.settings.FEATURES', {'CUSTOM_COURSES_EDX': True}) - def test_render_enrollment_message_ccx_members(self): + @ddt.data('body.txt', 'body.html') + def test_render_enrollment_message_ccx_members(self, body_file_name): """ Test enrollment email template renders for CCX. For EDX members. """ - subject_template = 'emails/enroll_email_enrolledsubject.txt' - message_template = 'emails/enroll_email_enrolledmessage.txt' + subject_template = 'instructor/edx_ace/enrollenrolled/email/subject.txt' + body_template = 'instructor/edx_ace/enrollenrolled/email/{body_file_name}'.format( + body_file_name=body_file_name, + ) + + subject, message = self.get_subject_and_message_ccx(subject_template, body_template) - subject, message = self.get_subject_and_message_ccx(subject_template, message_template) self.assertIn(self.ccx.display_name, subject) self.assertIn(self.ccx.display_name, message) site = settings.SITE_NAME @@ -866,28 +876,34 @@ class TestRenderMessageToString(SharedModuleStoreTestCase): self.assertIn(course_url, message) @patch.dict('django.conf.settings.FEATURES', {'CUSTOM_COURSES_EDX': True}) - def test_render_unenrollment_message_ccx_members(self): + @ddt.data('body.txt', 'body.html') + def test_render_unenrollment_message_ccx_members(self, body_file_name): """ Test unenrollment email template renders for CCX. For EDX members. """ - subject_template = 'emails/unenroll_email_subject.txt' - message_template = 'emails/unenroll_email_enrolledmessage.txt' + subject_template = 'instructor/edx_ace/enrolledunenroll/email/subject.txt' + body_template = 'instructor/edx_ace/enrolledunenroll/email/{body_file_name}'.format( + body_file_name=body_file_name, + ) - subject, message = self.get_subject_and_message_ccx(subject_template, message_template) + subject, message = self.get_subject_and_message_ccx(subject_template, body_template) self.assertIn(self.ccx.display_name, subject) self.assertIn(self.ccx.display_name, message) @patch.dict('django.conf.settings.FEATURES', {'CUSTOM_COURSES_EDX': True}) - def test_render_enrollment_message_ccx_non_members(self): + @ddt.data('body.txt', 'body.html') + def test_render_enrollment_message_ccx_non_members(self, body_file_name): """ Test enrollment email template renders for CCX. For non EDX members. """ - subject_template = 'emails/enroll_email_allowedsubject.txt' - message_template = 'emails/enroll_email_allowedmessage.txt' + subject_template = 'instructor/edx_ace/allowedenroll/email/subject.txt' + body_template = 'instructor/edx_ace/allowedenroll/email/{body_file_name}'.format( + body_file_name=body_file_name, + ) - subject, message = self.get_subject_and_message_ccx(subject_template, message_template) + subject, message = self.get_subject_and_message_ccx(subject_template, body_template) self.assertIn(self.ccx.display_name, subject) self.assertIn(self.ccx.display_name, message) site = settings.SITE_NAME @@ -895,14 +911,17 @@ class TestRenderMessageToString(SharedModuleStoreTestCase): self.assertIn(registration_url, message) @patch.dict('django.conf.settings.FEATURES', {'CUSTOM_COURSES_EDX': True}) - def test_render_unenrollment_message_ccx_non_members(self): + @ddt.data('body.txt', 'body.html') + def test_render_unenrollment_message_ccx_non_members(self, body_file_name): """ Test unenrollment email template renders for CCX. For non EDX members. """ - subject_template = 'emails/unenroll_email_subject.txt' - message_template = 'emails/unenroll_email_allowedmessage.txt' + subject_template = 'instructor/edx_ace/allowedunenroll/email/subject.txt' + body_template = 'instructor/edx_ace/allowedunenroll/email/{body_file_name}'.format( + body_file_name=body_file_name, + ) - subject, message = self.get_subject_and_message_ccx(subject_template, message_template) + subject, message = self.get_subject_and_message_ccx(subject_template, body_template) self.assertIn(self.ccx.display_name, subject) self.assertIn(self.ccx.display_name, message) diff --git a/lms/djangoapps/instructor/views/api.py b/lms/djangoapps/instructor/views/api.py index 4bd40fbee2..b2c50c4036 100644 --- a/lms/djangoapps/instructor/views/api.py +++ b/lms/djangoapps/instructor/views/api.py @@ -574,7 +574,7 @@ def create_and_enroll_user(email, username, name, country, password, course_id, try: # It's a new user, an email will be sent to each newly created user. email_params.update({ - 'message': 'account_creation_and_enrollment', + 'message_type': 'account_creation_and_enrollment', 'email_address': email, 'password': password, 'platform_name': configuration_helpers.get_value('platform_name', settings.PLATFORM_NAME), diff --git a/lms/djangoapps/instructor/views/registration_codes.py b/lms/djangoapps/instructor/views/registration_codes.py index 357de69be6..1c1123ff92 100644 --- a/lms/djangoapps/instructor/views/registration_codes.py +++ b/lms/djangoapps/instructor/views/registration_codes.py @@ -118,7 +118,7 @@ def delete_redemption_entry(request, code_redemption, course_key): course = get_course_by_id(course_key, depth=0) email_params = get_email_params(course, True, secure=request.is_secure()) - email_params['message'] = 'enrolled_unenroll' + email_params['message_type'] = 'enrolled_unenroll' email_params['email_address'] = email_address email_params['full_name'] = full_name send_mail_to_student(email_address, email_params) diff --git a/lms/templates/ccx/enroll_email_allowedmessage.txt b/lms/templates/ccx/enroll_email_allowedmessage.txt deleted file mode 100644 index 4315b038d0..0000000000 --- a/lms/templates/ccx/enroll_email_allowedmessage.txt +++ /dev/null @@ -1,43 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear student,")} - -${_("You have been invited to join {course_name} at {site_name} by a " - "member of the course staff.").format( - course_name=course.display_name, - site_name=site_name - )} -% if is_shib_course: -% if auto_enroll: - -${_("To access the course visit {course_url} and login.").format(course_url=course_url)} -% elif course_about_url is not None: - -${_("To access the course visit {course_about_url} and register for the course.").format( - course_about_url=course_about_url)} -% endif -% else: - -${_("To finish your registration, please visit {registration_url} and fill " - "out the registration form making sure to use {email_address} in the E-mail field.").format( - registration_url=registration_url, - email_address=email_address - )} -% if auto_enroll: -${_("Once you have registered and activated your account, you will see " - "{course_name} listed on your dashboard.").format( - course_name=course.display_name - )} -% elif course_about_url is not None: -${_("Once you have registered and activated your account, visit {course_about_url} " - "to join the course.").format(course_about_url=course_about_url)} -% else: -${_("You can then enroll in {course_name}.").format(course_name=course.display_name)} -% endif -% endif - ----- -${_("This email was automatically sent from {site_name} to " - "{email_address}").format( - site_name=site_name, email_address=email_address - )} diff --git a/lms/templates/ccx/enroll_email_allowedsubject.txt b/lms/templates/ccx/enroll_email_allowedsubject.txt deleted file mode 100644 index 0a39036140..0000000000 --- a/lms/templates/ccx/enroll_email_allowedsubject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been invited to register for {course_name}").format( - course_name=course.display_name - )} diff --git a/lms/templates/ccx/enroll_email_enrolledmessage.txt b/lms/templates/ccx/enroll_email_enrolledmessage.txt deleted file mode 100644 index b24f5a4a36..0000000000 --- a/lms/templates/ccx/enroll_email_enrolledmessage.txt +++ /dev/null @@ -1,20 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear {full_name}").format(full_name=full_name)} - -${_("You have been enrolled in {course_name} at {site_name} by a member " - "of the course staff. The course should now appear on your {site_name} " - "dashboard.").format( - course_name=course.display_name, - site_name=site_name - )} - -${_("To start accessing course materials, please visit {course_url}").format( - course_url=course_url - )} - ----- -${_("This email was automatically sent from {site_name} to " - "{full_name}").format( - site_name=site_name, full_name=full_name - )} diff --git a/lms/templates/ccx/enroll_email_enrolledsubject.txt b/lms/templates/ccx/enroll_email_enrolledsubject.txt deleted file mode 100644 index dc84c3f0a8..0000000000 --- a/lms/templates/ccx/enroll_email_enrolledsubject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been enrolled in {course_name}").format( - course_name=course.display_name - )} diff --git a/lms/templates/ccx/unenroll_email_allowedmessage.txt b/lms/templates/ccx/unenroll_email_allowedmessage.txt deleted file mode 100644 index 6eca90b8d5..0000000000 --- a/lms/templates/ccx/unenroll_email_allowedmessage.txt +++ /dev/null @@ -1,13 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear Student,")} - -${_("You have been un-enrolled from course {course_name} by a member " - "of the course staff. Please disregard the invitation " - "previously sent.").format(course_name=course.display_name)} - ----- -${_("This email was automatically sent from {site_name} " - "to {email_address}").format( - site_name=site_name, email_address=email_address - )} diff --git a/lms/templates/ccx/unenroll_email_enrolledmessage.txt b/lms/templates/ccx/unenroll_email_enrolledmessage.txt deleted file mode 100644 index 38770886c0..0000000000 --- a/lms/templates/ccx/unenroll_email_enrolledmessage.txt +++ /dev/null @@ -1,17 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear {full_name}").format(full_name=full_name)} - -${_("You have been un-enrolled in {course_name} at {site_name} by a member " - "of the course staff. The course will no longer appear on your " - "{site_name} dashboard.").format( - course_name=course.display_name, site_name=site_name - )} - -${_("Your other courses have not been affected.")} - ----- -${_("This email was automatically sent from {site_name} to " - "{full_name}").format( - full_name=full_name, site_name=site_name - )} diff --git a/lms/templates/ccx/unenroll_email_subject.txt b/lms/templates/ccx/unenroll_email_subject.txt deleted file mode 100644 index 4b971dcb35..0000000000 --- a/lms/templates/ccx/unenroll_email_subject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been un-enrolled from {course_name}").format( - course_name=course.display_name -)} diff --git a/lms/templates/emails/account_creation_and_enroll_emailMessage.txt b/lms/templates/emails/account_creation_and_enroll_emailMessage.txt deleted file mode 100644 index 0d88ebe34d..0000000000 --- a/lms/templates/emails/account_creation_and_enroll_emailMessage.txt +++ /dev/null @@ -1,14 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Welcome to {course_name}").format(course_name=course.display_name_with_default_escaped)} - -${_("To get started, please visit https://{site_name}. The login information for your account follows.").format(site_name=site_name)} - -${_("email: {email}").format(email=email_address)} -${_("password: {password}").format(password=password)} - -${_("It is recommended that you change your password.")} - -${_("Sincerely yours," -"" -"The {course_name} Team").format(course_name=course.display_name_with_default_escaped)} diff --git a/lms/templates/emails/activation_email.txt b/lms/templates/emails/activation_email.txt index 4c4d431a0c..f5b1f09331 100644 --- a/lms/templates/emails/activation_email.txt +++ b/lms/templates/emails/activation_email.txt @@ -1,3 +1,4 @@ +## mako <%! from django.utils.translation import ugettext as _ %> ${_("You're almost there! Use the link to activate your account to access engaging, high-quality " "{platform_name} courses. Note that you will not be able to log back into your account until " diff --git a/lms/templates/emails/activation_email_subject.txt b/lms/templates/emails/activation_email_subject.txt index cdb52fe458..a6961b8e6a 100644 --- a/lms/templates/emails/activation_email_subject.txt +++ b/lms/templates/emails/activation_email_subject.txt @@ -1,2 +1,3 @@ +## mako <%! from django.utils.translation import ugettext as _ %> ${_("Action Required: Activate your {platform_name} account").format(platform_name=platform_name)} diff --git a/lms/templates/emails/add_beta_tester_email_message.txt b/lms/templates/emails/add_beta_tester_email_message.txt deleted file mode 100644 index 9c544bda32..0000000000 --- a/lms/templates/emails/add_beta_tester_email_message.txt +++ /dev/null @@ -1,25 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear {full_name}").format(full_name=full_name)} - -${_("You have been invited to be a beta tester for {course_name} at {site_name} by a " - "member of the course staff.").format( - course_name=course.display_name_with_default_escaped, - site_name=site_name - )} - -% if auto_enroll: -${_("To start accessing course materials, please visit {course_url}").format( - course_url=course_url - )} -% elif course_about_url is not None: -${_("Visit {course_about_url} to join the course and begin the beta test.").format(course_about_url=course_about_url)} -% else: -${_("Visit {site_name} to enroll in the course and begin the beta test.").format(site_name=site_name)} -% endif - ----- -${_("This email was automatically sent from {site_name} to " - "{email_address}").format( - site_name=site_name, email_address=email_address - )} diff --git a/lms/templates/emails/add_beta_tester_email_subject.txt b/lms/templates/emails/add_beta_tester_email_subject.txt deleted file mode 100644 index eee3f83a8d..0000000000 --- a/lms/templates/emails/add_beta_tester_email_subject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been invited to a beta test for {course_name}").format( - course_name=course.display_name_with_default_escaped - )} diff --git a/lms/templates/emails/business_order_confirmation_email.txt b/lms/templates/emails/business_order_confirmation_email.txt index 5da0c794a8..8e83c86712 100644 --- a/lms/templates/emails/business_order_confirmation_email.txt +++ b/lms/templates/emails/business_order_confirmation_email.txt @@ -1,3 +1,4 @@ +## mako <%! from django.utils.translation import ugettext as _ %>
${_("Hi {name},").format(name=recipient_name)} diff --git a/lms/templates/emails/confirm_email_change.txt b/lms/templates/emails/confirm_email_change.txt index 8f5df7083e..3bff7faa4a 100644 --- a/lms/templates/emails/confirm_email_change.txt +++ b/lms/templates/emails/confirm_email_change.txt @@ -1,3 +1,4 @@ +## mako <%! from django.urls import reverse %> <%! from django.utils.translation import ugettext as _ %> <%! from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers %> diff --git a/lms/templates/emails/email_change.txt b/lms/templates/emails/email_change.txt index a025d2dbf0..a589369c6f 100644 --- a/lms/templates/emails/email_change.txt +++ b/lms/templates/emails/email_change.txt @@ -1,3 +1,4 @@ +## mako <%! from django.utils.translation import ugettext as _ %> <%! from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers %> ${_("We received a request to change the e-mail associated with your " diff --git a/lms/templates/emails/email_change_subject.txt b/lms/templates/emails/email_change_subject.txt index 11c27e52de..683e4fff1c 100644 --- a/lms/templates/emails/email_change_subject.txt +++ b/lms/templates/emails/email_change_subject.txt @@ -1,3 +1,4 @@ +## mako <%! from django.utils.translation import ugettext as _ %> <%! from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers %> ${_("Request to change {platform_name} account e-mail").format( diff --git a/lms/templates/emails/enroll_email_allowedmessage.txt b/lms/templates/emails/enroll_email_allowedmessage.txt deleted file mode 100644 index 8f120a10f2..0000000000 --- a/lms/templates/emails/enroll_email_allowedmessage.txt +++ /dev/null @@ -1,43 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear student,")} - -${_("You have been invited to join {course_name} at {site_name} by a " - "member of the course staff.").format( - course_name=display_name or course.display_name_with_default_escaped, - site_name=site_name - )} -% if is_shib_course: -% if auto_enroll: - -${_("To access the course visit {course_url} and login.").format(course_url=course_url)} -% elif course_about_url is not None: - -${_("To access the course visit {course_about_url} and register for the course.").format( - course_about_url=course_about_url)} -% endif -% else: - -${_("To finish your registration, please visit {registration_url} and fill " - "out the registration form making sure to use {email_address} in the E-mail field.").format( - registration_url=registration_url, - email_address=email_address - )} -% if auto_enroll: -${_("Once you have registered and activated your account, you will see " - "{course_name} listed on your dashboard.").format( - course_name=display_name or course.display_name_with_default_escaped - )} -% elif course_about_url is not None: -${_("Once you have registered and activated your account, visit {course_about_url} " - "to join the course.").format(course_about_url=course_about_url)} -% else: -${_("You can then enroll in {course_name}.").format(course_name=display_name or course.display_name_with_default_escaped)} -% endif -% endif - ----- -${_("This email was automatically sent from {site_name} to " - "{email_address}").format( - site_name=site_name, email_address=email_address - )} diff --git a/lms/templates/emails/enroll_email_allowedsubject.txt b/lms/templates/emails/enroll_email_allowedsubject.txt deleted file mode 100644 index 3a9df2271c..0000000000 --- a/lms/templates/emails/enroll_email_allowedsubject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been invited to register for {course_name}").format( - course_name=display_name or course.display_name_with_default_escaped - )} \ No newline at end of file diff --git a/lms/templates/emails/enroll_email_enrolledmessage.txt b/lms/templates/emails/enroll_email_enrolledmessage.txt deleted file mode 100644 index cc40568280..0000000000 --- a/lms/templates/emails/enroll_email_enrolledmessage.txt +++ /dev/null @@ -1,20 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear {full_name}").format(full_name=full_name)} - -${_("You have been enrolled in {course_name} at {site_name} by a member " - "of the course staff. The course should now appear on your {site_name} " - "dashboard.").format( - course_name=display_name or course.display_name_with_default_escaped, - site_name=site_name - )} - -${_("To start accessing course materials, please visit {course_url}").format( - course_url=course_url - )} - ----- -${_("This email was automatically sent from {site_name} to " - "{full_name}").format( - site_name=site_name, full_name=full_name - )} \ No newline at end of file diff --git a/lms/templates/emails/enroll_email_enrolledsubject.txt b/lms/templates/emails/enroll_email_enrolledsubject.txt deleted file mode 100644 index 7774aac1cc..0000000000 --- a/lms/templates/emails/enroll_email_enrolledsubject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been enrolled in {course_name}").format( - course_name=display_name or course.display_name_with_default_escaped - )} \ No newline at end of file diff --git a/lms/templates/emails/order_confirmation_email.txt b/lms/templates/emails/order_confirmation_email.txt index 706378158d..b875edef84 100644 --- a/lms/templates/emails/order_confirmation_email.txt +++ b/lms/templates/emails/order_confirmation_email.txt @@ -1,3 +1,4 @@ +## mako <%! from django.utils.translation import ugettext as _ %> ${_("Hi {name},").format(name=order.user.profile.name)} diff --git a/lms/templates/emails/photo_submission_confirmation.txt b/lms/templates/emails/photo_submission_confirmation.txt index d54c7866df..44c97790a1 100644 --- a/lms/templates/emails/photo_submission_confirmation.txt +++ b/lms/templates/emails/photo_submission_confirmation.txt @@ -1,3 +1,4 @@ +## mako <%! from django.utils.translation import ugettext as _ %> ${_("Hi {full_name},").format(full_name=full_name)} diff --git a/lms/templates/emails/registration_codes_sale_email.txt b/lms/templates/emails/registration_codes_sale_email.txt index e6fbd71515..876a88855f 100644 --- a/lms/templates/emails/registration_codes_sale_email.txt +++ b/lms/templates/emails/registration_codes_sale_email.txt @@ -1,3 +1,4 @@ +## mako <%! from django.utils.translation import ugettext as _ %> ${_("Thank you for purchasing enrollments in {course_name}.").format(course_name=course.display_name)} diff --git a/lms/templates/emails/registration_codes_sale_invoice_attachment.txt b/lms/templates/emails/registration_codes_sale_invoice_attachment.txt index cc01c944f2..ef1eacb73f 100644 --- a/lms/templates/emails/registration_codes_sale_invoice_attachment.txt +++ b/lms/templates/emails/registration_codes_sale_invoice_attachment.txt @@ -1,3 +1,4 @@ +## mako <%! from django.utils.translation import ugettext as _ %> ${_("INVOICE")} diff --git a/lms/templates/emails/reject_name_change.txt b/lms/templates/emails/reject_name_change.txt index 33816faf7b..4079d964bd 100644 --- a/lms/templates/emails/reject_name_change.txt +++ b/lms/templates/emails/reject_name_change.txt @@ -1,3 +1,4 @@ +## mako <%! from django.utils.translation import ugettext as _ %> <%namespace name='static' file='../static_content.html'/> (Not currently used) diff --git a/lms/templates/emails/remove_beta_tester_email_message.txt b/lms/templates/emails/remove_beta_tester_email_message.txt deleted file mode 100644 index 6bcfa51de8..0000000000 --- a/lms/templates/emails/remove_beta_tester_email_message.txt +++ /dev/null @@ -1,18 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear {full_name}").format(full_name=full_name)} - -${_("You have been removed as a beta tester for {course_name} at {site_name} by a " - "member of the course staff. The course will remain on your dashboard, but " - "you will no longer be part of the beta testing group.").format( - course_name=course.display_name_with_default_escaped, - site_name=site_name - )} - -${_("Your other courses have not been affected.")} - ----- -${_("This email was automatically sent from {site_name} to " - "{email_address}").format( - site_name=site_name, email_address=email_address - )} diff --git a/lms/templates/emails/remove_beta_tester_email_subject.txt b/lms/templates/emails/remove_beta_tester_email_subject.txt deleted file mode 100644 index 47cb095026..0000000000 --- a/lms/templates/emails/remove_beta_tester_email_subject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been removed from a beta test for {course_name}").format( - course_name=course.display_name_with_default_escaped - )} diff --git a/lms/templates/emails/reverification_processed.txt b/lms/templates/emails/reverification_processed.txt index a35c149b3b..0f65e16ac6 100644 --- a/lms/templates/emails/reverification_processed.txt +++ b/lms/templates/emails/reverification_processed.txt @@ -1,3 +1,4 @@ +## mako <%! from django.utils.translation import ugettext as _ %> % if status == "approved": ${_("We have successfully verified your identity for the {assessment} assessment in the {course_name} course." diff --git a/lms/templates/emails/unenroll_email_allowedmessage.txt b/lms/templates/emails/unenroll_email_allowedmessage.txt deleted file mode 100644 index 5b2524a046..0000000000 --- a/lms/templates/emails/unenroll_email_allowedmessage.txt +++ /dev/null @@ -1,13 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear Student,")} - -${_("You have been un-enrolled from course {course_name} by a member " - "of the course staff. Please disregard the invitation " - "previously sent.").format(course_name=display_name or course.display_name_with_default_escaped)} - ----- -${_("This email was automatically sent from {site_name} " - "to {email_address}").format( - site_name=site_name, email_address=email_address - )} \ No newline at end of file diff --git a/lms/templates/emails/unenroll_email_enrolledmessage.txt b/lms/templates/emails/unenroll_email_enrolledmessage.txt deleted file mode 100644 index 1dee0a64ae..0000000000 --- a/lms/templates/emails/unenroll_email_enrolledmessage.txt +++ /dev/null @@ -1,17 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("Dear {full_name}").format(full_name=full_name)} - -${_("You have been un-enrolled in {course_name} at {site_name} by a member " - "of the course staff. The course will no longer appear on your " - "{site_name} dashboard.").format( - course_name=display_name or course.display_name_with_default_escaped, site_name=site_name - )} - -${_("Your other courses have not been affected.")} - ----- -${_("This email was automatically sent from {site_name} to " - "{full_name}").format( - full_name=full_name, site_name=site_name - )} diff --git a/lms/templates/emails/unenroll_email_subject.txt b/lms/templates/emails/unenroll_email_subject.txt deleted file mode 100644 index 1db012d9e7..0000000000 --- a/lms/templates/emails/unenroll_email_subject.txt +++ /dev/null @@ -1,5 +0,0 @@ -<%! from django.utils.translation import ugettext as _ %> - -${_("You have been un-enrolled from {course_name}").format( - course_name=display_name or course.display_name_with_default_escaped -)} \ No newline at end of file diff --git a/lms/templates/instructor/edx_ace/accountcreationandenrollment/email/body.html b/lms/templates/instructor/edx_ace/accountcreationandenrollment/email/body.html new file mode 100644 index 0000000000..237309ad7a --- /dev/null +++ b/lms/templates/instructor/edx_ace/accountcreationandenrollment/email/body.html @@ -0,0 +1,41 @@ +{% extends 'ace_common/edx_ace/common/base_body.html' %} + +{% load i18n %} +{% load static %} +{% block content %} +
+ + {% blocktrans %} + Welcome to {{ course_name }} + {% endblocktrans %} ++ +
+ {% blocktrans %}To get started, please visit https://{{ site_name }}.{% endblocktrans %}
+
+ {% blocktrans %}The login information for your account follows:{% endblocktrans %}
+
+ {% blocktrans %}It is recommended that you change your password.{% endblocktrans %}
+
+ {% blocktrans %}Sincerely yours, The {{ course_name }} Team{% endblocktrans %}
+ |
+
+ + {% blocktrans %} + You have been invited to be a beta tester for {{ course_name }} at {{ site_name }} + {% endblocktrans %} ++ +
+ {% blocktrans %}The invitation has been sent by a member of the course staff.{% endblocktrans %}
+
+ {% blocktrans %}To start accessing course materials, please visit:{% endblocktrans %}
+
+ {% blocktrans %}To enroll in this course and begin the beta test:{% endblocktrans %}
+
+ {% blocktrans %}To enroll in this course and begin the beta test:{% endblocktrans %}
+
+ {% blocktrans %}This email was automatically sent from {{ site_name }} to {{ email_address }}{% endblocktrans %}
+ |
+
+ + {% blocktrans %}You have been invited to {{ course_name }}{% endblocktrans %} ++ +
+ {% blocktrans %}You have been invited to join {{ course_name }} at {{ site_name }} by a member of the course staff.{% endblocktrans %}
+
+ {% blocktrans %}To access this course click on the button below and login:{% endblocktrans %}
+
+ {% blocktrans %}To access this course visit it and register:{% endblocktrans %}
+
+ {% blocktrans %}Please finish your registration and fill out the registration form making sure to use {{ email_address }} in the Email field:{% endblocktrans %}
+
+ {% if auto_enroll %}
+ {% blocktrans %}Once you have registered and activated your account, you will see {{ course_name }} listed on your dashboard.{% endblocktrans %}
+ {% elif course_about_url is not None %}
+ {% blocktrans %}Once you have registered and activated your account, you will be able to access this course:{% endblocktrans %}
+ {% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_name course_cta_url=course_about_url %}
+ {% else %}
+ {% blocktrans %}You can then enroll in {{ course_name }}.{% endblocktrans %}
+ {% endif %}
+
+ {% blocktrans %}This email was automatically sent from {{ site_name }} to {{ email_address }}{% endblocktrans %}
+ |
+
+ + {% blocktrans %}You have been unenrolled from {{ course_name }}{% endblocktrans %} ++ +
+ {% blocktrans %}You have been unenrolled from the course {{ course_name }} by a member of the course staff. Please disregard the invitation previously sent.{% endblocktrans %}
+
+ {% blocktrans %}This email was automatically sent from {{ site_name }} to {{ email_address }}{% endblocktrans %}
+ |
+
+ + {% blocktrans %} + You have been unenrolled from {{ course_name }} + {% endblocktrans %} ++ +
+ {% blocktrans %}You have been unenrolled from {{ course_name }} at {{ site_name }} by a member of the course staff. This course will no longer appear on your {{ site_name }} dashboard.{% endblocktrans %}
+
+ {% blocktrans %}Your other courses have not been affected.{% endblocktrans %}
+
+ {% blocktrans %}This email was automatically sent from {{ site_name }} to {{ full_name }}{% endblocktrans %}
+ |
+
+ + {% blocktrans %} + You have been enrolled in {{ course_name }} + {% endblocktrans %} ++ +
+ {% blocktrans %}You have been enrolled in {{ course_name }} at {{ site_name }} by a member of the course staff. This course will now appear on your {{ site_name }} dashboard.{% endblocktrans %}
+
+ {% blocktrans %}This email was automatically sent from {{ site_name }} to {{ full_name }}{% endblocktrans %}
+ |
+
+ + {% blocktrans %}You have been removed as a beta tester for {{ course_name }} at {{ site_name }}{% endblocktrans %} ++ +
+ {% blocktrans %}You have been removed as a beta tester for {{ course_name }} at {{ site_name }} by a member of the course staff.{% endblocktrans %}
+
+ {% blocktrans %}This course will remain on your dashboard, but you will no longer be part of the beta testing group.{% endblocktrans %}
+
+ {% blocktrans %}Your other courses have not been affected.{% endblocktrans %}
+
+ {% blocktrans %}This email was automatically sent from {{ site_name }} to {{ email_address }}{% endblocktrans %}
+ |
+
SQ_)5wCwJJ+FEC0Av}QUz*DS^#ZTGe
zc_eBze2X!7 1k8Y6)RK!1~q~QsE~#AvJ0j~
z&FKIvk25g}f5s~K6xERuy=|)6V+QK|FfLBTta|>>rJy<5iR!>P9FJN1SP0jmBCrt?
z={Qsfk771F>(^hRrXZ}Z _dR5;{PAYgn7-JC7)cv6M&}rGcV1?25b(ipsMji_&RzE^LPEOCF_j
zLMJHGcL?T(C!tvRD=0C)SPJX;WGJ?>AD)Fzpt#?zlu=Gda=!MdqBJ|b0KY_@kUC0Z
zcd9f|x(l`yo}fN&+9-WL?{kP05yr_
~(w;wxs?Z8>s!Reb2uJ>rhX6&%WSjgQKbM$L3i1FV=rFg~b%q)5F*Sqwm}6
z_e2~^J?{hCST
M0m#uvw5(*WqC2<);E08ACONhJ2$x@AD86|TK=EP&H_5BY+1u6Nk>SC;0_7y
z!GgQH%ishE5C{n*!KHB-To3N<-na#K1_ozv1|M_=#&}
}NlmIx#j~FqRd9n4qdf@&(EC%hQ`VEL
zjgpgFo<)$b6FzQ?5cE44e0;OjXsfN0z{CJ^2SQ^e9Vmvw3_u1jMC!Abzq#1gTA{2D
ztF9fD6#*+bwjhZ9P9mqI2e&1~yryd+5$uQAJ7NF+$3sUAod6hx;T2Ae0k9Hu2{P@d
z@*#
6s;&nCJ*j-M-2*}p=}S^Ck|*NY=|qBp
z_;ZW3FH)Di$Y8Md6Z;Oo5Hn