Django

Code

Changeset 1795

Show
Ignore:
Timestamp:
12/29/05 14:33:56 (3 years ago)
Author:
adrian
Message:

Fixed #1135 -- Changed django.core.mail functions not to allow newlines in headers

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/core/mail.py

    r710 r1795  
    44from email.MIMEText import MIMEText 
    55import smtplib 
     6 
     7class SafeMIMEText(MIMEText): 
     8    def __setitem__(self, name, val): 
     9        "Forbids multi-line headers, to prevent header injection." 
     10        if '\n' in val or '\r' in val: 
     11            raise ValueError, "Header values can't contain newlines (got %r for header %r)" % (val, name) 
     12        MIMEText.__setitem__(self, name, val) 
    613 
    714def send_mail(subject, message, from_email, recipient_list, fail_silently=False): 
     
    3037            continue 
    3138        from_email = from_email or DEFAULT_FROM_EMAIL 
    32         msg = MIMEText(message) 
     39        msg = SafeMIMEText(message) 
    3340        msg['Subject'] = subject 
    3441        msg['From'] = from_email 
  • django/trunk/docs/email.txt

    r1785 r1795  
    115115    ) 
    116116    send_mass_mail(datatuple) 
     117 
     118Preventing header injection 
     119=========================== 
     120 
     121**New in Django development version.** 
     122 
     123`Header injection`_ is a security exploit in which an attacker inserts extra 
     124e-mail headers to control the "To:" and "From:" in e-mail messages that your 
     125scripts generate. 
     126 
     127The Django e-mail functions outlined above all protect against header injection 
     128by forbidding newlines in header values. If any ``subject``, ``from_email`` or 
     129``recipient_list`` contains a newline, the e-mail function (e.g. 
     130``send_mail()``) will raise ``ValueError`` and, hence, will not send the 
     131e-mail. It's your responsibility to validate all data before passing it to the 
     132e-mail functions. 
     133 
     134Here's an example view that takes a ``subject``, ``message`` and ``from_email`` 
     135from the request's POST data, sends that to admin@example.com and redirects to 
     136"/contact/thanks/" when it's done:: 
     137 
     138    from django.core.mail import send_mail 
     139 
     140    def send_email(request): 
     141        subject = request.POST.get('subject', '') 
     142        message = request.POST.get('message', '') 
     143        from_email = request.POST.get('from_email', '') 
     144        if subject and message and from_email \ 
     145                and '\n' not in subject and '\n' not in message 
     146                and '\n' not in from_email: 
     147            send_mail(subject, message, from_email, ['admin@example.com']) 
     148            return HttpResponseRedirect('/contact/thanks/') 
     149        else: 
     150            # In reality we'd use a manipulator 
     151            # to get proper validation errors. 
     152            return HttpResponse('Make sure all fields are entered and valid.') 
     153 
     154.. _Header injection: http://securephp.damonkohler.com/index.php/Email_Injection