Browse Source

Fixed #23910 -- Added reply_to parameter to EmailMessage

Thanks to Berker Peksag and Tim Graham for the review and suggestions.
Martin Blech 10 years ago
parent
commit
e023ceb453
4 changed files with 52 additions and 4 deletions
  1. 13 3
      django/core/mail/message.py
  2. 3 0
      docs/releases/1.8.txt
  3. 8 1
      docs/topics/email.txt
  4. 28 0
      tests/mail/tests.py

+ 13 - 3
django/core/mail/message.py

@@ -214,7 +214,8 @@ class EmailMessage(object):
     encoding = None     # None => use settings default
 
     def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
-                 connection=None, attachments=None, headers=None, cc=None):
+                 connection=None, attachments=None, headers=None, cc=None,
+                 reply_to=None):
         """
         Initialize a single email message (which can be sent to multiple
         recipients).
@@ -241,6 +242,12 @@ class EmailMessage(object):
             self.bcc = list(bcc)
         else:
             self.bcc = []
+        if reply_to:
+            if isinstance(reply_to, six.string_types):
+                raise TypeError('"reply_to" argument must be a list or tuple')
+            self.reply_to = list(reply_to)
+        else:
+            self.reply_to = []
         self.from_email = from_email or settings.DEFAULT_FROM_EMAIL
         self.subject = subject
         self.body = body
@@ -263,6 +270,8 @@ class EmailMessage(object):
         msg['To'] = self.extra_headers.get('To', ', '.join(self.to))
         if self.cc:
             msg['Cc'] = ', '.join(self.cc)
+        if self.reply_to:
+            msg['Reply-To'] = self.extra_headers.get('Reply-To', ', '.join(self.reply_to))
 
         # Email header names are case-insensitive (RFC 2045), so we have to
         # accommodate that when doing comparisons.
@@ -395,7 +404,7 @@ class EmailMultiAlternatives(EmailMessage):
 
     def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
             connection=None, attachments=None, headers=None, alternatives=None,
-            cc=None):
+            cc=None, reply_to=None):
         """
         Initialize a single email message (which can be sent to multiple
         recipients).
@@ -405,7 +414,8 @@ class EmailMultiAlternatives(EmailMessage):
         conversions.
         """
         super(EmailMultiAlternatives, self).__init__(
-            subject, body, from_email, to, bcc, connection, attachments, headers, cc
+            subject, body, from_email, to, bcc, connection, attachments,
+            headers, cc, reply_to,
         )
         self.alternatives = alternatives or []
 

+ 3 - 0
docs/releases/1.8.txt

@@ -210,6 +210,9 @@ Email
 * The SMTP :class:`~django.core.mail.backends.smtp.EmailBackend` now supports
   setting the ``timeout`` parameter with the :setting:`EMAIL_TIMEOUT` setting.
 
+* :class:`~django.core.mail.EmailMessage` and ``EmailMultiAlternatives`` now
+  support the ``reply_to`` parameter.
+
 File Storage
 ^^^^^^^^^^^^
 

+ 8 - 1
docs/topics/email.txt

@@ -278,11 +278,18 @@ All parameters are optional and can be set at any time prior to calling the
 * ``cc``: A list or tuple of recipient addresses used in the "Cc" header
   when sending the email.
 
+* ``reply_to``: A list or tuple of recipient addresses used in the "Reply-To"
+  header when sending the email.
+
+.. versionchanged:: 1.8
+
+    The ``reply_to`` parameter was added.
+
 For example::
 
     email = EmailMessage('Hello', 'Body goes here', 'from@example.com',
                 ['to1@example.com', 'to2@example.com'], ['bcc@example.com'],
-                headers = {'Reply-To': 'another@example.com'})
+                reply_to=['another@example.com'], headers={'Message-ID': 'foo'})
 
 The class has the following methods:
 

+ 28 - 0
tests/mail/tests.py

@@ -89,6 +89,21 @@ class MailTests(HeadersCheckMixin, SimpleTestCase):
         self.assertEqual(message['Cc'], 'cc@example.com, cc.other@example.com')
         self.assertEqual(email.recipients(), ['to@example.com', 'other@example.com', 'cc@example.com', 'cc.other@example.com', 'bcc@example.com'])
 
+    def test_reply_to(self):
+        email = EmailMessage(
+            'Subject', 'Content', 'from@example.com', ['to@example.com'],
+            reply_to=['reply_to@example.com'],
+        )
+        message = email.message()
+        self.assertEqual(message['Reply-To'], 'reply_to@example.com')
+
+        email = EmailMessage(
+            'Subject', 'Content', 'from@example.com', ['to@example.com'],
+            reply_to=['reply_to1@example.com', 'reply_to2@example.com']
+        )
+        message = email.message()
+        self.assertEqual(message['Reply-To'], 'reply_to1@example.com, reply_to2@example.com')
+
     def test_recipients_as_tuple(self):
         email = EmailMessage('Subject', 'Content', 'from@example.com', ('to@example.com', 'other@example.com'), cc=('cc@example.com', 'cc.other@example.com'), bcc=('bcc@example.com',))
         message = email.message()
@@ -102,6 +117,8 @@ class MailTests(HeadersCheckMixin, SimpleTestCase):
             EmailMessage(cc='foo@example.com')
         with self.assertRaisesMessage(TypeError, '"bcc" argument must be a list or tuple'):
             EmailMessage(bcc='foo@example.com')
+        with self.assertRaisesMessage(TypeError, '"reply_to" argument must be a list or tuple'):
+            EmailMessage(reply_to='reply_to@example.com')
 
     def test_header_injection(self):
         email = EmailMessage('Subject\nInjection Test', 'Content', 'from@example.com', ['to@example.com'])
@@ -163,6 +180,17 @@ class MailTests(HeadersCheckMixin, SimpleTestCase):
         self.assertEqual(message['To'], 'list-subscriber@example.com, list-subscriber2@example.com')
         self.assertEqual(email.to, ['list-subscriber@example.com', 'list-subscriber2@example.com'])
 
+    def test_reply_to_header(self):
+        """
+        Specifying 'Reply-To' in headers should override reply_to.
+        """
+        email = EmailMessage(
+            'Subject', 'Content', 'bounce@example.com', ['to@example.com'],
+            reply_to=['foo@example.com'], headers={'Reply-To': 'override@example.com'},
+        )
+        message = email.message()
+        self.assertEqual(message['Reply-To'], 'override@example.com')
+
     def test_multiple_message_call(self):
         """
         Regression for #13259 - Make sure that headers are not changed when