Support from_name in "from_name <email>" sender address.

Allows specifying the sender's display name as part of the from email address,
without requiring use of the DjrillMessage class:

    send_mail('Subject', 'Message', 'From Name <from@example.com>',
              ['Recipient #1 <to1@example.com>', 'to2@example.com'])

(This matches the behavior of Django's default SMTP backend.)

Cherry-picked from:
medmunds/Djrill@46cd5c9d: Support "realname <email>" sender address
medmunds/Djrill@cd4e57cc: Support "realname <email>" sender address - fix for using DjrillMessage
medmunds/Djrill@16f8efc9: Add tests for "Display Name <email@example.com>" addresses
This commit is contained in:
medmunds
2012-11-15 15:03:26 -08:00
parent 5a986fe5b5
commit d9cb23b003
2 changed files with 24 additions and 3 deletions

View File

@@ -4,6 +4,7 @@ from django.core.mail.backends.base import BaseEmailBackend
from django.core.mail.message import sanitize_address from django.core.mail.message import sanitize_address
from django.utils import simplejson as json from django.utils import simplejson as json
from email.utils import parseaddr
import requests import requests
class DjrillBackendHTTPError(Exception): class DjrillBackendHTTPError(Exception):
@@ -62,7 +63,6 @@ class DjrillBackend(BaseEmailBackend):
self.sender = sanitize_address(message.from_email, message.encoding) self.sender = sanitize_address(message.from_email, message.encoding)
recipients_list = [sanitize_address(addr, message.encoding) recipients_list = [sanitize_address(addr, message.encoding)
for addr in message.recipients()] for addr in message.recipients()]
from email.utils import parseaddr
self.recipients = [{"email": e, "name": n} for n,e in [ self.recipients = [{"email": e, "name": n} for n,e in [
parseaddr(r) for r in recipients_list]] parseaddr(r) for r in recipients_list]]
@@ -101,12 +101,15 @@ class DjrillBackend(BaseEmailBackend):
use by default. Standard text email messages sent through Django will use by default. Standard text email messages sent through Django will
still work through Mandrill. still work through Mandrill.
""" """
from_name, from_email = parseaddr(self.sender)
msg_dict = { msg_dict = {
"text": message.body, "text": message.body,
"subject": message.subject, "subject": message.subject,
"from_email": self.sender, "from_email": from_email,
"to": self.recipients "to": self.recipients
} }
if from_name:
msg_dict["from_name"] = from_name
if message.extra_headers: if message.extra_headers:
accepted_headers = {} accepted_headers = {}
@@ -123,11 +126,12 @@ class DjrillBackend(BaseEmailBackend):
Builds advanced message dict Builds advanced message dict
""" """
self.msg_dict.update({ self.msg_dict.update({
"from_name": message.from_name,
"tags": message.tags, "tags": message.tags,
"track_opens": message.track_opens, "track_opens": message.track_opens,
"track_clicks": message.track_clicks "track_clicks": message.track_clicks
}) })
if message.from_name:
self.msg_dict["from_name"] = message.from_name
def _add_alternatives(self, message): def _add_alternatives(self, message):

View File

@@ -55,6 +55,7 @@ class DjrillBackendTests(DjrillBackendMockAPITestCase):
data = self.get_api_call_data() data = self.get_api_call_data()
self.assertEqual(data['message']['subject'], "Subject here") self.assertEqual(data['message']['subject'], "Subject here")
self.assertEqual(data['message']['text'], "Here is the message.") self.assertEqual(data['message']['text'], "Here is the message.")
self.assertFalse('from_name' in data['message'])
self.assertEqual(data['message']['from_email'], "from@example.com") self.assertEqual(data['message']['from_email'], "from@example.com")
self.assertEqual(len(data['message']['to']), 1) self.assertEqual(len(data['message']['to']), 1)
self.assertEqual(data['message']['to'][0]['email'], "to@example.com") self.assertEqual(data['message']['to'][0]['email'], "to@example.com")
@@ -65,6 +66,22 @@ class DjrillBackendTests(DjrillBackendMockAPITestCase):
mail.send_mail('Subject', 'Message', 'from@example.com', mail.send_mail('Subject', 'Message', 'from@example.com',
['to@example.com']) ['to@example.com'])
def test_name_addr(self):
"""Make sure RFC2822 name-addr format (with display-name) is allowed
(Test both sender and recipient addresses)
"""
mail.send_mail('Subject', 'Message', 'From Name <from@example.com>',
['Recipient #1 <to1@example.com>', 'to2@example.com'])
data = self.get_api_call_data()
self.assertEqual(data['message']['from_name'], "From Name")
self.assertEqual(data['message']['from_email'], "from@example.com")
self.assertEqual(len(data['message']['to']), 2)
self.assertEqual(data['message']['to'][0]['name'], "Recipient #1")
self.assertEqual(data['message']['to'][0]['email'], "to1@example.com")
self.assertEqual(data['message']['to'][1]['name'], "")
self.assertEqual(data['message']['to'][1]['email'], "to2@example.com")
def test_email_message(self): def test_email_message(self):
email = mail.EmailMessage('Subject', 'Body goes here', email = mail.EmailMessage('Subject', 'Body goes here',
'from@example.com', 'from@example.com',