diff --git a/sendgrid/helpers/mail/mail.py b/sendgrid/helpers/mail/mail.py index ba21f789..2472ad7d 100644 --- a/sendgrid/helpers/mail/mail.py +++ b/sendgrid/helpers/mail/mail.py @@ -60,6 +60,7 @@ def __init__( self._ip_pool_name = None self._mail_settings = None self._reply_to = None + self._reply_to_list = None self._send_at = None self._subject = None self._template_id = None @@ -695,6 +696,32 @@ def reply_to(self, value): value = ReplyTo(value[0], value[1]) self._reply_to = value + @property + def reply_to_list(self): + """A list of ReplyTo email addresses + + :rtype: list(ReplyTo), tuple + """ + return self._reply_to_list + + @reply_to_list.setter + def reply_to_list(self, value): + """A list of ReplyTo email addresses + + :param value: A list of ReplyTo email addresses + :type value: list(ReplyTo), tuple + """ + if isinstance(value, list): + for reply in value: + if isinstance(reply, ReplyTo): + if not isinstance(reply.email, str): + raise ValueError('You must provide an email for each entry in a reply_to_list') + else: + raise ValueError( + 'Please use a list of ReplyTos for a reply_to_list.' + ) + self._reply_to_list = value + @property def contents(self): """The contents of the email @@ -981,6 +1008,7 @@ def get(self): 'mail_settings': self._get_or_none(self.mail_settings), 'tracking_settings': self._get_or_none(self.tracking_settings), 'reply_to': self._get_or_none(self.reply_to), + 'reply_to_list': [r.get() for r in self.reply_to_list or []], } return {key: value for key, value in mail.items() diff --git a/test/unit/test_mail_helpers.py b/test/unit/test_mail_helpers.py index a7d08d89..c00307d4 100644 --- a/test/unit/test_mail_helpers.py +++ b/test/unit/test_mail_helpers.py @@ -235,6 +235,58 @@ def test_send_a_single_email_to_multiple_recipients(self): }''') ) + def test_send_a_single_email_with_multiple_reply_to_addresses(self): + from sendgrid.helpers.mail import (Mail, From, ReplyTo, To, Subject, + PlainTextContent, HtmlContent) + self.maxDiff = None + message = Mail( + from_email=From('test+from@example.com', 'Example From Name'), + to_emails=To('test+to0@example.com', 'Example To Name'), + subject=Subject('Sending with SendGrid is Fun'), + plain_text_content=PlainTextContent('and easy to do anywhere, even with Python'), + html_content=HtmlContent('and easy to do anywhere, even with Python')) + + message.reply_to_list = [ReplyTo(email = 'test+reply_to_1@example.com'), ReplyTo(email = 'test+reply_to_2@example.com')] + + self.assertEqual( + message.get(), + json.loads(r'''{ + "content": [ + { + "type": "text/plain", + "value": "and easy to do anywhere, even with Python" + }, + { + "type": "text/html", + "value": "and easy to do anywhere, even with Python" + } + ], + "from": { + "email": "test+from@example.com", + "name": "Example From Name" + }, + "personalizations": [ + { + "to": [ + { + "email": "test+to0@example.com", + "name": "Example To Name" + } + ] + } + ], + "reply_to_list": [ + { + "email": "test+reply_to_1@example.com" + }, + { + "email": "test+reply_to_2@example.com" + } + ], + "subject": "Sending with SendGrid is Fun" + }''') + ) + def test_multiple_emails_to_multiple_recipients(self): from sendgrid.helpers.mail import (Mail, From, To, Subject, PlainTextContent, HtmlContent, @@ -568,6 +620,44 @@ def test_value_error_is_raised_on_to_emails_set_to_list_of_lists(self): 'and easy to do anywhere, even with Python'), html_content=HtmlContent( 'and easy to do anywhere, even with Python')) + + def test_value_error_is_raised_on_to_emails_set_to_reply_to_list_of_strs(self): + from sendgrid.helpers.mail import (PlainTextContent, HtmlContent) + self.maxDiff = None + to_emails = [ + ('test+to0@example.com', 'Example To Name 0'), + ('test+to1@example.com', 'Example To Name 1') + ] + + mail = Mail( + from_email=From('test+from@example.com', 'Example From Name'), + to_emails=to_emails, + subject=Subject('Sending with SendGrid is Fun'), + plain_text_content=PlainTextContent( + 'and easy to do anywhere, even with Python'), + html_content=HtmlContent( + 'and easy to do anywhere, even with Python')) + with self.assertRaises(ValueError): + mail.reply_to_list = ['test+reply_to0@example.com', 'test+reply_to1@example.com'] + + def test_value_error_is_raised_on_to_emails_set_to_reply_to_list_of_tuples(self): + from sendgrid.helpers.mail import (PlainTextContent, HtmlContent) + self.maxDiff = None + to_emails = [ + ('test+to0@example.com', 'Example To Name 0'), + ('test+to1@example.com', 'Example To Name 1') + ] + + mail = Mail( + from_email=From('test+from@example.com', 'Example From Name'), + to_emails=to_emails, + subject=Subject('Sending with SendGrid is Fun'), + plain_text_content=PlainTextContent( + 'and easy to do anywhere, even with Python'), + html_content=HtmlContent( + 'and easy to do anywhere, even with Python')) + with self.assertRaises(ValueError): + mail.reply_to_list = [('test+reply_to@example.com', 'Test Name')] def test_error_is_not_raised_on_to_emails_set_to_list_of_tuples(self): from sendgrid.helpers.mail import (PlainTextContent, HtmlContent) diff --git a/use_cases/send_a_single_email_with_multiple_reply_to_addresses.md b/use_cases/send_a_single_email_with_multiple_reply_to_addresses.md new file mode 100644 index 00000000..55d6adf1 --- /dev/null +++ b/use_cases/send_a_single_email_with_multiple_reply_to_addresses.md @@ -0,0 +1,29 @@ +```python +import os +from sendgrid import SendGridAPIClient +from sendgrid.helpers.mail import Mail + +message = Mail( + from_email='from_email@example.com', + to_emails='to@example.com', + subject='Sending with Twilio SendGrid is Fun', + html_content='and easy to do anywhere, even with Python') +message.reply_to_list = [ + ReplyTo( + email='reply-to-1@example.com', + name="Reply To Name 1", + ), + ReplyTo( + email='reply-to-2@example.com', + name="Reply To Name 2", + ) +] +try: + sendgrid_client = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY')) + response = sendgrid_client.send(message) + print(response.status_code) + print(response.body) + print(response.headers) +except Exception as e: + print(e) +```