Ticket #1541: mail_attachment.diff

File mail_attachment.diff, 5.8 KB (added by mssnlayam@…, 8 years ago)
  • django/core/mail.py

     
    11# Use this module for e-mailing.
    22
    33from django.conf import settings
     4import mimetypes
     5from email import Encoders
     6from email.Message import Message
     7from email.MIMEAudio import MIMEAudio
     8from email.MIMEBase import MIMEBase
     9from email.MIMEMultipart import MIMEMultipart
     10from email.MIMEImage import MIMEImage
    411from email.MIMEText import MIMEText
    512from email.Header import Header
    613import smtplib, rfc822
     
    2229            val = Header(val, settings.DEFAULT_CHARSET)
    2330        MIMEText.__setitem__(self, name, val)
    2431
    25 def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=settings.EMAIL_HOST_USER, auth_password=settings.EMAIL_HOST_PASSWORD):
     32class SafeMIMEMultipart(MIMEMultipart):
     33    def __setitem__(self, name, val):
     34        "Forbids multi-line headers, to prevent header injection."
     35        if '\n' in val or '\r' in val:
     36            raise BadHeaderError, "Header values can't contain newlines (got %r for header %r)" % (val, name)
     37        if name == "Subject":
     38            val = Header(val, settings.DEFAULT_CHARSET)
     39        MIMEMultipart.__setitem__(self, name, val)
     40
     41    def attachFile(self, filename, fp):
     42        ctype, encoding = mimetypes.guess_type(filename)
     43        if ctype is None or encoding is not None:
     44            ctype = 'application/octet-stream'
     45        maintype, subtype = ctype.split('/', 1)
     46        if maintype == 'text':
     47            msg = SafeMIMEText(fp.read(), _subtype=subtype, _charset=settings.DEFAULT_CHARSET)
     48        elif maintype == 'image':
     49            msg = MIMEImage(fp.read(), _subtype=subtype)
     50        elif maintype == 'audio':
     51            msg = MIMEAudio(fp.read(), _subtype=subtype)
     52        else:
     53            msg = MIMEBase(maintype, subtype)
     54            msg.set_payload(fp.read())
     55            # Encode the payload using Base64
     56            Encoders.encode_base64(msg)
     57        # Set the filename parameter
     58        msg.add_header('Content-Disposition', 'attachment', filename=filename)
     59        MIMEMultipart.attach(self, msg)
     60
     61def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=settings.EMAIL_HOST_USER, auth_password=settings.EMAIL_HOST_PASSWORD, attachments=None):
    2662    """
    2763    Easy wrapper for sending a single message to a recipient list. All members
    2864    of the recipient list will see the other recipients in the 'To' field.
    2965    """
    30     return send_mass_mail([[subject, message, from_email, recipient_list]], fail_silently, auth_user, auth_password)
     66    return send_mass_mail([[subject, message, from_email, recipient_list, attachments]], fail_silently, auth_user, auth_password)
    3167
    3268def send_mass_mail(datatuple, fail_silently=False, auth_user=settings.EMAIL_HOST_USER, auth_password=settings.EMAIL_HOST_PASSWORD):
    3369    """
     
    4682            return
    4783        raise
    4884    num_sent = 0
    49     for subject, message, from_email, recipient_list in datatuple:
     85    for i in datatuple:
     86        try:
     87            subject, message, from_email, recipient_list, attachments = i
     88        except ValueError:
     89            subject, message, from_email, recipient_list = i
     90            attachments = None
    5091        if not recipient_list:
    5192            continue
    5293        from_email = from_email or settings.DEFAULT_FROM_EMAIL
    53         msg = SafeMIMEText(message, 'plain', settings.DEFAULT_CHARSET)
     94        body = SafeMIMEText(message, 'plain', settings.DEFAULT_CHARSET)
     95        if attachments:
     96            # This is a multipart mail
     97            msg = SafeMIMEMultipart()
     98            # First the body
     99            msg.attach(body)
     100            # Then the various files to be attached.
     101            for (filename, fp) in attachments:
     102                msg.attachFile(filename, fp)
     103        else:
     104            msg = body
    54105        msg['Subject'] = subject
    55106        msg['From'] = from_email
    56107        msg['To'] = ', '.join(recipient_list)
  • docs/email.txt

     
    3535
    3636    send_mail(subject, message, from_email, recipient_list,
    3737        fail_silently=False, auth_user=EMAIL_HOST_USER,
    38         auth_password=EMAIL_HOST_PASSWORD)
     38        auth_password=EMAIL_HOST_PASSWORD, attachments=None)
    3939
    4040The ``subject``, ``message``, ``from_email`` and ``recipient_list`` parameters
    4141are required.
     
    5555    * ``auth_password``: The optional password to use to authenticate to the
    5656      SMTP server. If this isn't provided, Django will use the value of the
    5757      ``EMAIL_HOST_PASSWORD`` setting.
     58    * ``attachments``: A list of ``(filename, fp)`` tuples specifying
     59      attachements.
    5860
    5961.. _smtplib docs: http://www.python.org/doc/current/lib/module-smtplib.html
    6062
     63Sending mail with attachments
     64-----------------------------
     65
     66``attachments`` is a list of ``(filename, fp)`` tuples. ``filename`` specifes
     67the name of the file to be attached, and ``fp`` is the file stream. To attach
     68an image and an audio file pass
     69
     70    attachments = [
     71        ('image.png', open('/home/user/image.png', 'rb')),
     72        ('audio.mp3', open('/home/user/audio.mp3', 'rb')),
     73    ]
     74
     75to the ``send_mail`` function.
     76
    6177send_mass_mail()
    6278================
    6379
     
    6783    send_mass_mail(datatuple, fail_silently=False,
    6884        auth_user=EMAIL_HOST_USER, auth_password=EMAIL_HOST_PASSWORD):
    6985
    70 ``datatuple`` is a tuple in which each element is in this format::
     86``datatuple`` is a tuple in which each element is either in the format::
    7187
    7288    (subject, message, from_email, recipient_list)
    7389
     90or::
     91
     92    (subject, message, from_email, recipient_list, attachments)
     93
    7494``fail_silently``, ``auth_user`` and ``auth_password`` have the same functions
    7595as in ``send_mail()``.
    7696
Back to Top