Use edx-ace for password reset email

This commit is contained in:
Omar Al-Ithawi
2018-04-18 22:56:03 +03:00
committed by Gabe Mulley
parent 93809a8497
commit 73af914cfc
27 changed files with 271 additions and 135 deletions

View File

@@ -19,7 +19,7 @@ class AceCommonConfig(AppConfig):
ProjectType.LMS: {
SettingsType.AWS: {PluginSettings.RELATIVE_PATH: u'settings.aws'},
SettingsType.COMMON: {PluginSettings.RELATIVE_PATH: u'settings.common'},
SettingsType.DEVSTACK: {PluginSettings.RELATIVE_PATH: u'settings.common'},
SettingsType.DEVSTACK: {PluginSettings.RELATIVE_PATH: u'settings.devstack'},
}
}
}

View File

@@ -14,3 +14,10 @@ def plugin_settings(settings):
'ACE_CHANNEL_SAILTHRU_API_SECRET', settings.ACE_CHANNEL_SAILTHRU_API_SECRET,
)
settings.ACE_ROUTING_KEY = settings.ENV_TOKENS.get('ACE_ROUTING_KEY', settings.ACE_ROUTING_KEY)
settings.ACE_CHANNEL_DEFAULT_EMAIL = settings.ENV_TOKENS.get(
'ACE_CHANNEL_DEFAULT_EMAIL', settings.ACE_CHANNEL_DEFAULT_EMAIL
)
settings.ACE_CHANNEL_TRANSACTIONAL_EMAIL = settings.ENV_TOKENS.get(
'ACE_CHANNEL_TRANSACTIONAL_EMAIL', settings.ACE_CHANNEL_TRANSACTIONAL_EMAIL
)

View File

@@ -1,6 +1,6 @@
def plugin_settings(settings):
settings.ACE_ENABLED_CHANNELS = [
'file_email'
'django_email'
]
settings.ACE_ENABLED_POLICIES = [
'bulk_email_optout'
@@ -9,6 +9,8 @@ def plugin_settings(settings):
settings.ACE_CHANNEL_SAILTHRU_TEMPLATE_NAME = 'Automated Communication Engine Email'
settings.ACE_CHANNEL_SAILTHRU_API_KEY = None
settings.ACE_CHANNEL_SAILTHRU_API_SECRET = None
settings.ACE_CHANNEL_DEFAULT_EMAIL = 'django_email'
settings.ACE_CHANNEL_TRANSACTIONAL_EMAIL = 'django_email'
settings.ACE_ROUTING_KEY = 'edx.core.low'

View File

@@ -0,0 +1,19 @@
"""
Settings for edX ACE on devstack.
"""
from openedx.core.djangoapps.ace_common.settings import common
def plugin_settings(settings):
"""
Override common settings and use `file_email` for better debugging.
"""
common.plugin_settings(settings)
settings.ACE_ENABLED_CHANNELS = [
'file_email'
]
settings.ACE_CHANNEL_DEFAULT_EMAIL = 'file_email'
settings.ACE_CHANNEL_TRANSACTIONAL_EMAIL = 'file_email'

View File

@@ -20,9 +20,9 @@
{% block preview_text %}{% endblock %}
</div>
{# Note {beacon_src} is not a template variable that is evaluated by the Django template engine. It is evaluated by #}
{# Sailthru when the email is sent. Other email providers would need to replace this variable in the HTML as well. #}
<img src="{beacon_src}" alt="" role="presentation" aria-hidden="true" />
{% for image_src in channel.tracker_image_sources %}
<img src="{image_src}" alt="" role="presentation" aria-hidden="true" />
{% endfor %}
{% google_analytics_tracking_pixel %}
@@ -157,17 +157,13 @@
<tr>
<!-- Actions -->
<td style="padding-bottom: 20px;">
{# Note that these variables are evaluated by Sailthru, not the Django template engine #}
<p>
<a href="{view_url}" style="color: #005686">
<font color="#005686"><b>{% trans "View on Web" %}</b></font>
</a>
</p>
<p>
<a href="{optout_confirm_url}" style="color: #005686">
<font color="#005686"><b>{% trans "Unsubscribe from this list" %}</b></font>
</a>
</p>
{% for action_link_url, action_link_text in channel.action_links %}
<p>
<a href="{{ action_link_url }}" style="color: #005686">
<font color="#005686"><b>{{ action_link_text }}</b></font>
</a>
</p>
{% endfor %}
</td>
</tr>
<tr>

View File

@@ -7,8 +7,8 @@ import attr
import ddt
import pytz
from django.conf import settings
from edx_ace.channel import ChannelType
from edx_ace.test_utils import StubPolicy, patch_channels, patch_policies
from edx_ace.channel import ChannelMap, ChannelType
from edx_ace.test_utils import StubPolicy, patch_policies
from edx_ace.utils.date import serialize
from freezegun import freeze_time
from mock import Mock, patch
@@ -383,11 +383,16 @@ class ScheduleSendEmailTestMixin(FilteredQueryCountMixin):
)
patch_policies(self, [StubPolicy([ChannelType.PUSH])])
mock_channel = Mock(
name='test_channel',
channel_type=ChannelType.EMAIL
channel_type=ChannelType.EMAIL,
action_links=[],
tracker_image_sources=[],
)
patch_channels(self, [mock_channel])
channel_map = ChannelMap([
['sailthru', mock_channel],
])
sent_messages = []
with self.settings(TEMPLATES=self._get_template_overrides()):
@@ -411,8 +416,9 @@ class ScheduleSendEmailTestMixin(FilteredQueryCountMixin):
with self.assertNumQueries(NUM_QUERIES_PER_MESSAGE_DELIVERY):
with patch('analytics.track') as mock_analytics_track:
self.deliver_task(*sent_messages[0])
self.assertEqual(mock_analytics_track.call_count, 1)
with patch('edx_ace.channel.channels', return_value=channel_map):
self.deliver_task(*sent_messages[0])
self.assertEqual(mock_analytics_track.call_count, 1)
self.assertEqual(mock_channel.deliver.call_count, 1)
for (_name, (_msg, email), _kwargs) in mock_channel.deliver.mock_calls:

View File

@@ -11,6 +11,7 @@ from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings
from django.core.validators import validate_email, ValidationError
from django.http import HttpResponseForbidden
from openedx.core.djangoapps.theming.helpers import get_current_request
from six import text_type
from student.models import User, UserProfile, Registration, email_exists_or_retired
@@ -432,7 +433,8 @@ def request_password_change(email, is_secure):
# and email it to the user.
form.save(
from_email=configuration_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL),
use_https=is_secure
use_https=is_secure,
request=get_current_request(),
)
else:
# No user with the provided email address exists.

View File

@@ -19,6 +19,7 @@ from nose.plugins.attrib import attr
from nose.tools import raises
from six import iteritems
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
from openedx.core.djangoapps.user_api.accounts import PRIVATE_VISIBILITY, USERNAME_MAX_LENGTH
from openedx.core.djangoapps.user_api.accounts.api import (
activate_account,
@@ -431,8 +432,13 @@ class AccountCreationActivationAndPasswordChangeTest(TestCase):
activation_key = create_account(self.USERNAME, self.PASSWORD, self.EMAIL)
activate_account(activation_key)
# Request a password change
request_password_change(self.EMAIL, self.IS_SECURE)
request = RequestFactory().post('/password')
request.user = Mock()
request.site = SiteFactory()
with patch('crum.get_current_request', return_value=request):
# Request a password change
request_password_change(self.EMAIL, self.IS_SECURE)
# Verify that one email message has been sent
self.assertEqual(len(mail.outbox), 1)
@@ -456,7 +462,12 @@ class AccountCreationActivationAndPasswordChangeTest(TestCase):
# Create an account, but do not activate it
create_account(self.USERNAME, self.PASSWORD, self.EMAIL)
request_password_change(self.EMAIL, self.IS_SECURE)
request = RequestFactory().post('/password')
request.user = Mock()
request.site = SiteFactory()
with patch('crum.get_current_request', return_value=request):
request_password_change(self.EMAIL, self.IS_SECURE)
# Verify that the activation email was still sent
self.assertEqual(len(mail.outbox), 1)