From 41147b581ca9f572bd5c61506727cb487dce15de Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 2 Feb 2022 16:16:28 -0800 Subject: [PATCH] Mandrill: don't send unnecessary empty fields Don't add empty Reply-To header and empty display names to Mandrill send API data. Fixes #262 --- anymail/backends/mandrill.py | 10 +++++++--- tests/test_mandrill_backend.py | 29 ++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/anymail/backends/mandrill.py b/anymail/backends/mandrill.py index ec970f3..9a5814c 100644 --- a/anymail/backends/mandrill.py +++ b/anymail/backends/mandrill.py @@ -104,8 +104,11 @@ class MandrillPayload(RequestsPayload): def add_recipient(self, recipient_type, email): assert recipient_type in ["to", "cc", "bcc"] + recipient_data = {"email": email.addr_spec, "type": recipient_type} + if email.display_name: + recipient_data["name"] = email.display_name to_list = self.data["message"].setdefault("to", []) - to_list.append({"email": email.addr_spec, "name": email.display_name, "type": recipient_type}) + to_list.append(recipient_data) def set_subject(self, subject): if getattr(self.message, "use_template_subject", False): @@ -114,8 +117,9 @@ class MandrillPayload(RequestsPayload): self.data["message"]["subject"] = subject def set_reply_to(self, emails): - reply_to = ", ".join([str(email) for email in emails]) - self.data["message"].setdefault("headers", {})["Reply-To"] = reply_to + if emails: + reply_to = ", ".join([str(email) for email in emails]) + self.data["message"].setdefault("headers", {})["Reply-To"] = reply_to def set_extra_headers(self, headers): self.data["message"].setdefault("headers", {}).update(headers) diff --git a/tests/test_mandrill_backend.py b/tests/test_mandrill_backend.py index 4bcba44..dc660b2 100644 --- a/tests/test_mandrill_backend.py +++ b/tests/test_mandrill_backend.py @@ -47,7 +47,7 @@ class MandrillBackendStandardEmailTests(MandrillBackendMockAPITestCase): self.assertEqual(data['message']['text'], "Here is the message.") self.assertNotIn('from_name', data['message']) self.assertEqual(data['message']['from_email'], "from@example.com") - self.assertEqual(data['message']['to'], [{'email': 'to@example.com', 'name': '', 'type': 'to'}]) + self.assertEqual(data['message']['to'], [{'email': 'to@example.com', 'type': 'to'}]) def test_name_addr(self): """Make sure RFC2822 name-addr format (with display-name) is allowed @@ -66,11 +66,11 @@ class MandrillBackendStandardEmailTests(MandrillBackendMockAPITestCase): self.assertEqual(data['message']['from_email'], "from@example.com") self.assertEqual(data['message']['to'], [ {'email': 'to1@example.com', 'name': 'Recipient #1', 'type': 'to'}, - {'email': 'to2@example.com', 'name': '', 'type': 'to'}, + {'email': 'to2@example.com', 'type': 'to'}, {'email': 'cc1@example.com', 'name': 'Carbon Copy', 'type': 'cc'}, - {'email': 'cc2@example.com', 'name': '', 'type': 'cc'}, + {'email': 'cc2@example.com', 'type': 'cc'}, {'email': 'bcc1@example.com', 'name': 'Blind Copy', 'type': 'bcc'}, - {'email': 'bcc2@example.com', 'name': '', 'type': 'bcc'}, + {'email': 'bcc2@example.com', 'type': 'bcc'}, ]) def test_email_message(self): @@ -94,11 +94,11 @@ class MandrillBackendStandardEmailTests(MandrillBackendMockAPITestCase): 'Message-ID': 'mycustommsgid@example.com'}) # Verify recipients correctly identified as "to", "cc", or "bcc" self.assertEqual(data['message']['to'], [ - {'email': 'to1@example.com', 'name': '', 'type': 'to'}, + {'email': 'to1@example.com', 'type': 'to'}, {'email': 'to2@example.com', 'name': 'Also To', 'type': 'to'}, - {'email': 'cc1@example.com', 'name': '', 'type': 'cc'}, + {'email': 'cc1@example.com', 'type': 'cc'}, {'email': 'cc2@example.com', 'name': 'Also CC', 'type': 'cc'}, - {'email': 'bcc1@example.com', 'name': '', 'type': 'bcc'}, + {'email': 'bcc1@example.com', 'type': 'bcc'}, {'email': 'bcc2@example.com', 'name': 'Also BCC', 'type': 'bcc'}, ]) # Don't use Mandrill's bcc_address "logging" feature for bcc's: @@ -551,6 +551,21 @@ class MandrillBackendAnymailFeatureTests(MandrillBackendMockAPITestCase): self.assertIn("Don't know how to send this data to Mandrill", str(err)) # our added context self.assertRegex(str(err), r"Decimal.*is not JSON serializable") # original message + def test_no_extraneous_fields(self): + """Don't send empty fields that have no effect on sending""" + mail.send_mail("Subject", "Body", "from@example.com", ["to@example.com"]) + data = self.get_api_call_json() + # Simple send should contain exactly this, nothing more: + self.assertEqual(data, { + "key": "test_api_key", + "message": { + "from_email": "from@example.com", + "to": [{"email": "to@example.com", "type": "to"}], + "subject": "Subject", + "text": "Body", + }, + }) + @tag('mandrill') class MandrillBackendRecipientsRefusedTests(MandrillBackendMockAPITestCase):