diff --git a/zerver/lib/email_mirror.py b/zerver/lib/email_mirror.py index 5ccb0fd0e4..920f43e487 100644 --- a/zerver/lib/email_mirror.py +++ b/zerver/lib/email_mirror.py @@ -10,6 +10,7 @@ from django.utils.timezone import now as timezone_now from django.utils.timezone import timedelta from zerver.lib.actions import ( + check_send_message, internal_send_huddle_message, internal_send_private_message, internal_send_stream_message, @@ -20,7 +21,7 @@ from zerver.lib.email_mirror_helpers import ( get_email_gateway_message_string_from_address, ) from zerver.lib.email_notifications import convert_html_to_markdown -from zerver.lib.exceptions import RateLimited +from zerver.lib.exceptions import JsonableError, RateLimited from zerver.lib.message import normalize_body, truncate_topic from zerver.lib.queue import queue_json_publish from zerver.lib.rate_limiter import RateLimitedObject @@ -33,6 +34,7 @@ from zerver.models import ( Recipient, Stream, UserProfile, + get_client, get_display_recipient, get_stream_by_id_in_realm, get_system_bot, @@ -210,6 +212,27 @@ def send_zulip(sender: UserProfile, stream: Stream, topic: str, content: str) -> ) +def send_mm_reply_to_stream( + user_profile: UserProfile, stream: Stream, topic: str, body: str +) -> None: + try: + check_send_message( + sender=user_profile, + client=get_client("Internal"), + message_type_name="stream", + message_to=[stream.id], + topic_name=topic, + message_content=body, + ) + except JsonableError as error: + error_message = "Error sending message to stream {stream} via missed messages email reply:\n{error}".format( + stream=stream.name, error=error.msg + ) + internal_send_private_message( + get_system_bot(settings.NOTIFICATION_BOT), user_profile, error_message + ) + + def get_message_part_by_type(message: EmailMessage, content_type: str) -> Optional[str]: charsets = message.get_charsets() @@ -429,12 +452,7 @@ def process_missed_message(to: str, message: EmailMessage) -> None: if recipient.type == Recipient.STREAM: stream = get_stream_by_id_in_realm(recipient.type_id, user_profile.realm) - internal_send_stream_message( - user_profile, - stream, - topic, - body, - ) + send_mm_reply_to_stream(user_profile, stream, topic, body) recipient_str = stream.name elif recipient.type == Recipient.PERSONAL: display_recipient = get_display_recipient(recipient) diff --git a/zerver/tests/test_email_mirror.py b/zerver/tests/test_email_mirror.py index 2e2b790ffc..f97f24ff27 100644 --- a/zerver/tests/test_email_mirror.py +++ b/zerver/tests/test_email_mirror.py @@ -11,7 +11,12 @@ import orjson from django.conf import settings from django.http import HttpResponse -from zerver.lib.actions import do_deactivate_realm, do_deactivate_user, ensure_stream +from zerver.lib.actions import ( + do_change_stream_post_policy, + do_deactivate_realm, + do_deactivate_user, + ensure_stream, +) from zerver.lib.email_mirror import ( ZulipEmailForwardError, create_missed_message_address, @@ -37,6 +42,7 @@ from zerver.lib.test_helpers import mock_queue_publish, most_recent_message, mos from zerver.models import ( MissedMessageEmailAddress, Recipient, + Stream, UserProfile, get_display_recipient, get_realm, @@ -927,6 +933,47 @@ class TestMissedMessageEmailMessages(ZulipTestCase): self.assertEqual(message.recipient.type, Recipient.STREAM) self.assertEqual(message.recipient.id, usermessage.message.recipient.id) + def test_receive_email_response_for_auth_failures(self) -> None: + user_profile = self.example_user("hamlet") + self.subscribe(user_profile, "announce") + self.login("hamlet") + result = self.client_post( + "/json/messages", + { + "type": "stream", + "topic": "test topic", + "content": "test_receive_email_response_for_auth_failures", + "client": "test suite", + "to": "announce", + }, + ) + self.assert_json_success(result) + + stream = get_stream("announce", user_profile.realm) + do_change_stream_post_policy(stream, Stream.STREAM_POST_POLICY_ADMINS) + + usermessage = most_recent_usermessage(user_profile) + + mm_address = create_missed_message_address(user_profile, usermessage.message) + + incoming_valid_message = EmailMessage() + incoming_valid_message.set_content("TestMissedMessageEmailMessages Body") + + incoming_valid_message["Subject"] = "TestMissedMessageEmailMessages Subject" + incoming_valid_message["From"] = user_profile.delivery_email + incoming_valid_message["To"] = mm_address + incoming_valid_message["Reply-to"] = user_profile.delivery_email + + process_message(incoming_valid_message) + + message = most_recent_message(user_profile) + + self.assertEqual( + message.content, + "Error sending message to stream announce via missed messages email reply:\nOnly organization administrators can send to this stream.", + ) + self.assertEqual(message.sender, get_system_bot(settings.NOTIFICATION_BOT)) + def test_missed_stream_message_email_response_tracks_topic_change(self) -> None: self.subscribe(self.example_user("hamlet"), "Denmark") self.subscribe(self.example_user("othello"), "Denmark")