email_mirror: Fix exception handling unstructured headers.

This commit rewrites the way addresses are collected. If
the header with the address is not an AddressHeader (for instance,
Delivered-To and Envelope-To), we take its string representation.

Fixes: #15864 ("Error in email_mirror - _UnstructuredHeader has no attribute addresses").
This commit is contained in:
Emilio López 2020-07-22 16:11:25 -03:00 committed by GitHub
parent a8bef38151
commit 7b35234c7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 3 deletions

View File

@ -1,5 +1,6 @@
import logging import logging
import re import re
from email.headerregistry import AddressHeader
from email.message import EmailMessage from email.message import EmailMessage
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
@ -310,9 +311,14 @@ def find_emailgateway_recipient(message: EmailMessage) -> str:
for header_name in recipient_headers: for header_name in recipient_headers:
for header_value in message.get_all(header_name, []): for header_value in message.get_all(header_name, []):
for addr in header_value.addresses: if isinstance(header_value, AddressHeader):
if match_email_re.match(addr.addr_spec): emails = [addr.addr_spec for addr in header_value.addresses]
return addr.addr_spec else:
emails = [str(header_value)]
for email in emails:
if match_email_re.match(email):
return email
raise ZulipEmailForwardError("Missing recipient in mirror email") raise ZulipEmailForwardError("Missing recipient in mirror email")

View File

@ -232,6 +232,36 @@ class TestStreamEmailMessagesSuccess(ZulipTestCase):
self.assertEqual(get_display_recipient(message.recipient), stream.name) self.assertEqual(get_display_recipient(message.recipient), stream.name)
self.assertEqual(message.topic_name(), incoming_valid_message['Subject']) self.assertEqual(message.topic_name(), incoming_valid_message['Subject'])
# Test receiving an email with the address on an UnstructuredHeader
# (e.g. Envelope-To) instead of an AddressHeader (e.g. To).
# https://github.com/zulip/zulip/issues/15864
def test_receive_stream_email_messages_other_header_success(self) -> None:
user_profile = self.example_user('hamlet')
self.login_user(user_profile)
self.subscribe(user_profile, "Denmark")
stream = get_stream("Denmark", user_profile.realm)
stream_to_address = encode_email_address(stream)
incoming_valid_message = EmailMessage()
incoming_valid_message.set_content('TestStreamEmailMessages Body')
incoming_valid_message['Subject'] = 'TestStreamEmailMessages Subject'
incoming_valid_message['From'] = self.example_email('hamlet')
# Simulate a mailing list
incoming_valid_message['To'] = "foo-mailinglist@example.com"
incoming_valid_message['Envelope-To'] = stream_to_address
incoming_valid_message['Reply-to'] = self.example_email('othello')
process_message(incoming_valid_message)
# Hamlet is subscribed to this stream so should see the email message from Othello.
message = most_recent_message(user_profile)
self.assertEqual(message.content, "TestStreamEmailMessages Body")
self.assertEqual(get_display_recipient(message.recipient), stream.name)
self.assertEqual(message.topic_name(), incoming_valid_message['Subject'])
def test_receive_stream_email_messages_blank_subject_success(self) -> None: def test_receive_stream_email_messages_blank_subject_success(self) -> None:
user_profile = self.example_user('hamlet') user_profile = self.example_user('hamlet')
self.login_user(user_profile) self.login_user(user_profile)