mirror of
https://github.com/pacnpal/django-anymail.git
synced 2025-12-20 03:41:05 -05:00
Utils: Finish ParsedEmail --> EmailAddress conversion
Within an EmailAddress (previously ParsedEmail object), properties now match Python 3.6 email.headerregistry.Address naming: * .email --> .addr_spec * .name --> .display_name * .localpart --> .username (Completes work started in 386668908423d1d4eade90cf7a21a546a1e96514; this updates remaining uses of old names and removes them.)
This commit is contained in:
@@ -53,7 +53,7 @@ class EmailBackend(AnymailRequestsBackend):
|
|||||||
backend=self)
|
backend=self)
|
||||||
# Simulate a per-recipient status of "queued":
|
# Simulate a per-recipient status of "queued":
|
||||||
status = AnymailRecipientStatus(message_id=message_id, status="queued")
|
status = AnymailRecipientStatus(message_id=message_id, status="queued")
|
||||||
return {recipient.email: status for recipient in payload.all_recipients}
|
return {recipient.addr_spec: status for recipient in payload.all_recipients}
|
||||||
|
|
||||||
|
|
||||||
class MailgunPayload(RequestsPayload):
|
class MailgunPayload(RequestsPayload):
|
||||||
@@ -127,7 +127,7 @@ class MailgunPayload(RequestsPayload):
|
|||||||
self.data[recipient_type] = [email.address for email in emails]
|
self.data[recipient_type] = [email.address for email in emails]
|
||||||
self.all_recipients += emails # used for backend.parse_recipient_status
|
self.all_recipients += emails # used for backend.parse_recipient_status
|
||||||
if recipient_type == 'to':
|
if recipient_type == 'to':
|
||||||
self.to_emails = [email.email for email in emails] # used for populate_recipient_variables
|
self.to_emails = [email.addr_spec for email in emails] # used for populate_recipient_variables
|
||||||
|
|
||||||
def set_subject(self, subject):
|
def set_subject(self, subject):
|
||||||
self.data["subject"] = subject
|
self.data["subject"] = subject
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ class EmailBackend(AnymailRequestsBackend):
|
|||||||
# (Mailjet only communicates "Sent")
|
# (Mailjet only communicates "Sent")
|
||||||
for recipients in payload.recipients.values():
|
for recipients in payload.recipients.values():
|
||||||
for email in recipients:
|
for email in recipients:
|
||||||
if email.email not in recipient_status:
|
if email.addr_spec not in recipient_status:
|
||||||
recipient_status[email.email] = AnymailRecipientStatus(message_id=None, status='unknown')
|
recipient_status[email.addr_spec] = AnymailRecipientStatus(message_id=None, status='unknown')
|
||||||
|
|
||||||
return recipient_status
|
return recipient_status
|
||||||
|
|
||||||
@@ -144,9 +144,9 @@ class MailjetPayload(RequestsPayload):
|
|||||||
merge_data = self.merge_data or {}
|
merge_data = self.merge_data or {}
|
||||||
for email in self.recipients["to"]:
|
for email in self.recipients["to"]:
|
||||||
recipient = {
|
recipient = {
|
||||||
"Email": email.email,
|
"Email": email.addr_spec,
|
||||||
"Name": email.name,
|
"Name": email.display_name,
|
||||||
"Vars": merge_data.get(email.email)
|
"Vars": merge_data.get(email.addr_spec)
|
||||||
}
|
}
|
||||||
# Strip out empty Name and Vars
|
# Strip out empty Name and Vars
|
||||||
recipient = {k: v for k, v in recipient.items() if v}
|
recipient = {k: v for k, v in recipient.items() if v}
|
||||||
@@ -163,9 +163,9 @@ class MailjetPayload(RequestsPayload):
|
|||||||
# Workaround Mailjet 3.0 bug parsing display-name with commas
|
# Workaround Mailjet 3.0 bug parsing display-name with commas
|
||||||
# (see test_comma_in_display_name in test_mailjet_backend for details)
|
# (see test_comma_in_display_name in test_mailjet_backend for details)
|
||||||
formatted_emails = [
|
formatted_emails = [
|
||||||
email.address if "," not in email.name
|
email.address if "," not in email.display_name
|
||||||
# else name has a comma, so force it into MIME encoded-word utf-8 syntax:
|
# else name has a comma, so force it into MIME encoded-word utf-8 syntax:
|
||||||
else EmailAddress(email.name.encode('utf-8'), email.email).formataddr('utf-8')
|
else EmailAddress(email.display_name.encode('utf-8'), email.addr_spec).formataddr('utf-8')
|
||||||
for email in emails
|
for email in emails
|
||||||
]
|
]
|
||||||
self.data[recipient_type.capitalize()] = ", ".join(formatted_emails)
|
self.data[recipient_type.capitalize()] = ", ".join(formatted_emails)
|
||||||
@@ -175,9 +175,9 @@ class MailjetPayload(RequestsPayload):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def set_from_email(self, email):
|
def set_from_email(self, email):
|
||||||
self.data["FromEmail"] = email.email
|
self.data["FromEmail"] = email.addr_spec
|
||||||
if email.name:
|
if email.display_name:
|
||||||
self.data["FromName"] = email.name
|
self.data["FromName"] = email.display_name
|
||||||
|
|
||||||
def set_recipients(self, recipient_type, emails):
|
def set_recipients(self, recipient_type, emails):
|
||||||
assert recipient_type in ["to", "cc", "bcc"]
|
assert recipient_type in ["to", "cc", "bcc"]
|
||||||
|
|||||||
@@ -95,14 +95,14 @@ class MandrillPayload(RequestsPayload):
|
|||||||
if getattr(self.message, "use_template_from", False):
|
if getattr(self.message, "use_template_from", False):
|
||||||
self.deprecation_warning('message.use_template_from', 'message.from_email = None')
|
self.deprecation_warning('message.use_template_from', 'message.from_email = None')
|
||||||
else:
|
else:
|
||||||
self.data["message"]["from_email"] = email.email
|
self.data["message"]["from_email"] = email.addr_spec
|
||||||
if email.name:
|
if email.display_name:
|
||||||
self.data["message"]["from_name"] = email.name
|
self.data["message"]["from_name"] = email.display_name
|
||||||
|
|
||||||
def add_recipient(self, recipient_type, email):
|
def add_recipient(self, recipient_type, email):
|
||||||
assert recipient_type in ["to", "cc", "bcc"]
|
assert recipient_type in ["to", "cc", "bcc"]
|
||||||
to_list = self.data["message"].setdefault("to", [])
|
to_list = self.data["message"].setdefault("to", [])
|
||||||
to_list.append({"email": email.email, "name": email.name, "type": recipient_type})
|
to_list.append({"email": email.addr_spec, "name": email.display_name, "type": recipient_type})
|
||||||
|
|
||||||
def set_subject(self, subject):
|
def set_subject(self, subject):
|
||||||
if getattr(self.message, "use_template_subject", False):
|
if getattr(self.message, "use_template_subject", False):
|
||||||
|
|||||||
@@ -69,9 +69,9 @@ class EmailBackend(AnymailRequestsBackend):
|
|||||||
backend=self)
|
backend=self)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
recipient.email: AnymailRecipientStatus(
|
recipient.addr_spec: AnymailRecipientStatus(
|
||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
status=('rejected' if recipient.email.lower() in rejected_emails
|
status=('rejected' if recipient.addr_spec.lower() in rejected_emails
|
||||||
else default_status)
|
else default_status)
|
||||||
)
|
)
|
||||||
for recipient in payload.all_recipients
|
for recipient in payload.all_recipients
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class EmailBackend(AnymailRequestsBackend):
|
|||||||
# SendGrid v3 doesn't provide any information in the response for a successful send,
|
# SendGrid v3 doesn't provide any information in the response for a successful send,
|
||||||
# so simulate a per-recipient status of "queued":
|
# so simulate a per-recipient status of "queued":
|
||||||
status = AnymailRecipientStatus(message_id=payload.message_id, status="queued")
|
status = AnymailRecipientStatus(message_id=payload.message_id, status="queued")
|
||||||
return {recipient.email: status for recipient in payload.all_recipients}
|
return {recipient.addr_spec: status for recipient in payload.all_recipients}
|
||||||
|
|
||||||
|
|
||||||
class SendGridPayload(RequestsPayload):
|
class SendGridPayload(RequestsPayload):
|
||||||
@@ -199,17 +199,17 @@ class SendGridPayload(RequestsPayload):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def email_object(email, workaround_name_quote_bug=False):
|
def email_object(email, workaround_name_quote_bug=False):
|
||||||
"""Converts ParsedEmail to SendGrid API {email, name} dict"""
|
"""Converts EmailAddress to SendGrid API {email, name} dict"""
|
||||||
obj = {"email": email.email}
|
obj = {"email": email.addr_spec}
|
||||||
if email.name:
|
if email.display_name:
|
||||||
# Work around SendGrid API bug: v3 fails to properly quote display-names
|
# Work around SendGrid API bug: v3 fails to properly quote display-names
|
||||||
# containing commas or semicolons in personalizations (but not in from_email
|
# containing commas or semicolons in personalizations (but not in from_email
|
||||||
# or reply_to). See https://github.com/sendgrid/sendgrid-python/issues/291.
|
# or reply_to). See https://github.com/sendgrid/sendgrid-python/issues/291.
|
||||||
# We can work around the problem by quoting the name for SendGrid.
|
# We can work around the problem by quoting the name for SendGrid.
|
||||||
if workaround_name_quote_bug:
|
if workaround_name_quote_bug:
|
||||||
obj["name"] = '"%s"' % rfc822_quote(email.name)
|
obj["name"] = '"%s"' % rfc822_quote(email.display_name)
|
||||||
else:
|
else:
|
||||||
obj["name"] = email.name
|
obj["name"] = email.display_name
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def set_from_email(self, email):
|
def set_from_email(self, email):
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class EmailBackend(AnymailRequestsBackend):
|
|||||||
backend=self)
|
backend=self)
|
||||||
# Simulate a per-recipient status of "queued":
|
# Simulate a per-recipient status of "queued":
|
||||||
status = AnymailRecipientStatus(message_id=payload.message_id, status="queued")
|
status = AnymailRecipientStatus(message_id=payload.message_id, status="queued")
|
||||||
return {recipient.email: status for recipient in payload.all_recipients}
|
return {recipient.addr_spec: status for recipient in payload.all_recipients}
|
||||||
|
|
||||||
|
|
||||||
class SendGridPayload(RequestsPayload):
|
class SendGridPayload(RequestsPayload):
|
||||||
@@ -166,7 +166,7 @@ class SendGridPayload(RequestsPayload):
|
|||||||
all_fields = set()
|
all_fields = set()
|
||||||
for recipient_data in self.merge_data.values():
|
for recipient_data in self.merge_data.values():
|
||||||
all_fields = all_fields.union(recipient_data.keys())
|
all_fields = all_fields.union(recipient_data.keys())
|
||||||
recipients = [email.email for email in self.to_list]
|
recipients = [email.addr_spec for email in self.to_list]
|
||||||
|
|
||||||
if self.merge_field_format is None and all(field.isalnum() for field in all_fields):
|
if self.merge_field_format is None and all(field.isalnum() for field in all_fields):
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
@@ -203,9 +203,9 @@ class SendGridPayload(RequestsPayload):
|
|||||||
self.data['headers'] = CaseInsensitiveDict() # headers keys are case-insensitive
|
self.data['headers'] = CaseInsensitiveDict() # headers keys are case-insensitive
|
||||||
|
|
||||||
def set_from_email(self, email):
|
def set_from_email(self, email):
|
||||||
self.data["from"] = email.email
|
self.data["from"] = email.addr_spec
|
||||||
if email.name:
|
if email.display_name:
|
||||||
self.data["fromname"] = email.name
|
self.data["fromname"] = email.display_name
|
||||||
|
|
||||||
def set_to(self, emails):
|
def set_to(self, emails):
|
||||||
self.to_list = emails # track for later use by build_merge_data
|
self.to_list = emails # track for later use by build_merge_data
|
||||||
@@ -214,9 +214,9 @@ class SendGridPayload(RequestsPayload):
|
|||||||
def set_recipients(self, recipient_type, emails):
|
def set_recipients(self, recipient_type, emails):
|
||||||
assert recipient_type in ["to", "cc", "bcc"]
|
assert recipient_type in ["to", "cc", "bcc"]
|
||||||
if emails:
|
if emails:
|
||||||
self.data[recipient_type] = [email.email for email in emails]
|
self.data[recipient_type] = [email.addr_spec for email in emails]
|
||||||
empty_name = " " # SendGrid API balks on complete empty name fields
|
empty_name = " " # SendGrid API balks on complete empty name fields
|
||||||
self.data[recipient_type + "name"] = [email.name or empty_name for email in emails]
|
self.data[recipient_type + "name"] = [email.display_name or empty_name for email in emails]
|
||||||
self.all_recipients += emails # used for backend.parse_recipient_status
|
self.all_recipients += emails # used for backend.parse_recipient_status
|
||||||
|
|
||||||
def set_subject(self, subject):
|
def set_subject(self, subject):
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class EmailBackend(AnymailBaseBackend):
|
|||||||
else: # mixed results, or wrong total
|
else: # mixed results, or wrong total
|
||||||
status = 'unknown'
|
status = 'unknown'
|
||||||
recipient_status = AnymailRecipientStatus(message_id=transmission_id, status=status)
|
recipient_status = AnymailRecipientStatus(message_id=transmission_id, status=status)
|
||||||
return {recipient.email: recipient_status for recipient in payload.all_recipients}
|
return {recipient.addr_spec: recipient_status for recipient in payload.all_recipients}
|
||||||
|
|
||||||
|
|
||||||
class SparkPostPayload(BasePayload):
|
class SparkPostPayload(BasePayload):
|
||||||
@@ -92,11 +92,11 @@ class SparkPostPayload(BasePayload):
|
|||||||
if len(self.merge_data) > 0:
|
if len(self.merge_data) > 0:
|
||||||
# Build JSON recipient structures
|
# Build JSON recipient structures
|
||||||
for email in self.to_emails:
|
for email in self.to_emails:
|
||||||
rcpt = {'address': {'email': email.email}}
|
rcpt = {'address': {'email': email.addr_spec}}
|
||||||
if email.name:
|
if email.display_name:
|
||||||
rcpt['address']['name'] = email.name
|
rcpt['address']['name'] = email.display_name
|
||||||
try:
|
try:
|
||||||
rcpt['substitution_data'] = self.merge_data[email.email]
|
rcpt['substitution_data'] = self.merge_data[email.addr_spec]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass # no merge_data or none for this recipient
|
pass # no merge_data or none for this recipient
|
||||||
recipients.append(rcpt)
|
recipients.append(rcpt)
|
||||||
|
|||||||
@@ -68,15 +68,15 @@ class TestPayload(BasePayload):
|
|||||||
|
|
||||||
def set_to(self, emails):
|
def set_to(self, emails):
|
||||||
self.params['to'] = emails
|
self.params['to'] = emails
|
||||||
self.recipient_emails += [email.email for email in emails]
|
self.recipient_emails += [email.addr_spec for email in emails]
|
||||||
|
|
||||||
def set_cc(self, emails):
|
def set_cc(self, emails):
|
||||||
self.params['cc'] = emails
|
self.params['cc'] = emails
|
||||||
self.recipient_emails += [email.email for email in emails]
|
self.recipient_emails += [email.addr_spec for email in emails]
|
||||||
|
|
||||||
def set_bcc(self, emails):
|
def set_bcc(self, emails):
|
||||||
self.params['bcc'] = emails
|
self.params['bcc'] = emails
|
||||||
self.recipient_emails += [email.email for email in emails]
|
self.recipient_emails += [email.addr_spec for email in emails]
|
||||||
|
|
||||||
def set_subject(self, subject):
|
def set_subject(self, subject):
|
||||||
self.params['subject'] = subject
|
self.params['subject'] = subject
|
||||||
|
|||||||
@@ -232,22 +232,6 @@ class EmailAddress(object):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.address
|
return self.address
|
||||||
|
|
||||||
# Deprecated property names from old ParsedEmail (don't use in new code!)
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
return self.display_name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def email(self):
|
|
||||||
return self.addr_spec
|
|
||||||
|
|
||||||
@property
|
|
||||||
def localpart(self):
|
|
||||||
return self.username
|
|
||||||
|
|
||||||
|
|
||||||
ParsedEmail = EmailAddress # deprecated class name (don't use!)
|
|
||||||
|
|
||||||
|
|
||||||
class Attachment(object):
|
class Attachment(object):
|
||||||
"""A normalized EmailMessage.attachments item with additional functionality
|
"""A normalized EmailMessage.attachments item with additional functionality
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class TestPreSendSignal(TestBackendTestCase):
|
|||||||
self.message.to = ['legit@example.com', 'bad@example.com']
|
self.message.to = ['legit@example.com', 'bad@example.com']
|
||||||
self.message.send()
|
self.message.send()
|
||||||
params = self.get_send_params()
|
params = self.get_send_params()
|
||||||
self.assertEqual([email.email for email in params['to']], # params['to'] is ParsedEmail list
|
self.assertEqual([email.addr_spec for email in params['to']], # params['to'] is EmailAddress list
|
||||||
['legit@example.com'])
|
['legit@example.com'])
|
||||||
self.assertRegex(params['text_body'],
|
self.assertRegex(params['text_body'],
|
||||||
r"If you have received this message in error, ignore it$")
|
r"If you have received this message in error, ignore it$")
|
||||||
|
|||||||
Reference in New Issue
Block a user