Sendinblue: fix "invalid headers" error

Work around recent (unannounced) Sendinblue API change
that caused "Invalid headers" API error with non-string
custom header values, by converting basic numeric types
to strings. (Borrowed code from SendGrid backend.)

Fixes #288
This commit is contained in:
medmunds
2022-11-04 15:23:29 -07:00
committed by Mike Edmunds
parent 448e8d9d95
commit 681a4afe6b
3 changed files with 13 additions and 3 deletions

View File

@@ -52,6 +52,10 @@ Fixes
* **Postmark:** Handle Postmark's SubscriptionChange events as Anymail
unsubscribe, subscribe, or bounce tracking events, rather than "unknown".
(Thanks to `@puru02`_ for the fix.)
* **Sendinblue:** Work around recent (unannounced) Sendinblue API change
that caused "Invalid headers" API error with non-string custom header
values. Anymail now converts int and float header values to strings.
Other
~~~~~

View File

@@ -3,7 +3,7 @@ from requests.structures import CaseInsensitiveDict
from .base_requests import AnymailRequestsBackend, RequestsPayload
from ..exceptions import AnymailRequestsAPIError
from ..message import AnymailRecipientStatus
from ..utils import get_anymail_setting
from ..utils import get_anymail_setting, BASIC_NUMERIC_TYPES
class EmailBackend(AnymailRequestsBackend):
@@ -112,7 +112,12 @@ class SendinBluePayload(RequestsPayload):
self.data['replyTo'] = self.email_object(emails[0])
def set_extra_headers(self, headers):
self.data['headers'].update(headers)
# SendinBlue requires header values to be strings -- not integers -- as of 11/2022.
# We'll stringify ints and floats; anything else is the caller's responsibility.
self.data["headers"].update({
k: str(v) if isinstance(v, BASIC_NUMERIC_TYPES) else v
for k, v in headers.items()
})
def set_tags(self, tags):
if len(tags) > 0:

View File

@@ -118,7 +118,8 @@ class SendinBlueBackendStandardEmailTests(SendinBlueBackendMockAPITestCase):
self.message.send()
data = self.get_api_call_json()
self.assertEqual(data['headers']['X-Custom'], 'string')
self.assertEqual(data['headers']['X-Num'], 123)
# Header values must be strings (changed 11/2022)
self.assertEqual(data['headers']['X-Num'], "123")
# Reply-To must be moved to separate param
self.assertNotIn('Reply-To', data['headers'])
self.assertEqual(data['replyTo'], {'name': "Do Not Reply", 'email': "noreply@example.com"})