email_mirror: Change default topic name if subject ends up empty.

If the email subject is something like `Fwd:`, it gets stripped to an
empty string, activating the "(no topic)" override. This however leads
to failure if the organization enables the setting forcing every message
to have a topic. Such emails should still go through, so we should just
change the topic value used.
This commit is contained in:
Mateusz Mandera 2024-07-09 01:15:12 +02:00 committed by Tim Abbott
parent 9f67452155
commit 8f461b3c03
3 changed files with 13 additions and 6 deletions

View File

@ -73,6 +73,7 @@ IGNORED_PHRASES = [
r"and", r"and",
r"bot", r"bot",
r"e\.g\.", r"e\.g\.",
r"email",
r"enabled", r"enabled",
r"signups", r"signups",
# Placeholders # Placeholders

View File

@ -409,11 +409,17 @@ def is_forwarded(subject: str) -> bool:
def process_stream_message(to: str, message: EmailMessage) -> None: def process_stream_message(to: str, message: EmailMessage) -> None:
subject_header = message.get("Subject", "") subject_header = message.get("Subject", "")
subject = strip_from_subject(subject_header) or "(no topic)"
subject = strip_from_subject(subject_header)
# We don't want to reject email messages with disallowed characters in the Subject, # We don't want to reject email messages with disallowed characters in the Subject,
# so we just remove them to make it a valid Zulip topic name. # so we just remove them to make it a valid Zulip topic name.
subject = "".join([char for char in subject if is_character_printable(char)]) or "(no topic)" subject = "".join([char for char in subject if is_character_printable(char)])
# If the subject gets stripped to the empty string, we need to set some
# default value for the message topic. We can't use the usual
# "(no topic)" as that value is not permitted if the realm enforces
# that all messages must have a topic.
subject = subject or _("Email with no subject")
stream, options = decode_stream_email_address(to) stream, options = decode_stream_email_address(to)
# Don't remove quotations if message is forwarded, unless otherwise specified: # Don't remove quotations if message is forwarded, unless otherwise specified:

View File

@ -326,7 +326,7 @@ class TestStreamEmailMessagesSuccess(ZulipTestCase):
self.assertEqual(message.content, "TestStreamEmailMessages body") self.assertEqual(message.content, "TestStreamEmailMessages body")
self.assert_message_stream_name(message, stream.name) self.assert_message_stream_name(message, stream.name)
self.assertEqual(message.topic_name(), "(no topic)") self.assertEqual(message.topic_name(), "Email with no subject")
def test_receive_stream_email_messages_subject_with_nonprintable_chars( def test_receive_stream_email_messages_subject_with_nonprintable_chars(
self, self,
@ -358,7 +358,7 @@ class TestStreamEmailMessagesSuccess(ZulipTestCase):
process_message(incoming_valid_message) process_message(incoming_valid_message)
message = most_recent_message(user_profile) message = most_recent_message(user_profile)
self.assertEqual(message.topic_name(), "(no topic)") self.assertEqual(message.topic_name(), "Email with no subject")
def test_receive_private_stream_email_messages_success(self) -> None: def test_receive_private_stream_email_messages_success(self) -> None:
user_profile = self.example_user("hamlet") user_profile = self.example_user("hamlet")
@ -1617,12 +1617,12 @@ class TestStreamEmailMessagesSubjectStripping(ZulipTestCase):
message = most_recent_message(user_profile) message = most_recent_message(user_profile)
self.assertEqual("Test", message.topic_name()) self.assertEqual("Test", message.topic_name())
# If after stripping we get an empty subject, it should get set to (no topic) # If after stripping we get an empty subject, it should get set to Email with no subject
del incoming_valid_message["Subject"] del incoming_valid_message["Subject"]
incoming_valid_message["Subject"] = "Re: Fwd: Re: " incoming_valid_message["Subject"] = "Re: Fwd: Re: "
process_message(incoming_valid_message) process_message(incoming_valid_message)
message = most_recent_message(user_profile) message = most_recent_message(user_profile)
self.assertEqual("(no topic)", message.topic_name()) self.assertEqual("Email with no subject", message.topic_name())
def test_strip_from_subject(self) -> None: def test_strip_from_subject(self) -> None:
subject_list = orjson.loads(self.fixture_data("subjects.json", type="email")) subject_list = orjson.loads(self.fixture_data("subjects.json", type="email"))