Refactor email sending logic to use a group for QA email recipients (#21791)
* Refactor email sending logic to use a group for QA email recipients * Add migration creating force send mail group
This commit is contained in:
Родитель
8bcad61549
Коммит
ceb064f3e9
|
@ -0,0 +1,29 @@
|
|||
from django.db import migrations
|
||||
|
||||
from olympia.amo.mail import DevEmailBackend
|
||||
|
||||
def create_group(apps, schema_editor):
|
||||
Group = apps.get_model('access', 'Group')
|
||||
|
||||
Group.objects.create(
|
||||
name=DevEmailBackend.force_send_mail_group,
|
||||
notes=(
|
||||
'UserProfiles belonging to this group will have real emails sent'
|
||||
' to them in dev/stage environments. This is useful for testing email flows.'
|
||||
)
|
||||
)
|
||||
|
||||
def delete_group(apps, schema_editor):
|
||||
Group = apps.get_model('access', 'Group')
|
||||
|
||||
Group.objects.filter(name=DevEmailBackend.force_send_mail_group).delete()
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('access', '0002_give_api_bypass_throttling_permission'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(create_group, delete_group)
|
||||
]
|
|
@ -1,9 +1,9 @@
|
|||
from django.conf import settings
|
||||
from django.core import mail
|
||||
from django.core.mail.backends.base import BaseEmailBackend
|
||||
|
||||
import olympia.core.logger
|
||||
from olympia.amo.models import FakeEmail
|
||||
from olympia.users.models import UserProfile
|
||||
|
||||
|
||||
log = olympia.core.logger.getLogger('z.amo.mail')
|
||||
|
@ -17,21 +17,26 @@ class DevEmailBackend(BaseEmailBackend):
|
|||
`settings.SEND_REAL_EMAIL` is disabled.
|
||||
|
||||
BUT even if `settings.SEND_REAL_EMAIL` is disabled, if the targeted
|
||||
email address is in the `settings.EMAIL_QA_ALLOW_LIST` list,
|
||||
the email will be sent.
|
||||
email address is in `dev_email` group users, the email will be sent.
|
||||
"""
|
||||
|
||||
force_send_mail_group = 'Force Send Mail'
|
||||
|
||||
def send_messages(self, messages):
|
||||
"""Save a `FakeEmail` object viewable within the admin.
|
||||
|
||||
If one of the target email addresses is in
|
||||
`settings.EMAIL_QA_ALLOW_LIST`, it send a real email message.
|
||||
group named `Group.force_send_mail_group`, it send a real email message.
|
||||
"""
|
||||
log.info('Sending dev mail messages.')
|
||||
qa_messages = []
|
||||
force_send_emails = UserProfile.objects.filter(
|
||||
groups__name=self.force_send_mail_group
|
||||
).values_list('email', flat=True)
|
||||
|
||||
for msg in messages:
|
||||
FakeEmail.objects.create(message=msg.message().as_string())
|
||||
qa_emails = set(msg.to).intersection(settings.EMAIL_QA_ALLOW_LIST)
|
||||
qa_emails = set(msg.to).intersection(force_send_emails)
|
||||
if qa_emails:
|
||||
if len(msg.to) != len(qa_emails):
|
||||
# We need to replace the recipients with the QA
|
||||
|
|
|
@ -96,6 +96,7 @@ class TestPositiveAutoField(TestCase):
|
|||
assert extra == 'auto_increment'
|
||||
|
||||
def test_unsigned_int_limits(self):
|
||||
self.ClassUsingPositiveAutoField.objects.all().delete()
|
||||
self.ClassUsingPositiveAutoField.objects.create(id=1)
|
||||
mysql_max_signed_int = 2147483647
|
||||
self.ClassUsingPositiveAutoField.objects.create(id=mysql_max_signed_int + 10)
|
||||
|
|
|
@ -8,8 +8,7 @@ from olympia.access.models import Group
|
|||
|
||||
|
||||
def test_admin_group(admin_group):
|
||||
assert Group.objects.count() == 1
|
||||
admin_group = Group.objects.get()
|
||||
admin_group = Group.objects.get(name='Admins')
|
||||
assert admin_group.name == 'Admins'
|
||||
assert admin_group.rules == '*:*'
|
||||
|
||||
|
|
|
@ -9,8 +9,13 @@ from django.utils import translation
|
|||
|
||||
from celery.exceptions import Retry
|
||||
|
||||
from olympia.access.models import Group
|
||||
from olympia.amo.mail import DevEmailBackend
|
||||
from olympia.amo.models import FakeEmail
|
||||
from olympia.amo.tests import TestCase
|
||||
from olympia.amo.tests import (
|
||||
TestCase,
|
||||
user_factory,
|
||||
)
|
||||
from olympia.amo.utils import send_html_mail_jinja, send_mail
|
||||
from olympia.users import notifications
|
||||
from olympia.users.models import UserNotification, UserProfile
|
||||
|
@ -159,11 +164,23 @@ class TestSendMail(TestCase):
|
|||
|
||||
@mock.patch.object(settings, 'EMAIL_DENY_LIST', ())
|
||||
@mock.patch.object(settings, 'SEND_REAL_EMAIL', False)
|
||||
@mock.patch.object(settings, 'EMAIL_QA_ALLOW_LIST', ('nope@mozilla.org',))
|
||||
def test_qa_allowed_list(self):
|
||||
def test_success_fake_mail_missing_group(self):
|
||||
Group.objects.all().delete()
|
||||
assert Group.objects.all().count() == 0
|
||||
|
||||
assert send_mail(
|
||||
'test subject', 'test body', recipient_list=['nope@mozilla.org']
|
||||
'test subject', 'test body', recipient_list=['nobody@mozilla.org']
|
||||
)
|
||||
|
||||
@mock.patch.object(settings, 'EMAIL_DENY_LIST', ())
|
||||
@mock.patch.object(settings, 'SEND_REAL_EMAIL', False)
|
||||
def test_qa_allowed_list(self):
|
||||
nope_user = user_factory()
|
||||
group = Group.objects.create(
|
||||
name=DevEmailBackend.force_send_mail_group, rules='foo'
|
||||
)
|
||||
group.users.set([nope_user])
|
||||
assert send_mail('test subject', 'test body', recipient_list=[nope_user.email])
|
||||
assert len(mail.outbox) == 1
|
||||
assert mail.outbox[0].subject.find('test subject') == 0
|
||||
assert mail.outbox[0].body.find('test body') == 0
|
||||
|
@ -172,15 +189,19 @@ class TestSendMail(TestCase):
|
|||
|
||||
@mock.patch.object(settings, 'EMAIL_DENY_LIST', ())
|
||||
@mock.patch.object(settings, 'SEND_REAL_EMAIL', False)
|
||||
@mock.patch.object(settings, 'EMAIL_QA_ALLOW_LIST', ('nope@mozilla.org',))
|
||||
def test_qa_allowed_list_with_mixed_emails(self):
|
||||
nope_user = user_factory()
|
||||
group = Group.objects.create(
|
||||
name=DevEmailBackend.force_send_mail_group, rules='foo'
|
||||
)
|
||||
group.users.set([nope_user])
|
||||
assert send_mail(
|
||||
'test subject',
|
||||
'test body',
|
||||
recipient_list=['nope@mozilla.org', 'b@example.fr'],
|
||||
recipient_list=[nope_user.email, 'b@example.fr'],
|
||||
)
|
||||
assert len(mail.outbox) == 1
|
||||
assert mail.outbox[0].to == ['nope@mozilla.org']
|
||||
assert mail.outbox[0].to == [nope_user.email]
|
||||
assert FakeEmail.objects.count() == 1
|
||||
|
||||
def test_dont_localize(self):
|
||||
|
|
|
@ -321,7 +321,9 @@ class GenerateAddonsSerializer(serializers.Serializer):
|
|||
# Groups should have been created by loaddata initial.json at this
|
||||
# point, we need our user to be part of a group allowed to submit
|
||||
# extensions signed by Mozilla. Let's use Admins (pk=1) as a shortcut.
|
||||
GroupUser.objects.get_or_create(user=user, group=Group.objects.get(pk=1))
|
||||
GroupUser.objects.get_or_create(
|
||||
user=user, group=Group.objects.get(name='Admins')
|
||||
)
|
||||
|
||||
# generate a proper uploaded file that simulates what django requires
|
||||
# as request.POST
|
||||
|
|
|
@ -7,7 +7,7 @@ from olympia.landfill.serializers import GenerateAddonsSerializer
|
|||
|
||||
class TestGenerateAddonsSerializer(TestCase):
|
||||
def test_create_installable_addon(self):
|
||||
Group.objects.get_or_create(pk=1, defaults={'name': 'Admins', 'rules': '*:*'})
|
||||
Group.objects.create(name='Admins', rules='*:*')
|
||||
AppVersion.objects.create(application=amo.FIREFOX.id, version='42.0')
|
||||
AppVersion.objects.create(application=amo.FIREFOX.id, version='*')
|
||||
AppVersion.objects.create(application=amo.ANDROID.id, version='48.0')
|
||||
|
|
|
@ -752,8 +752,6 @@ DEFAULT_FROM_EMAIL = ADDONS_EMAIL
|
|||
# Email goes to the console by default. s/console/smtp/ for regular delivery
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
|
||||
# Please use all lowercase for the QA allow list.
|
||||
EMAIL_QA_ALLOW_LIST = env.list('EMAIL_QA_ALLOW_LIST', default=())
|
||||
# Please use all lowercase for the deny_list.
|
||||
EMAIL_DENY_LIST = env.list('EMAIL_DENY_LIST', default=('nobody@mozilla.org',))
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче