diff --git a/common/djangoapps/student/tasks.py b/common/djangoapps/student/tasks.py index f3d6644cbf..9ab3908acc 100644 --- a/common/djangoapps/student/tasks.py +++ b/common/djangoapps/student/tasks.py @@ -15,7 +15,7 @@ log = logging.getLogger('edx.celery.task') @task(bind=True) def send_activation_email(self, subject, message, from_address, dest_addr): """ - Sending an activation email to the users. + Sending an activation email to the user. """ max_retries = settings.RETRY_ACTIVATION_EMAIL_MAX_ATTEMPTS retries = self.request.retries diff --git a/common/djangoapps/student/tests/test_email.py b/common/djangoapps/student/tests/test_email.py index 16bc35192d..529e23cbce 100644 --- a/common/djangoapps/student/tests/test_email.py +++ b/common/djangoapps/student/tests/test_email.py @@ -1,13 +1,15 @@ import json import unittest +import mock from student.tests.factories import UserFactory, RegistrationFactory, PendingEmailChangeFactory from student.views import ( reactivation_email_for_user, do_email_change_request, confirm_email_change, validate_new_email, SETTING_CHANGE_INITIATED ) -from student.models import UserProfile, PendingEmailChange +from student.models import UserProfile, PendingEmailChange, Registration +from third_party_auth.views import inactive_user_view from django.core.urlresolvers import reverse from django.core import mail from django.contrib.auth.models import User @@ -132,6 +134,24 @@ class ActivationEmailTests(TestCase): for fragment in body_fragments: self.assertIn(fragment, msg.body) + @mock.patch('student.tasks.log') + def test_send_email_to_inactive_user(self, mock_log): + """ + Tests that when an inactive user logs-in using the social auth, system + sends an activation email to the user. + """ + inactive_user = UserFactory(is_active=False) + Registration().register(inactive_user) + request = RequestFactory().get(settings.SOCIAL_AUTH_INACTIVE_USER_URL) + request.user = inactive_user + with patch('edxmako.request_context.get_current_request'): + inactive_user_view(request) + mock_log.info.assert_called_with( + "Activation Email has been sent to User {user_email}".format( + user_email=inactive_user.email + ) + ) + @patch('student.views.render_to_string', Mock(side_effect=mock_render_to_string, autospec=True)) @patch('django.contrib.auth.models.User.email_user') diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 02eaf539e4..616d732bfe 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -576,6 +576,38 @@ def is_course_blocked(request, redeemed_registration_codes, course_key): return blocked +def compose_and_send_activation_email(user, profile, user_registration=None): + """ + Construct all the required params and send the activation email + through celery task + + Arguments: + user: current logged-in user + profile: profile object of the current logged-in user + user_registration: registration of the current logged-in user + """ + dest_addr = user.email + if user_registration is None: + user_registration = Registration.objects.get(user=user) + context = { + 'name': profile.name, + 'key': user_registration.activation_key, + } + subject = render_to_string('emails/activation_email_subject.txt', context) + # Email subject *must not* contain newlines + subject = ''.join(subject.splitlines()) + message_for_activation = render_to_string('emails/activation_email.txt', context) + from_address = configuration_helpers.get_value( + 'email_from_address', + settings.DEFAULT_FROM_EMAIL + ) + if settings.FEATURES.get('REROUTE_ACTIVATION_EMAIL'): + dest_addr = settings.FEATURES['REROUTE_ACTIVATION_EMAIL'] + message_for_activation = ("Activation for %s (%s): %s\n" % (user, user.email, profile.name) + + '-' * 80 + '\n\n' + message_for_activation) + send_activation_email.delay(subject, message_for_activation, from_address, dest_addr) + + @login_required @ensure_csrf_cookie def dashboard(request): @@ -1356,7 +1388,6 @@ def login_user(request, error=""): # pylint: disable=too-many-statements,unused } } ) - if user is not None and user.is_active: try: # We do not log here, because we have a handler registered @@ -1848,27 +1879,7 @@ def create_account_with_params(request, params): ) ) if send_email: - dest_addr = user.email - context = { - 'name': profile.name, - 'key': registration.activation_key, - } - - # composes activation email - subject = render_to_string('emails/activation_email_subject.txt', context) - # Email subject *must not* contain newlines - subject = ''.join(subject.splitlines()) - message = render_to_string('emails/activation_email.txt', context) - - from_address = configuration_helpers.get_value( - 'email_from_address', - settings.DEFAULT_FROM_EMAIL - ) - if settings.FEATURES.get('REROUTE_ACTIVATION_EMAIL'): - dest_addr = settings.FEATURES['REROUTE_ACTIVATION_EMAIL'] - message = ("Activation for %s (%s): %s\n" % (user, user.email, profile.name) + - '-' * 80 + '\n\n' + message) - send_activation_email.delay(subject, message, from_address, dest_addr) + compose_and_send_activation_email(user, profile, registration) else: registration.activate() _enroll_user_in_pending_courses(user) # Enroll student in any pending courses diff --git a/common/djangoapps/third_party_auth/views.py b/common/djangoapps/third_party_auth/views.py index caf0ab2b5e..1a0003f7d7 100644 --- a/common/djangoapps/third_party_auth/views.py +++ b/common/djangoapps/third_party_auth/views.py @@ -10,6 +10,8 @@ import social from social.apps.django_app.views import complete from social.apps.django_app.utils import load_strategy, load_backend from social.utils import setting_name +from student.models import UserProfile +from student.views import compose_and_send_activation_email from .models import SAMLConfiguration URL_NAMESPACE = getattr(settings, setting_name('URL_NAMESPACE'), None) or 'social' @@ -28,6 +30,8 @@ def inactive_user_view(request): # 'next' may be set to '/account/finish_auth/.../' if this user needs to be auto-enrolled # in a course. Otherwise, just redirect them to the dashboard, which displays a message # about activating their account. + profile = UserProfile.objects.get(user=request.user) + compose_and_send_activation_email(request.user, profile) return redirect(request.GET.get('next', 'dashboard'))