diff --git a/static/js/settings_notifications.js b/static/js/settings_notifications.js index c108c4a507..0d0f5b6445 100644 --- a/static/js/settings_notifications.js +++ b/static/js/settings_notifications.js @@ -20,6 +20,7 @@ var pm_mention_notification_settings = [ var other_notification_settings = [ "enable_digest_emails", "realm_name_in_notifications", + "message_content_in_email_notifications", ]; exports.notification_settings = other_notification_settings.concat( diff --git a/static/templates/settings/notification-settings.handlebars b/static/templates/settings/notification-settings.handlebars index b0b2336d8f..eadb987277 100644 --- a/static/templates/settings/notification-settings.handlebars +++ b/static/templates/settings/notification-settings.handlebars @@ -154,7 +154,20 @@ {{t "Send digest emails when I'm away" }} - +
Click here to log in to Zulip and view your new messages. diff --git a/templates/zerver/emails/missed_message.subject b/templates/zerver/emails/missed_message.subject index a9800fde9b..92c669b48a 100644 --- a/templates/zerver/emails/missed_message.subject +++ b/templates/zerver/emails/missed_message.subject @@ -1,7 +1,10 @@ -{% if group_pm %} Group PMs with {{ huddle_display_name }} -{% elif at_mention %} {{ sender_str }} mentioned you -{% elif private_message %} {{ sender_str }} sent you a message +{% if show_message_content %} + {% if group_pm %} Group PMs with {{ huddle_display_name }} + {% elif at_mention %} {{ sender_str }} mentioned you + {% elif private_message %} {{ sender_str }} sent you a message + {% endif %} +{% else %} + New missed message{{ message_count|pluralize }} {% endif %} -{% if realm_name_in_notifications %} - in {{ realm_str }} +{% if realm_name_in_notifications %} in {{ realm_str }} {% endif %} diff --git a/templates/zerver/emails/missed_message.txt b/templates/zerver/emails/missed_message.txt index 139edc559e..32e3f63aed 100644 --- a/templates/zerver/emails/missed_message.txt +++ b/templates/zerver/emails/missed_message.txt @@ -2,16 +2,16 @@ Hello {{ name }}, While you were away you received {{ message_count }} new message{{ messages|pluralize }}{% if mention %} in which you were mentioned{% endif %}! - +{% if show_message_content %} {% for recipient_block in messages %} {{ recipient_block.header.plain }} {% for sender_block in recipient_block.senders %} {% if sender_block.sender %}{{ sender_block.sender }}{% endif %}{% for message_block in sender_block.content %} - {{ message_block.plain }} + {{ message_block.plain }} {% endfor %} {% endfor %} {% endfor %} - +{% endif %} Click here to log in to Zulip and view your new messages: diff --git a/zerver/lib/notifications.py b/zerver/lib/notifications.py index e576a0e46b..1e50f59611 100644 --- a/zerver/lib/notifications.py +++ b/zerver/lib/notifications.py @@ -304,6 +304,7 @@ def do_send_missedmessage_events_reply_in_zulip(user_profile: UserProfile, 'mention': missed_messages[0].is_stream_message(), 'unsubscribe_link': unsubscribe_link, 'realm_name_in_notifications': user_profile.realm_name_in_notifications, + 'show_message_content': user_profile.message_content_in_email_notifications, }) # If this setting (email mirroring integration) is enabled, only then @@ -320,6 +321,12 @@ def do_send_missedmessage_events_reply_in_zulip(user_profile: UserProfile, 'reply_to_zulip': False, }) + # If there is no content in message, it's not clear what user would be replying to. + if not user_profile.message_content_in_email_notifications: + context.update({ + 'reply_to_zulip': False, + }) + from zerver.lib.email_mirror import create_missed_message_address reply_to_address = create_missed_message_address(user_profile, missed_messages[0]) if reply_to_address == FromAddress.NOREPLY: diff --git a/zerver/migrations/0146_userprofile_message_content_in_email_notifications.py b/zerver/migrations/0146_userprofile_message_content_in_email_notifications.py new file mode 100644 index 0000000000..1c8a733155 --- /dev/null +++ b/zerver/migrations/0146_userprofile_message_content_in_email_notifications.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.6 on 2017-11-29 12:33 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('zerver', '0145_reactions_realm_emoji_name_to_id'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='message_content_in_email_notifications', + field=models.BooleanField(default=True), + ), + ] diff --git a/zerver/models.py b/zerver/models.py index 89dedbe272..0331778fcd 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -572,6 +572,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin): pm_content_in_desktop_notifications = models.BooleanField(default=True) # type: bool enable_sounds = models.BooleanField(default=True) # type: bool enable_offline_email_notifications = models.BooleanField(default=True) # type: bool + message_content_in_email_notifications = models.BooleanField(default=True) # type: bool enable_offline_push_notifications = models.BooleanField(default=True) # type: bool enable_online_push_notifications = models.BooleanField(default=False) # type: bool @@ -678,6 +679,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin): enable_stream_email_notifications=bool, enable_stream_push_notifications=bool, enable_stream_sounds=bool, + message_content_in_email_notifications=bool, pm_content_in_desktop_notifications=bool, realm_name_in_notifications=bool, ) diff --git a/zerver/tests/test_home.py b/zerver/tests/test_home.py index 0be4ff6d66..f29f3ce5eb 100644 --- a/zerver/tests/test_home.py +++ b/zerver/tests/test_home.py @@ -89,6 +89,7 @@ class HomeTest(ZulipTestCase): "max_icon_file_size", "max_message_id", "maxfilesize", + "message_content_in_email_notifications", "muted_topics", "narrow", "narrow_stream", diff --git a/zerver/tests/test_notifications.py b/zerver/tests/test_notifications.py index c4ce4a50a5..dbbbaed04b 100644 --- a/zerver/tests/test_notifications.py +++ b/zerver/tests/test_notifications.py @@ -14,7 +14,8 @@ from typing import Any, Dict, List, Text from zerver.lib.notifications import fix_emojis, \ handle_missedmessage_emails, relative_to_full_url -from zerver.lib.actions import do_update_message +from zerver.lib.actions import do_update_message, \ + do_change_notification_settings from zerver.lib.message import access_message from zerver.lib.test_classes import ZulipTestCase from zerver.lib.send_email import FromAddress @@ -36,7 +37,9 @@ class TestMissedMessages(ZulipTestCase): return [str(random.getrandbits(32)) for _ in range(30)] def _test_cases(self, tokens: List[str], msg_id: int, body: str, subject: str, - send_as_user: bool, verify_html_body: bool=False) -> None: + send_as_user: bool, verify_html_body: bool=False, + show_message_content: bool=True, + verify_body_does_not_include: List[str]=None) -> None: othello = self.example_user('othello') hamlet = self.example_user('hamlet') handle_missedmessage_emails(hamlet.id, [{'message_id': msg_id}]) @@ -58,6 +61,9 @@ class TestMissedMessages(ZulipTestCase): self.assertIn(body, self.normalize_string(msg.alternatives[0][0])) else: self.assertIn(body, self.normalize_string(msg.body)) + if verify_body_does_not_include is not None: + for text in verify_body_does_not_include: + self.assertNotIn(text, self.normalize_string(msg.body)) @patch('zerver.lib.email_mirror.generate_random_token') def _realm_name_in_missed_message_email_subject(self, @@ -80,7 +86,8 @@ class TestMissedMessages(ZulipTestCase): @patch('zerver.lib.email_mirror.generate_random_token') def _extra_context_in_missed_stream_messages_mention(self, send_as_user: bool, - mock_random_token: MagicMock) -> None: + mock_random_token: MagicMock, + show_message_content: bool=True) -> None: tokens = self._get_tokens() mock_random_token.side_effect = tokens @@ -92,9 +99,21 @@ class TestMissedMessages(ZulipTestCase): msg_id = self.send_stream_message( self.example_email('othello'), "denmark", '@**King Hamlet**') - body = 'Denmark > test Othello, the Moor of Venice 1 2 3 4 5 6 7 8 9 10 @**King Hamlet**' - subject = 'Othello, the Moor of Venice mentioned you' - self._test_cases(tokens, msg_id, body, subject, send_as_user) + + if show_message_content: + body = 'Denmark > test Othello, the Moor of Venice 1 2 3 4 5 6 7 8 9 10 @**King Hamlet**' + subject = 'Othello, the Moor of Venice mentioned you' + verify_body_does_not_include = [] + else: + # Test in case if message content in missed email message are disabled. + body = 'While you were away you received 1 new message in which you were mentioned!' + subject = 'New missed message' + verify_body_does_not_include = ['Denmark > test', 'Othello, the Moor of Venice', + '1 2 3 4 5 6 7 8 9 10 @**King Hamlet**', 'private', 'group', + 'Or just reply to this email.'] + self._test_cases(tokens, msg_id, body, subject, send_as_user, + show_message_content=show_message_content, + verify_body_does_not_include=verify_body_does_not_include) @patch('zerver.lib.email_mirror.generate_random_token') def _extra_context_in_missed_stream_messages_mention_two_senders( @@ -113,7 +132,8 @@ class TestMissedMessages(ZulipTestCase): @patch('zerver.lib.email_mirror.generate_random_token') def _extra_context_in_personal_missed_stream_messages(self, send_as_user: bool, - mock_random_token: MagicMock) -> None: + mock_random_token: MagicMock, + show_message_content: bool=True) -> None: tokens = self._get_tokens() mock_random_token.side_effect = tokens @@ -122,9 +142,19 @@ class TestMissedMessages(ZulipTestCase): self.example_email('hamlet'), 'Extremely personal message!', ) - body = 'You and Othello, the Moor of Venice Extremely personal message!' - subject = 'Othello, the Moor of Venice sent you a message' - self._test_cases(tokens, msg_id, body, subject, send_as_user) + + if show_message_content: + body = 'You and Othello, the Moor of Venice Extremely personal message!' + subject = 'Othello, the Moor of Venice sent you a message' + verify_body_does_not_include = [] + else: + body = 'While you were away you received 1 new message!' + subject = 'New missed message' + verify_body_does_not_include = ['Othello, the Moor of Venice', 'Extremely personal message!', + 'mentioned', 'group', 'Or just reply to this email.'] + self._test_cases(tokens, msg_id, body, subject, send_as_user, + show_message_content=show_message_content, + verify_body_does_not_include=verify_body_does_not_include) @patch('zerver.lib.email_mirror.generate_random_token') def _reply_to_email_in_personal_missed_stream_messages(self, send_as_user: bool, @@ -158,7 +188,8 @@ class TestMissedMessages(ZulipTestCase): @patch('zerver.lib.email_mirror.generate_random_token') def _extra_context_in_huddle_missed_stream_messages_two_others(self, send_as_user: bool, - mock_random_token: MagicMock) -> None: + mock_random_token: MagicMock, + show_message_content: bool=True) -> None: tokens = self._get_tokens() mock_random_token.side_effect = tokens @@ -171,10 +202,20 @@ class TestMissedMessages(ZulipTestCase): 'Group personal message!', ) - body = ('You and Iago, Othello, the Moor of Venice Othello,' - ' the Moor of Venice Group personal message') - subject = 'Group PMs with Iago and Othello, the Moor of Venice' - self._test_cases(tokens, msg_id, body, subject, send_as_user) + if show_message_content: + body = ('You and Iago, Othello, the Moor of Venice Othello,' + ' the Moor of Venice Group personal message') + subject = 'Group PMs with Iago and Othello, the Moor of Venice' + verify_body_does_not_include = [] + else: + body = 'While you were away you received 1 new message!' + subject = 'New missed message' + verify_body_does_not_include = ['Iago', 'Othello, the Moor of Venice Othello, the Moor of Venice', + 'Group personal message!', 'private', 'mentioned', + 'Or just reply to this email.'] + self._test_cases(tokens, msg_id, body, subject, send_as_user, + show_message_content=show_message_content, + verify_body_does_not_include=verify_body_does_not_include) @patch('zerver.lib.email_mirror.generate_random_token') def _extra_context_in_huddle_missed_stream_messages_three_others(self, send_as_user: bool, @@ -293,6 +334,16 @@ class TestMissedMessages(ZulipTestCase): mail.outbox = [] self._realm_name_in_missed_message_email_subject(True) + def test_message_content_disabled_in_missed_message_notifications(self) -> None: + # Test when user disabled message content in email notifications. + do_change_notification_settings(self.example_user("hamlet"), + "message_content_in_email_notifications", False) + self._extra_context_in_missed_stream_messages_mention(False, show_message_content=False) + mail.outbox = [] + self._extra_context_in_personal_missed_stream_messages(False, show_message_content=False) + mail.outbox = [] + self._extra_context_in_huddle_missed_stream_messages_two_others(False, show_message_content=False) + @override_settings(SEND_MISSED_MESSAGE_EMAILS_AS_USER=True) def test_extra_context_in_missed_stream_messages_as_user(self) -> None: self._extra_context_in_missed_stream_messages_mention(True) diff --git a/zerver/views/user_settings.py b/zerver/views/user_settings.py index 2427a13563..19c4e186ff 100644 --- a/zerver/views/user_settings.py +++ b/zerver/views/user_settings.py @@ -170,9 +170,10 @@ def json_change_notify_settings( enable_offline_push_notifications: Optional[bool]=REQ(validator=check_bool, default=None), enable_online_push_notifications: Optional[bool]=REQ(validator=check_bool, default=None), enable_digest_emails: Optional[bool]=REQ(validator=check_bool, default=None), + message_content_in_email_notifications: Optional[bool]=REQ(validator=check_bool, default=None), pm_content_in_desktop_notifications: Optional[bool]=REQ(validator=check_bool, default=None), - realm_name_in_notifications: Optional[bool]=REQ(validator=check_bool, default=None)) \ - -> HttpResponse: + realm_name_in_notifications: Optional[bool]=REQ(validator=check_bool, default=None) +) -> HttpResponse: result = {} # Stream notification settings.