mirror of https://github.com/zulip/zulip.git
emails: Make sender name go in-line with message body.
Making sender name go in-line with message body only if the html starts with <p> tag since it won't look good if the message starts with a code snippet, ul, etc. If message starts with p tag we can safely assume that it can go in-line with sender name.
This commit is contained in:
parent
7867830e14
commit
3a6fc09a4d
|
@ -9,7 +9,6 @@
|
||||||
<div class='hot_convo_recipient_header'>{{ recipient_block.header.html|safe }}</div>
|
<div class='hot_convo_recipient_header'>{{ recipient_block.header.html|safe }}</div>
|
||||||
<div class='hot_convo_message_content'>
|
<div class='hot_convo_message_content'>
|
||||||
{% for sender_block in recipient_block.senders %}
|
{% for sender_block in recipient_block.senders %}
|
||||||
{% if sender_block.sender %} <div class="hot_convo_message_sender">{{ sender_block.sender }}</div>{% endif %}
|
|
||||||
{% for message_block in sender_block.content %}
|
{% for message_block in sender_block.content %}
|
||||||
<div class='hot_convo_message_content_block'>
|
<div class='hot_convo_message_content_block'>
|
||||||
{{ message_block.html|safe }}
|
{{ message_block.html|safe }}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
{% if hot_conversations %}
|
{% if hot_conversations %}
|
||||||
{% for convo in hot_conversations %}{% for recipient_block in convo.first_few_messages %}{{ recipient_block.header.plain }}
|
{% for convo in hot_conversations %}{% for recipient_block in convo.first_few_messages %}{{ recipient_block.header.plain }}
|
||||||
{% for sender_block in recipient_block.senders %}{% if sender_block.sender %}{{ sender_block.sender }}
|
{% for sender_block in recipient_block.senders %}
|
||||||
{% endif %}
|
|
||||||
{% for message_block in sender_block.content %}{{ message_block.plain }}
|
{% for message_block in sender_block.content %}{{ message_block.plain }}
|
||||||
{% endfor %}{% endfor %}
|
{% endfor %}{% endfor %}
|
||||||
{% if convo.count > 0 %}+ {{ convo.count }} more message{{ convo.count|pluralize }} by {{ convo.participants|display_list(4) }}.{% endif %}{% endfor %}{% endfor %}{% endif %}
|
{% if convo.count > 0 %}+ {{ convo.count }} more message{{ convo.count|pluralize }} by {{ convo.participants|display_list(4) }}.{% endif %}{% endfor %}{% endfor %}{% endif %}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
{% for recipient_block in messages %}
|
{% for recipient_block in messages %}
|
||||||
{% for sender_block in recipient_block.senders %}
|
{% for sender_block in recipient_block.senders %}
|
||||||
<div class="missed_message">
|
<div class="missed_message">
|
||||||
{% if sender_block.sender %}<div class="missed_message_sender">{{ sender_block.sender }}</div>{% endif %}
|
|
||||||
{% for message_block in sender_block.content %}
|
{% for message_block in sender_block.content %}
|
||||||
{{ message_block.html|safe }}
|
{{ message_block.html|safe }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
{% if show_message_content %}
|
{% if show_message_content %}
|
||||||
{% for recipient_block in messages %}
|
{% for recipient_block in messages %}
|
||||||
{% for sender_block in recipient_block.senders %}
|
{% for sender_block in recipient_block.senders %}
|
||||||
{% if sender_block.sender %}
|
|
||||||
{{ sender_block.sender }}
|
|
||||||
---
|
|
||||||
{% endif %}
|
|
||||||
{% for message_block in sender_block.content %}
|
{% for message_block in sender_block.content %}
|
||||||
{{ message_block.plain }}
|
{{ message_block.plain }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import re
|
||||||
import subprocess
|
import subprocess
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
import pytz
|
import pytz
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
def relative_to_full_url(base_url: str, content: str) -> str:
|
def relative_to_full_url(base_url: str, content: str) -> str:
|
||||||
# Convert relative URLs to absolute URLs.
|
# Convert relative URLs to absolute URLs.
|
||||||
|
@ -138,7 +139,18 @@ def build_message_list(user_profile: UserProfile, messages: List[Message]) -> Li
|
||||||
# with a simple hyperlink.
|
# with a simple hyperlink.
|
||||||
return re.sub(r"\[(\S*)\]\((\S*)\)", r"\2", content)
|
return re.sub(r"\[(\S*)\]\((\S*)\)", r"\2", content)
|
||||||
|
|
||||||
def build_message_payload(message: Message) -> Dict[str, str]:
|
def append_sender_to_message(message_plain: str, message_html: str, sender: str) -> Tuple[str, str]:
|
||||||
|
message_plain = "{}: {}".format(sender, message_plain)
|
||||||
|
message_soup = BeautifulSoup(message_html, "html.parser")
|
||||||
|
sender_name_soup = BeautifulSoup("<b>{}</b>: ".format(sender), "html.parser")
|
||||||
|
first_tag = message_soup.find()
|
||||||
|
if first_tag.name == "p":
|
||||||
|
first_tag.insert(0, sender_name_soup)
|
||||||
|
else:
|
||||||
|
message_soup.insert(0, sender_name_soup)
|
||||||
|
return message_plain, str(message_soup)
|
||||||
|
|
||||||
|
def build_message_payload(message: Message, sender: Optional[str]=None) -> Dict[str, str]:
|
||||||
plain = message.content
|
plain = message.content
|
||||||
plain = fix_plaintext_image_urls(plain)
|
plain = fix_plaintext_image_urls(plain)
|
||||||
# There's a small chance of colliding with non-Zulip URLs containing
|
# There's a small chance of colliding with non-Zulip URLs containing
|
||||||
|
@ -154,13 +166,14 @@ def build_message_list(user_profile: UserProfile, messages: List[Message]) -> Li
|
||||||
html = message.rendered_content
|
html = message.rendered_content
|
||||||
html = relative_to_full_url(user_profile.realm.uri, html)
|
html = relative_to_full_url(user_profile.realm.uri, html)
|
||||||
html = fix_emojis(html, user_profile.realm.uri, user_profile.emojiset)
|
html = fix_emojis(html, user_profile.realm.uri, user_profile.emojiset)
|
||||||
|
if sender:
|
||||||
|
plain, html = append_sender_to_message(plain, html, sender)
|
||||||
return {'plain': plain, 'html': html}
|
return {'plain': plain, 'html': html}
|
||||||
|
|
||||||
def build_sender_payload(message: Message) -> Dict[str, Any]:
|
def build_sender_payload(message: Message) -> Dict[str, Any]:
|
||||||
sender = sender_string(message)
|
sender = sender_string(message)
|
||||||
return {'sender': sender,
|
return {'sender': sender,
|
||||||
'content': [build_message_payload(message)]}
|
'content': [build_message_payload(message, sender)]}
|
||||||
|
|
||||||
def message_header(user_profile: UserProfile, message: Message) -> Dict[str, Any]:
|
def message_header(user_profile: UserProfile, message: Message) -> Dict[str, Any]:
|
||||||
if message.recipient.type == Recipient.PERSONAL:
|
if message.recipient.type == Recipient.PERSONAL:
|
||||||
|
|
|
@ -241,7 +241,7 @@ class TestMissedMessages(ZulipTestCase):
|
||||||
'@**King Hamlet**')
|
'@**King Hamlet**')
|
||||||
|
|
||||||
if show_message_content:
|
if show_message_content:
|
||||||
body = ("Othello, the Moor of Venice --- 1 2 3 4 5 6 7 8 9 10 @**King Hamlet** "
|
body = ("Othello, the Moor of Venice: 1 2 3 4 5 6 7 8 9 10 @**King Hamlet** "
|
||||||
"You are receiving this email because you were mentioned")
|
"You are receiving this email because you were mentioned")
|
||||||
email_subject = '#Denmark > test'
|
email_subject = '#Denmark > test'
|
||||||
verify_body_does_not_include = [] # type: List[str]
|
verify_body_does_not_include = [] # type: List[str]
|
||||||
|
@ -271,7 +271,7 @@ class TestMissedMessages(ZulipTestCase):
|
||||||
msg_id = self.send_stream_message(
|
msg_id = self.send_stream_message(
|
||||||
self.example_email('othello'), "denmark",
|
self.example_email('othello'), "denmark",
|
||||||
'12')
|
'12')
|
||||||
body = ("Othello, the Moor of Venice --- 1 2 3 4 5 6 7 8 9 10 12 "
|
body = ("Othello, the Moor of Venice: 1 2 3 4 5 6 7 8 9 10 12 "
|
||||||
"You are receiving this email "
|
"You are receiving this email "
|
||||||
"because you have email notifications enabled for this stream.")
|
"because you have email notifications enabled for this stream.")
|
||||||
email_subject = '#Denmark > test'
|
email_subject = '#Denmark > test'
|
||||||
|
@ -288,7 +288,7 @@ class TestMissedMessages(ZulipTestCase):
|
||||||
msg_id = self.send_stream_message(
|
msg_id = self.send_stream_message(
|
||||||
self.example_email('othello'), "Denmark",
|
self.example_email('othello'), "Denmark",
|
||||||
'@**King Hamlet**')
|
'@**King Hamlet**')
|
||||||
body = ("Cordelia Lear --- 0 1 2 Othello, the Moor of Venice --- @**King Hamlet** "
|
body = ("Cordelia Lear: 0 1 2 Othello, the Moor of Venice: @**King Hamlet** "
|
||||||
"You are receiving this email because you were mentioned")
|
"You are receiving this email because you were mentioned")
|
||||||
email_subject = '#Denmark > test'
|
email_subject = '#Denmark > test'
|
||||||
self._test_cases(tokens, msg_id, body, email_subject, send_as_user, trigger='mentioned')
|
self._test_cases(tokens, msg_id, body, email_subject, send_as_user, trigger='mentioned')
|
||||||
|
@ -366,7 +366,7 @@ class TestMissedMessages(ZulipTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
if show_message_content:
|
if show_message_content:
|
||||||
body = 'Othello, the Moor of Venice --- Group personal message! Manage email preferences:'
|
body = 'Othello, the Moor of Venice: Group personal message! Manage email preferences:'
|
||||||
email_subject = 'Group PMs with Iago and Othello, the Moor of Venice'
|
email_subject = 'Group PMs with Iago and Othello, the Moor of Venice'
|
||||||
verify_body_does_not_include = [] # type: List[str]
|
verify_body_does_not_include = [] # type: List[str]
|
||||||
else:
|
else:
|
||||||
|
@ -395,7 +395,7 @@ class TestMissedMessages(ZulipTestCase):
|
||||||
'Group personal message!',
|
'Group personal message!',
|
||||||
)
|
)
|
||||||
|
|
||||||
body = 'Othello, the Moor of Venice --- Group personal message! Manage email preferences'
|
body = 'Othello, the Moor of Venice: Group personal message! Manage email preferences'
|
||||||
email_subject = 'Group PMs with Cordelia Lear, Iago, and Othello, the Moor of Venice'
|
email_subject = 'Group PMs with Cordelia Lear, Iago, and Othello, the Moor of Venice'
|
||||||
self._test_cases(tokens, msg_id, body, email_subject, send_as_user)
|
self._test_cases(tokens, msg_id, body, email_subject, send_as_user)
|
||||||
|
|
||||||
|
@ -412,7 +412,7 @@ class TestMissedMessages(ZulipTestCase):
|
||||||
self.example_email('prospero')],
|
self.example_email('prospero')],
|
||||||
'Group personal message!')
|
'Group personal message!')
|
||||||
|
|
||||||
body = 'Othello, the Moor of Venice --- Group personal message! Manage email preferences'
|
body = 'Othello, the Moor of Venice: Group personal message! Manage email preferences'
|
||||||
email_subject = 'Group PMs with Cordelia Lear, Iago, and 2 others'
|
email_subject = 'Group PMs with Cordelia Lear, Iago, and 2 others'
|
||||||
self._test_cases(tokens, msg_id, body, email_subject, send_as_user)
|
self._test_cases(tokens, msg_id, body, email_subject, send_as_user)
|
||||||
|
|
||||||
|
@ -658,6 +658,42 @@ class TestMissedMessages(ZulipTestCase):
|
||||||
email_subject = 'PMs with Othello, the Moor of Venice'
|
email_subject = 'PMs with Othello, the Moor of Venice'
|
||||||
self._test_cases(tokens, msg_id, body, email_subject, send_as_user=False, verify_html_body=True)
|
self._test_cases(tokens, msg_id, body, email_subject, send_as_user=False, verify_html_body=True)
|
||||||
|
|
||||||
|
@patch('zerver.lib.email_mirror.generate_random_token')
|
||||||
|
def test_sender_name_in_missed_message(self, mock_random_token: MagicMock) -> None:
|
||||||
|
tokens = self._get_tokens()
|
||||||
|
mock_random_token.side_effect = tokens
|
||||||
|
|
||||||
|
hamlet = self.example_user('hamlet')
|
||||||
|
msg_id_1 = self.send_stream_message(self.example_email('iago'),
|
||||||
|
"Denmark",
|
||||||
|
'@**King Hamlet**')
|
||||||
|
msg_id_2 = self.send_stream_message(self.example_email('iago'),
|
||||||
|
"Verona",
|
||||||
|
'* 1\n *2')
|
||||||
|
msg_id_3 = self.send_personal_message(self.example_email('iago'),
|
||||||
|
hamlet.email,
|
||||||
|
'Hello')
|
||||||
|
|
||||||
|
handle_missedmessage_emails(hamlet.id, [
|
||||||
|
{'message_id': msg_id_1, "trigger": "mentioned"},
|
||||||
|
{'message_id': msg_id_2, "trigger": "stream_email_notify"},
|
||||||
|
{'message_id': msg_id_3},
|
||||||
|
])
|
||||||
|
|
||||||
|
self.assertIn('Iago: @**King Hamlet**\n\nYou are', mail.outbox[0].body)
|
||||||
|
# If message content starts with <p> tag the sender name is appended inside the <p> tag.
|
||||||
|
self.assertIn('<p><b>Iago</b>: <span class="user-mention"', mail.outbox[0].alternatives[0][0])
|
||||||
|
|
||||||
|
self.assertIn('Iago: * 1\n *2\n\nYou are receiving', mail.outbox[1].body)
|
||||||
|
# If message content does not starts with <p> tag sender name is appended before the <p> tag
|
||||||
|
self.assertIn(' <b>Iago</b>: <ul>\n<li>1<br/>\n *2</li>\n</ul>\n',
|
||||||
|
mail.outbox[1].alternatives[0][0])
|
||||||
|
|
||||||
|
self.assertEqual('Hello\n\n\nManage email preferences:', mail.outbox[2].body[:33])
|
||||||
|
# Sender name is not appended to message for PM missed messages
|
||||||
|
self.assertIn('>\n \n <p>Hello</p>\n',
|
||||||
|
mail.outbox[2].alternatives[0][0])
|
||||||
|
|
||||||
@patch('zerver.lib.email_mirror.generate_random_token')
|
@patch('zerver.lib.email_mirror.generate_random_token')
|
||||||
def test_multiple_missed_personal_messages(self, mock_random_token: MagicMock) -> None:
|
def test_multiple_missed_personal_messages(self, mock_random_token: MagicMock) -> None:
|
||||||
tokens = self._get_tokens()
|
tokens = self._get_tokens()
|
||||||
|
|
Loading…
Reference in New Issue