notifications: Refactor missed message queue to use send_email.

This commit also changes the sender from "Zulip <NOREPLY_EMAIL_ADDRESS>" to
NOREPLY_EMAIL_ADDRESS when it is not set explicitly.
This commit is contained in:
Rishi Gupta 2017-05-04 16:31:07 -07:00 committed by Tim Abbott
parent fda65b3b37
commit 8321bd3f92
5 changed files with 26 additions and 39 deletions

View File

@ -0,0 +1 @@
Missed Zulips from {{ sender_str }}

View File

@ -4,11 +4,11 @@ from typing import cast, Any, Dict, Iterable, List, Mapping, Optional, Sequence,
from confirmation.models import Confirmation
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.template import loader
from django.utils.timezone import now as timezone_now
from zerver.decorator import statsd_increment
from zerver.lib.send_email import send_future_email
from zerver.lib.send_email import send_future_email, display_email, \
send_email_from_dict
from zerver.lib.queue import queue_json_publish
from zerver.models import (
Recipient,
@ -271,23 +271,22 @@ def do_send_missedmessage_events_reply_in_zulip(user_profile, missed_messages, m
'reply_to_zulip': False,
})
headers = {}
from zerver.lib.email_mirror import create_missed_message_address
address = create_missed_message_address(user_profile, missed_messages[0])
headers['Reply-To'] = address
senders = set(m.sender.full_name for m in missed_messages)
sender_str = ", ".join(senders)
context.update({
'sender_str': sender_str,
})
subject = "Missed Zulips from %s" % (sender_str,)
from_email = 'Zulip <%s>' % (settings.NOREPLY_EMAIL_ADDRESS,)
from_email = None
if len(senders) == 1 and settings.SEND_MISSED_MESSAGE_EMAILS_AS_USER:
# If this setting is enabled, you can reply to the Zulip
# missed message emails directly back to the original sender.
# However, one must ensure the Zulip server is in the SPF
# record for the domain, or there will be spam/deliverability
# problems.
headers['Sender'] = from_email
sender = missed_messages[0].sender
from_email = '"%s" <%s>' % (sender_str, sender.email)
context.update({
@ -295,34 +294,17 @@ def do_send_missedmessage_events_reply_in_zulip(user_profile, missed_messages, m
'reply_to_zulip': False,
})
text_content = loader.render_to_string('zerver/emails/missed_message.txt', context)
html_content = loader.render_to_string('zerver/emails/missed_message.html', context)
email_content = {
'subject': subject,
'text_content': text_content,
'html_content': html_content,
email_dict = {
'template_prefix': 'zerver/emails/missed_message',
'to_email': display_email(user_profile),
'from_email': from_email,
'to': [user_profile.email],
'headers': headers
}
queue_json_publish("missedmessage_email_senders", email_content, send_missedmessage_email)
'reply_to_email': address,
'context': context}
queue_json_publish("missedmessage_email_senders", email_dict, send_email_from_dict)
user_profile.last_reminder = timezone_now()
user_profile.save(update_fields=['last_reminder'])
def send_missedmessage_email(data):
# type: (Mapping[str, Any]) -> None
msg = EmailMultiAlternatives(
data.get('subject'),
data.get('text_content'),
data.get('from_email'),
data.get('to'),
headers=data.get('headers'))
msg.attach_alternative(data.get('html_content'), "text/html")
msg.send()
def handle_missedmessage_emails(user_profile_id, missed_email_events):
# type: (int, Iterable[Dict[str, Any]]) -> None
message_ids = [event.get('message_id') for event in missed_email_events]

View File

@ -8,7 +8,7 @@ import datetime
from email.utils import parseaddr
import ujson
from typing import Any, Dict, Iterable, List, Optional, Text
from typing import Any, Dict, Iterable, List, Mapping, Optional, Text
def display_email(user):
# type: (UserProfile) -> Text
@ -40,6 +40,12 @@ def send_email_to_user(template_prefix, user, from_email=None, context={}):
# type: (str, UserProfile, Optional[Text], Dict[str, Text]) -> bool
return send_email(template_prefix, display_email(user), from_email=from_email, context=context)
# Returns None instead of bool so that the type signature matches the third
# argument of zerver.lib.queue.queue_json_publish
def send_email_from_dict(email_dict):
# type: (Mapping[str, Any]) -> None
send_email(**dict(email_dict))
def send_future_email(template_prefix, to_email, from_email=None, context={},
delay=datetime.timedelta(0)):
# type: (str, Text, Optional[Text], Dict[str, Any], datetime.timedelta) -> None

View File

@ -39,16 +39,14 @@ class TestMissedMessages(ZulipTestCase):
else:
reply_to_addresses = ["noreply@example.com"]
msg = mail.outbox[0]
sender = 'Zulip <{}>'.format(settings.NOREPLY_EMAIL_ADDRESS)
sender = settings.NOREPLY_EMAIL_ADDRESS
from_email = sender
self.assertEqual(len(mail.outbox), 1)
if send_as_user:
from_email = '"%s" <%s>' % (othello.full_name, othello.email)
self.assertEqual(msg.extra_headers['Sender'], sender)
else:
self.assertNotIn("Sender", msg.extra_headers)
self.assertEqual(msg.from_email, from_email)
self.assertIn(msg.extra_headers['Reply-To'], reply_to_addresses)
self.assertEqual(len(msg.reply_to), 1)
self.assertIn(msg.reply_to[0], reply_to_addresses)
self.assertIn(body, self.normalize_string(msg.body))
@patch('zerver.lib.email_mirror.generate_random_token')

View File

@ -14,7 +14,7 @@ from zerver.lib.feedback import handle_feedback
from zerver.lib.queue import SimpleQueueClient, queue_json_publish
from zerver.lib.timestamp import timestamp_to_datetime
from zerver.lib.notifications import handle_missedmessage_emails, enqueue_welcome_emails, \
clear_followup_emails_queue, send_missedmessage_email
clear_followup_emails_queue
from zerver.lib.push_notifications import handle_push_notification
from zerver.lib.actions import do_send_confirmation_email, \
do_update_user_activity, do_update_user_activity_interval, do_update_user_presence, \
@ -22,7 +22,7 @@ from zerver.lib.actions import do_send_confirmation_email, \
render_incoming_message, do_update_embedded_data
from zerver.lib.url_preview import preview as url_preview
from zerver.lib.digest import handle_digest_email
from zerver.lib.send_email import send_future_email
from zerver.lib.send_email import send_future_email, send_email_from_dict
from zerver.lib.email_mirror import process_message as mirror_email
from zerver.decorator import JsonableError
from zerver.tornado.socket import req_redis_key
@ -226,7 +226,7 @@ class MissedMessageWorker(QueueProcessingWorker):
class MissedMessageSendingWorker(QueueProcessingWorker):
def consume(self, data):
# type: (Mapping[str, Any]) -> None
send_missedmessage_email(data)
send_email_from_dict(data)
@assign_queue('missedmessage_mobile_notifications')
class PushNotificationsWorker(QueueProcessingWorker):