Fixed #1135 -- Changed django.core.mail functions not to allow newlines in headers
git-svn-id: http://code.djangoproject.com/svn/django/trunk@1795 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
f7f812cd70
commit
8b5c2192e8
|
@ -4,6 +4,13 @@ from django.conf.settings import DEFAULT_FROM_EMAIL, EMAIL_HOST, EMAIL_SUBJECT_P
|
||||||
from email.MIMEText import MIMEText
|
from email.MIMEText import MIMEText
|
||||||
import smtplib
|
import smtplib
|
||||||
|
|
||||||
|
class SafeMIMEText(MIMEText):
|
||||||
|
def __setitem__(self, name, val):
|
||||||
|
"Forbids multi-line headers, to prevent header injection."
|
||||||
|
if '\n' in val or '\r' in val:
|
||||||
|
raise ValueError, "Header values can't contain newlines (got %r for header %r)" % (val, name)
|
||||||
|
MIMEText.__setitem__(self, name, val)
|
||||||
|
|
||||||
def send_mail(subject, message, from_email, recipient_list, fail_silently=False):
|
def send_mail(subject, message, from_email, recipient_list, fail_silently=False):
|
||||||
"""
|
"""
|
||||||
Easy wrapper for sending a single message to a recipient list. All members
|
Easy wrapper for sending a single message to a recipient list. All members
|
||||||
|
@ -29,7 +36,7 @@ def send_mass_mail(datatuple, fail_silently=False):
|
||||||
if not recipient_list:
|
if not recipient_list:
|
||||||
continue
|
continue
|
||||||
from_email = from_email or DEFAULT_FROM_EMAIL
|
from_email = from_email or DEFAULT_FROM_EMAIL
|
||||||
msg = MIMEText(message)
|
msg = SafeMIMEText(message)
|
||||||
msg['Subject'] = subject
|
msg['Subject'] = subject
|
||||||
msg['From'] = from_email
|
msg['From'] = from_email
|
||||||
msg['To'] = ', '.join(recipient_list)
|
msg['To'] = ', '.join(recipient_list)
|
||||||
|
|
|
@ -114,3 +114,41 @@ receiving a separate e-mail::
|
||||||
('Subject', 'Message.', 'from@example.com', ['jane@example.com'],
|
('Subject', 'Message.', 'from@example.com', ['jane@example.com'],
|
||||||
)
|
)
|
||||||
send_mass_mail(datatuple)
|
send_mass_mail(datatuple)
|
||||||
|
|
||||||
|
Preventing header injection
|
||||||
|
===========================
|
||||||
|
|
||||||
|
**New in Django development version.**
|
||||||
|
|
||||||
|
`Header injection`_ is a security exploit in which an attacker inserts extra
|
||||||
|
e-mail headers to control the "To:" and "From:" in e-mail messages that your
|
||||||
|
scripts generate.
|
||||||
|
|
||||||
|
The Django e-mail functions outlined above all protect against header injection
|
||||||
|
by forbidding newlines in header values. If any ``subject``, ``from_email`` or
|
||||||
|
``recipient_list`` contains a newline, the e-mail function (e.g.
|
||||||
|
``send_mail()``) will raise ``ValueError`` and, hence, will not send the
|
||||||
|
e-mail. It's your responsibility to validate all data before passing it to the
|
||||||
|
e-mail functions.
|
||||||
|
|
||||||
|
Here's an example view that takes a ``subject``, ``message`` and ``from_email``
|
||||||
|
from the request's POST data, sends that to admin@example.com and redirects to
|
||||||
|
"/contact/thanks/" when it's done::
|
||||||
|
|
||||||
|
from django.core.mail import send_mail
|
||||||
|
|
||||||
|
def send_email(request):
|
||||||
|
subject = request.POST.get('subject', '')
|
||||||
|
message = request.POST.get('message', '')
|
||||||
|
from_email = request.POST.get('from_email', '')
|
||||||
|
if subject and message and from_email \
|
||||||
|
and '\n' not in subject and '\n' not in message
|
||||||
|
and '\n' not in from_email:
|
||||||
|
send_mail(subject, message, from_email, ['admin@example.com'])
|
||||||
|
return HttpResponseRedirect('/contact/thanks/')
|
||||||
|
else:
|
||||||
|
# In reality we'd use a manipulator
|
||||||
|
# to get proper validation errors.
|
||||||
|
return HttpResponse('Make sure all fields are entered and valid.')
|
||||||
|
|
||||||
|
.. _Header injection: http://securephp.damonkohler.com/index.php/Email_Injection
|
||||||
|
|
Loading…
Reference in New Issue