summaryrefslogtreecommitdiff
path: root/django/core/mail.py
diff options
context:
space:
mode:
Diffstat (limited to 'django/core/mail.py')
-rw-r--r--django/core/mail.py84
1 files changed, 46 insertions, 38 deletions
diff --git a/django/core/mail.py b/django/core/mail.py
index 72343cb4df..bf48dcb882 100644
--- a/django/core/mail.py
+++ b/django/core/mail.py
@@ -2,20 +2,21 @@
Tools for sending email.
"""
-from django.conf import settings
-from django.utils.encoding import smart_str, force_unicode
-from email import Charset, Encoders
-from email.MIMEText import MIMEText
-from email.MIMEMultipart import MIMEMultipart
-from email.MIMEBase import MIMEBase
-from email.Header import Header
-from email.Utils import formatdate, parseaddr, formataddr
import mimetypes
import os
import smtplib
import socket
import time
import random
+from email import Charset, Encoders
+from email.MIMEText import MIMEText
+from email.MIMEMultipart import MIMEMultipart
+from email.MIMEBase import MIMEBase
+from email.Header import Header
+from email.Utils import formatdate, parseaddr, formataddr
+
+from django.conf import settings
+from django.utils.encoding import smart_str, force_unicode
# Don't BASE64-encode UTF-8 messages so that we avoid unwanted attention from
# some spam filters.
@@ -38,8 +39,9 @@ class CachedDnsName(object):
DNS_NAME = CachedDnsName()
-# Copied from Python standard library and modified to used the cached hostname
-# for performance.
+# Copied from Python standard library, with the following modifications:
+# * Used cached hostname for performance.
+# * Added try/except to support lack of getpid() in Jython (#5496).
def make_msgid(idstring=None):
"""Returns a string suitable for RFC 2822 compliant Message-ID, e.g:
@@ -53,7 +55,7 @@ def make_msgid(idstring=None):
try:
pid = os.getpid()
except AttributeError:
- # Not getpid() in Jython, for example.
+ # No getpid() in Jython, for example.
pid = 1
randint = random.randrange(100000)
if idstring is None:
@@ -68,7 +70,7 @@ class BadHeaderError(ValueError):
pass
def forbid_multi_line_headers(name, val):
- "Forbids multi-line headers, to prevent header injection."
+ """Forbids multi-line headers, to prevent header injection."""
if '\n' in val or '\r' in val:
raise BadHeaderError("Header values can't contain newlines (got %r for header %r)" % (val, name))
try:
@@ -101,7 +103,7 @@ class SMTPConnection(object):
"""
def __init__(self, host=None, port=None, username=None, password=None,
- use_tls=None, fail_silently=False):
+ use_tls=None, fail_silently=False):
self.host = host or settings.EMAIL_HOST
self.port = port or settings.EMAIL_PORT
self.username = username or settings.EMAIL_HOST_USER
@@ -112,14 +114,17 @@ class SMTPConnection(object):
def open(self):
"""
- Ensure we have a connection to the email server. Returns whether or not
- a new connection was required.
+ Ensures we have a connection to the email server. Returns whether or
+ not a new connection was required (True or False).
"""
if self.connection:
# Nothing to do if the connection is already open.
return False
try:
- self.connection = smtplib.SMTP(self.host, self.port)
+ # If local_hostname is not specified, socket.getfqdn() gets used.
+ # For performance, we use the cached FQDN for local_hostname.
+ self.connection = smtplib.SMTP(self.host, self.port,
+ local_hostname=DNS_NAME.get_fqdn())
if self.use_tls:
self.connection.ehlo()
self.connection.starttls()
@@ -132,7 +137,7 @@ class SMTPConnection(object):
raise
def close(self):
- """Close the connection to the email server."""
+ """Closes the connection to the email server."""
try:
try:
self.connection.quit()
@@ -149,7 +154,7 @@ class SMTPConnection(object):
def send_messages(self, email_messages):
"""
- Send one or more EmailMessage objects and return the number of email
+ Sends one or more EmailMessage objects and returns the number of email
messages sent.
"""
if not email_messages:
@@ -192,7 +197,7 @@ class EmailMessage(object):
def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
connection=None, attachments=None, headers=None):
"""
- Initialise a single email message (which can be sent to multiple
+ Initialize a single email message (which can be sent to multiple
recipients).
All strings used to create the message can be unicode strings (or UTF-8
@@ -221,7 +226,8 @@ class EmailMessage(object):
def message(self):
encoding = self.encoding or settings.DEFAULT_CHARSET
- msg = SafeMIMEText(smart_str(self.body, settings.DEFAULT_CHARSET), self.content_subtype, encoding)
+ msg = SafeMIMEText(smart_str(self.body, settings.DEFAULT_CHARSET),
+ self.content_subtype, encoding)
if self.attachments:
body_msg = msg
msg = SafeMIMEMultipart(_subtype=self.multipart_subtype)
@@ -237,8 +243,6 @@ class EmailMessage(object):
msg['To'] = ', '.join(self.to)
msg['Date'] = formatdate()
msg['Message-ID'] = make_msgid()
- if self.bcc:
- msg['Bcc'] = ', '.join(self.bcc)
for name, value in self.extra_headers.items():
msg[name] = value
return msg
@@ -251,7 +255,7 @@ class EmailMessage(object):
return self.to + self.bcc
def send(self, fail_silently=False):
- """Send the email message."""
+ """Sends the email message."""
return self.get_connection(fail_silently).send_messages([self])
def attach(self, filename=None, content=None, mimetype=None):
@@ -278,7 +282,7 @@ class EmailMessage(object):
def _create_attachment(self, filename, content, mimetype=None):
"""
- Convert the filename, content, mimetype triple into a MIME attachment
+ Converts the filename, content, mimetype triple into a MIME attachment
object.
"""
if mimetype is None:
@@ -295,7 +299,8 @@ class EmailMessage(object):
attachment.set_payload(content)
Encoders.encode_base64(attachment)
if filename:
- attachment.add_header('Content-Disposition', 'attachment', filename=filename)
+ attachment.add_header('Content-Disposition', 'attachment',
+ filename=filename)
return attachment
class EmailMultiAlternatives(EmailMessage):
@@ -310,7 +315,8 @@ class EmailMultiAlternatives(EmailMessage):
"""Attach an alternative content representation."""
self.attach(content=content, mimetype=mimetype)
-def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None):
+def send_mail(subject, message, from_email, recipient_list,
+ fail_silently=False, auth_user=None, auth_password=None):
"""
Easy wrapper for sending a single message to a recipient list. All members
of the recipient list will see the other recipients in the 'To' field.
@@ -322,10 +328,12 @@ def send_mail(subject, message, from_email, recipient_list, fail_silently=False,
functionality should use the EmailMessage class directly.
"""
connection = SMTPConnection(username=auth_user, password=auth_password,
- fail_silently=fail_silently)
- return EmailMessage(subject, message, from_email, recipient_list, connection=connection).send()
+ fail_silently=fail_silently)
+ return EmailMessage(subject, message, from_email, recipient_list,
+ connection=connection).send()
-def send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None):
+def send_mass_mail(datatuple, fail_silently=False, auth_user=None,
+ auth_password=None):
"""
Given a datatuple of (subject, message, from_email, recipient_list), sends
each message to each recipient list. Returns the number of e-mails sent.
@@ -339,19 +347,19 @@ def send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password
functionality should use the EmailMessage class directly.
"""
connection = SMTPConnection(username=auth_user, password=auth_password,
- fail_silently=fail_silently)
- messages = [EmailMessage(subject, message, sender, recipient) for subject, message, sender, recipient in datatuple]
+ fail_silently=fail_silently)
+ messages = [EmailMessage(subject, message, sender, recipient)
+ for subject, message, sender, recipient in datatuple]
return connection.send_messages(messages)
def mail_admins(subject, message, fail_silently=False):
- "Sends a message to the admins, as defined by the ADMINS setting."
+ """Sends a message to the admins, as defined by the ADMINS setting."""
EmailMessage(settings.EMAIL_SUBJECT_PREFIX + subject, message,
- settings.SERVER_EMAIL, [a[1] for a in
- settings.ADMINS]).send(fail_silently=fail_silently)
+ settings.SERVER_EMAIL, [a[1] for a in settings.ADMINS]
+ ).send(fail_silently=fail_silently)
def mail_managers(subject, message, fail_silently=False):
- "Sends a message to the managers, as defined by the MANAGERS setting."
+ """Sends a message to the managers, as defined by the MANAGERS setting."""
EmailMessage(settings.EMAIL_SUBJECT_PREFIX + subject, message,
- settings.SERVER_EMAIL, [a[1] for a in
- settings.MANAGERS]).send(fail_silently=fail_silently)
-
+ settings.SERVER_EMAIL, [a[1] for a in settings.MANAGERS]
+ ).send(fail_silently=fail_silently)