Index: django/core/mail.py
===================================================================
--- django/core/mail.py	(revision 5468)
+++ django/core/mail.py	(working copy)
@@ -4,6 +4,7 @@
 
 from django.conf import settings
 from email.MIMEText import MIMEText
+from email.MIMEMultipart import MIMEMultipart
 from email.Header import Header
 from email.Utils import formatdate
 from email import Charset
@@ -64,6 +65,13 @@
             val = Header(val, settings.DEFAULT_CHARSET)
         MIMEText.__setitem__(self, name, val)
 
+class SafeMIMEMultipart(MIMEMultipart):
+    def __setitem__(self, name, val):
+        "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)
+        MIMEMultipart.__setitem__(self, name, val)
+
 class SMTPConnection(object):
     """
     A wrapper that manages the SMTP network connection.
@@ -154,21 +162,35 @@
     """
     A container for email information.
     """
-    def __init__(self, subject='', body='', from_email=None, to=None, bcc=None, connection=None):
+    def __init__(self, subject='', body='',
+                 from_email=None, to=None, bcc=None,
+                 attachments=None, body_html=None,
+                 connection=None):
         self.to = to or []
         self.bcc = bcc or []
         self.from_email = from_email or settings.DEFAULT_FROM_EMAIL
         self.subject = subject
         self.body = body
         self.connection = connection
+        self.attachments = attachments or []
+        if body_html:
+            self.attach(SafeMIMEText(body_html, 'html', settings.DEFAULT_CHARSET))
 
     def get_connection(self, fail_silently=False):
         if not self.connection:
             self.connection = SMTPConnection(fail_silently=fail_silently)
         return self.connection
 
+    def attach(self, attachment):
+        self.attachments += [attachment]
+        
     def message(self):
-        msg = SafeMIMEText(self.body, 'plain', settings.DEFAULT_CHARSET)
+        if self.attachments is not []:
+            msg = SafeMIMEMultipart('alternative', settings.DEFAULT_CHARSET)
+            for attachment in self.attachments:
+                msg.attach(attachment)
+        else:
+            msg = SafeMIMEText(self.body, 'plain', settings.DEFAULT_CHARSET)
         msg['Subject'] = self.subject
         msg['From'] = self.from_email
         msg['To'] = ', '.join(self.to)
@@ -189,7 +211,8 @@
         """Send the email message."""
         return self.get_connection(fail_silently).send_messages([self])
 
-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,
+              message_html=None, 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.
@@ -202,7 +225,8 @@
     """
     connection = SMTPConnection(username=auth_user, password=auth_password,
                                  fail_silently=fail_silently)
-    return EmailMessage(subject, message, from_email, recipient_list, connection=connection).send()
+    return EmailMessage(subject, message, from_email, recipient_list,
+                        body_html=message_html, connection=connection).send()
 
 def send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None):
     """
