email: Convert send_email to use formataddr.

Changed the requirements for UserProfile in order to allow use of
the formataddr function in send_mail.py.

Converted send_email to use formataddr in conjunction with the commit
that strengthened requirements for full_name, such that they can now be
used in the to field of emails.

Fixes #4676.
This commit is contained in:
Conner Bondurant
2019-06-28 22:41:13 -04:00
committed by Tim Abbott
parent c25dcf048d
commit 4d4b6b8319
3 changed files with 8 additions and 5 deletions

View File

@@ -43,9 +43,7 @@ def build_email(template_prefix: str, to_user_ids: Optional[List[int]]=None,
assert (to_user_ids is None) ^ (to_emails is None) assert (to_user_ids is None) ^ (to_emails is None)
if to_user_ids is not None: if to_user_ids is not None:
to_users = [get_user_profile_by_id(to_user_id) for to_user_id in to_user_ids] to_users = [get_user_profile_by_id(to_user_id) for to_user_id in to_user_ids]
# Change to formataddr((to_user.full_name, to_user.email)) once to_emails = [formataddr((to_user.full_name, to_user.delivery_email)) for to_user in to_users]
# https://github.com/zulip/zulip/issues/4676 is resolved
to_emails = [to_user.delivery_email for to_user in to_users]
if context is None: if context is None:
context = {} context = {}

View File

@@ -1,4 +1,5 @@
from contextlib import contextmanager from contextlib import contextmanager
from email.utils import parseaddr
from typing import (cast, Any, Dict, Iterable, Iterator, List, Optional, from typing import (cast, Any, Dict, Iterable, Iterator, List, Optional,
Tuple, Union, Set) Tuple, Union, Set)
@@ -360,6 +361,7 @@ class ZulipTestCase(TestCase):
""" """
if full_name is None: if full_name is None:
full_name = email.replace("@", "_") full_name = email.replace("@", "_")
payload = { payload = {
'full_name': full_name, 'full_name': full_name,
'password': password, 'password': password,
@@ -383,7 +385,7 @@ class ZulipTestCase(TestCase):
# This is a bit of a crude heuristic, but good enough for most tests. # This is a bit of a crude heuristic, but good enough for most tests.
url_pattern = settings.EXTERNAL_HOST + r"(\S+)>" url_pattern = settings.EXTERNAL_HOST + r"(\S+)>"
for message in reversed(outbox): for message in reversed(outbox):
if email_address in message.to: if email_address in parseaddr(message.to)[1]:
return re.search(url_pattern, message.body).groups()[0] return re.search(url_pattern, message.body).groups()[0]
else: else:
raise AssertionError("Couldn't find a confirmation email.") raise AssertionError("Couldn't find a confirmation email.")

View File

@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from email.utils import parseaddr
from typing import (Any, Dict, Iterable, List, Mapping, from typing import (Any, Dict, Iterable, List, Mapping,
Optional, TypeVar, Union) Optional, TypeVar, Union)
@@ -983,7 +985,8 @@ class ActivateTest(ZulipTestCase):
from django.core.mail import outbox from django.core.mail import outbox
self.assertEqual(len(outbox), 1) self.assertEqual(len(outbox), 1)
for message in outbox: for message in outbox:
self.assertEqual(set([hamlet.delivery_email, iago.delivery_email]), set(message.to)) to_fields = [parseaddr(to_field)[1] for to_field in message.to]
self.assertEqual(set([hamlet.delivery_email, iago.delivery_email]), set(to_fields))
self.assertEqual(ScheduledEmail.objects.count(), 0) self.assertEqual(ScheduledEmail.objects.count(), 0)
class RecipientInfoTest(ZulipTestCase): class RecipientInfoTest(ZulipTestCase):