Skip to content

Commit 6acdf36

Browse files
committed
Resend: Remove obsolete display name workaround
1 parent e548f6c commit 6acdf36

File tree

3 files changed

+7
-138
lines changed

3 files changed

+7
-138
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ Fixes
5959
Other
6060
~~~~~
6161

62+
* **Resend:** Remove Anymail's workaround for an earlier Resend API bug with
63+
punctuation in address display names. Resend has fixed the bug.
64+
6265
* **SendGrid:** Remove Anymail's workaround for an earlier SendGrid API bug with
6366
punctuation in address display names. SendGrid has fixed the bug.
6467

anymail/backends/resend.py

Lines changed: 4 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
import mimetypes
2-
from email.charset import QP, Charset
3-
from email.header import decode_header, make_header
4-
from email.headerregistry import Address
52

63
from ..exceptions import AnymailRequestsAPIError
74
from ..message import AnymailRecipientStatus
@@ -12,11 +9,6 @@
129
)
1310
from .base_requests import AnymailRequestsBackend, RequestsPayload
1411

15-
# Used to force RFC-2047 encoded word
16-
# in address formatting workaround
17-
QP_CHARSET = Charset("utf-8")
18-
QP_CHARSET.header_encoding = QP
19-
2012

2113
class EmailBackend(AnymailRequestsBackend):
2214
"""
@@ -39,18 +31,6 @@ def __init__(self, **kwargs):
3931
)
4032
if not api_url.endswith("/"):
4133
api_url += "/"
42-
43-
# Undocumented setting to control workarounds for Resend display-name issues
44-
# (see below). If/when Resend improves their API, you can disable Anymail's
45-
# workarounds by adding `"RESEND_WORKAROUND_DISPLAY_NAME_BUGS": False`
46-
# to your `ANYMAIL` settings.
47-
self.workaround_display_name_bugs = get_anymail_setting(
48-
"workaround_display_name_bugs",
49-
esp_name=esp_name,
50-
kwargs=kwargs,
51-
default=True,
52-
)
53-
5434
super().__init__(api_url, **kwargs)
5535

5636
def build_message_payload(self, message, defaults):
@@ -118,7 +98,7 @@ def serialize_data(self):
11898
payload = []
11999
for to_email, to in zip(to_emails, self.to_recipients):
120100
data = self.data.copy()
121-
data["to"] = [to_email] # formatted for Resend (w/ workarounds)
101+
data["to"] = [to_email]
122102
if to.addr_spec in self.merge_metadata:
123103
# Merge global metadata with any per-recipient metadata.
124104
recipient_metadata = self.metadata.copy()
@@ -149,59 +129,14 @@ def serialize_data(self):
149129
def init_payload(self):
150130
self.data = {} # becomes json
151131

152-
def _resend_email_address(self, address):
153-
"""
154-
Return EmailAddress address formatted for use with Resend.
155-
156-
Works around a Resend bug that rejects properly formatted RFC 5322
157-
addresses that have the display-name enclosed in double quotes (e.g.,
158-
any display-name containing a comma), by substituting an RFC 2047
159-
encoded word.
160-
161-
This works for all Resend address fields _except_ `from` (see below).
162-
"""
163-
formatted = address.address
164-
if self.backend.workaround_display_name_bugs:
165-
if formatted.startswith('"'):
166-
# Workaround: force RFC-2047 encoded word
167-
formatted = str(
168-
Address(
169-
display_name=QP_CHARSET.header_encode(address.display_name),
170-
addr_spec=address.addr_spec,
171-
)
172-
)
173-
return formatted
174-
175132
def set_from_email(self, email):
176-
# Can't use the address header workaround above for the `from` field:
177-
# self.data["from"] = self._resend_email_address(email)
178-
# When `from` uses RFC-2047 encoding, Resend returns a "security_error"
179-
# status 451, "The email payload contain invalid characters".
180-
formatted = email.address
181-
if self.backend.workaround_display_name_bugs:
182-
if formatted.startswith("=?"):
183-
# Workaround: use an *unencoded* (Unicode str) display-name.
184-
# This allows use of non-ASCII characters (which Resend rejects when
185-
# encoded with RFC 2047). Some punctuation will still result in unusual
186-
# behavior or cause an "invalid `from` field" 422 error, but there's
187-
# nothing we can do about that.
188-
formatted = str(
189-
# email.headerregistry.Address str format uses unencoded Unicode
190-
Address(
191-
# Convert RFC 2047 display name back to Unicode str
192-
display_name=str(
193-
make_header(decode_header(email.display_name))
194-
),
195-
addr_spec=email.addr_spec,
196-
)
197-
)
198-
self.data["from"] = formatted
133+
self.data["from"] = email.address
199134

200135
def set_recipients(self, recipient_type, emails):
201136
assert recipient_type in ["to", "cc", "bcc"]
202137
if emails:
203138
field = recipient_type
204-
self.data[field] = [self._resend_email_address(email) for email in emails]
139+
self.data[field] = [email.address for email in emails]
205140
self.recipients += emails
206141
if recipient_type == "to":
207142
self.to_recipients = emails
@@ -211,9 +146,7 @@ def set_subject(self, subject):
211146

212147
def set_reply_to(self, emails):
213148
if emails:
214-
self.data["reply_to"] = [
215-
self._resend_email_address(email) for email in emails
216-
]
149+
self.data["reply_to"] = [email.address for email in emails]
217150

218151
def set_extra_headers(self, headers):
219152
# Resend requires header values to be strings (not integers) as of 2023-10-20.

tests/test_resend_backend.py

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from decimal import Decimal
55
from email.mime.base import MIMEBase
66
from email.mime.image import MIMEImage
7-
from email.utils import formataddr
87

98
from django.core import mail
109
from django.core.exceptions import ImproperlyConfigured
@@ -100,72 +99,6 @@ def test_name_addr(self):
10099
data["bcc"], ["Blind Copy <bcc1@example.com>", "bcc2@example.com"]
101100
)
102101

103-
def test_display_name_workarounds(self):
104-
# Resend's API has a bug that rejects a display-name in double quotes
105-
# (per RFC 5322 section 3.4). Attempting to omit the quotes works, unless
106-
# the display-name also contains a comma. Try to avoid the whole problem
107-
# by using RFC 2047 encoded words for addresses Resend will parse incorrectly.
108-
msg = mail.EmailMessage(
109-
"Subject",
110-
"Message",
111-
formataddr(("Félix Företag, Inc.", "from@example.com")),
112-
[
113-
'"To, comma" <to1@example.com>',
114-
"non–ascii <to2@example.com>",
115-
"=?utf-8?q?pre_encoded?= <to3@example.com>",
116-
],
117-
reply_to=['"Reply, comma" <reply1@example.com>'],
118-
)
119-
msg.send()
120-
data = self.get_api_call_json()
121-
self.assertEqual(
122-
data["from"],
123-
# for `from` field only, avoid RFC 2047 and retain non-ASCII characters:
124-
'"Félix Företag, Inc." <from@example.com>',
125-
)
126-
self.assertEqual(
127-
data["to"],
128-
[
129-
"=?utf-8?q?To=2C_comma?= <to1@example.com>",
130-
"=?utf-8?b?bm9u4oCTYXNjaWk=?= <to2@example.com>",
131-
"=?utf-8?q?pre_encoded?= <to3@example.com>",
132-
],
133-
)
134-
self.assertEqual(
135-
data["reply_to"], ["=?utf-8?q?Reply=2C_comma?= <reply1@example.com>"]
136-
)
137-
138-
@override_settings(ANYMAIL_RESEND_WORKAROUND_DISPLAY_NAME_BUGS=False)
139-
def test_undocumented_workaround_setting(self):
140-
# Same test as above, but workarounds disabled
141-
msg = mail.EmailMessage(
142-
"Subject",
143-
"Message",
144-
'"Félix Företag" <from@example.com>',
145-
[
146-
'"To, comma" <to1@example.com>',
147-
"non–ascii <to2@example.com>",
148-
"=?utf-8?q?pre_encoded?= <to3@example.com>",
149-
],
150-
reply_to=['"Reply, comma" <reply1@example.com>'],
151-
)
152-
msg.send()
153-
data = self.get_api_call_json()
154-
self.assertEqual(
155-
data["from"],
156-
# (Django uses base64 encoded word unless QP is shorter)
157-
"=?utf-8?b?RsOpbGl4IEbDtnJldGFn?= <from@example.com>",
158-
)
159-
self.assertEqual(
160-
data["to"],
161-
[
162-
'"To, comma" <to1@example.com>',
163-
"=?utf-8?b?bm9u4oCTYXNjaWk=?= <to2@example.com>",
164-
"=?utf-8?q?pre_encoded?= <to3@example.com>",
165-
],
166-
)
167-
self.assertEqual(data["reply_to"], ['"Reply, comma" <reply1@example.com>'])
168-
169102
def test_email_message(self):
170103
email = mail.EmailMessage(
171104
"Subject",

0 commit comments

Comments
 (0)