Ticket #3366: 3366.diff

File 3366.diff, 6.9 KB (added by Gary Wilson <gary.wilson@…>, 13 years ago)
  • django/core/mail.py

    === modified file 'django/core/mail.py'
     
    1 # Use this module for e-mailing.
     1"""
     2Tools for sending emails.
     3"""
    24
    35from django.conf import settings
    46from email.MIMEText import MIMEText
     
    2224            val = Header(val, settings.DEFAULT_CHARSET)
    2325        MIMEText.__setitem__(self, name, val)
    2426
    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):
    26     """
    27     Easy wrapper for sending a single message to a recipient list. All members
    28     of the recipient list will see the other recipients in the 'To' field.
    29     """
    30     return send_mass_mail([[subject, message, from_email, recipient_list]], fail_silently, auth_user, auth_password)
    31 
    32 def send_mass_mail(datatuple, fail_silently=False, auth_user=settings.EMAIL_HOST_USER, auth_password=settings.EMAIL_HOST_PASSWORD):
    33     """
    34     Given a datatuple of (subject, message, from_email, recipient_list), sends
    35     each message to each recipient list. Returns the number of e-mails sent.
    36 
    37     If from_email is None, the DEFAULT_FROM_EMAIL setting is used.
    38     If auth_user and auth_password are set, they're used to log in.
    39     """
    40     try:
    41         server = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT)
    42         if auth_user and auth_password:
    43             server.login(auth_user, auth_password)
    44     except:
    45         if fail_silently:
    46             return
    47         raise
    48     num_sent = 0
    49     for subject, message, from_email, recipient_list in datatuple:
    50         if not recipient_list:
    51             continue
    52         from_email = from_email or settings.DEFAULT_FROM_EMAIL
    53         msg = SafeMIMEText(message, 'plain', settings.DEFAULT_CHARSET)
    54         msg['Subject'] = subject
    55         msg['From'] = from_email
    56         msg['To'] = ', '.join(recipient_list)
     27class EmailConnection(object):
     28    """An SMTP connection."""
     29
     30    def __init__(self, host=settings.EMAIL_HOST, port=settings.EMAIL_PORT,
     31                 username=settings.EMAIL_HOST_USER,
     32                 password=settings.EMAIL_HOST_PASSWORD, fail_silently=False):
     33        self.host = host
     34        self.port = port
     35        self.username = username
     36        self.password = password
     37        self.fail_silently = fail_silently
     38        self.connection = None
     39
     40    def open(self):
     41        """Open the connection to the email server."""
     42
     43        # Nothing to do if the connection is already open.
     44        if self.connection:
     45            return
     46        try:
     47            self.connection = smtplib.SMTP(self.host, self.port)
     48            if self.username and self.password:
     49                self.connection.login(self.username, self.password)
     50        except:
     51            if self.fail_silently:
     52                return
     53            raise
     54
     55    def close(self):
     56        """Close the connection to the email server."""
     57
     58        # Python versions < 2.5 do not allow try...except...finally,
     59        # so we nest a try...except in a try...finally here for backwards
     60        # compatibility.
     61        try:
     62            try:
     63                self.connection.quit()
     64            except:
     65                if self.fail_silently:
     66                    return
     67                raise
     68        finally:
     69            self.connection = None
     70
     71    def send_messages(self, email_messages):
     72        """
     73        Send one or more EmailMessage objects and return the number of email
     74        messages sent.
     75        """
     76
     77        if not email_messages:
     78            return
     79        self.open()
     80        num_sent = 0
     81        for message in email_messages:
     82            sent = self._send(message)
     83            if sent:
     84                num_sent += 1
     85        self.close()
     86        return num_sent
     87
     88    def _send(self, email_message):
     89        """A helper method that does the actual sending."""
     90
     91        if not email_message.to:
     92            return False
     93        msg = SafeMIMEText(email_message.body, 'plain',
     94                           settings.DEFAULT_CHARSET)
     95        msg['Subject'] = email_message.subject
     96        msg['From'] = email_message.from_email
     97        msg['To'] = ', '.join(email_message.to)
    5798        msg['Date'] = rfc822.formatdate()
     99        msg['Message-ID'] = self._message_id()
     100        try:
     101            self.connection.sendmail(email_message.from_email,
     102                                     email_message.to, msg.as_string())
     103        except:
     104            if not self.fail_silently:
     105                raise
     106        return True
     107
     108    def _message_id(self):
     109        """Generate a message ID."""
     110
     111        # Python 2.3 doesn't have random.getrandbits().
    58112        try:
    59113            random_bits = str(random.getrandbits(64))
    60         except AttributeError: # Python 2.3 doesn't have random.getrandbits().
     114        except AttributeError:
    61115            random_bits = ''.join([random.choice('1234567890') for i in range(19)])
    62         msg['Message-ID'] = "<%d.%s@%s>" % (time.time(), random_bits, DNS_NAME)
    63         try:
    64             server.sendmail(from_email, recipient_list, msg.as_string())
    65             num_sent += 1
    66         except:
    67             if not fail_silently:
    68                 raise
    69     try:
    70         server.quit()
    71     except:
    72         if fail_silently:
    73             return
    74         raise
    75     return num_sent
     116        return "<%d.%s@%s>" % (time.time(), random_bits, DNS_NAME)
     117
     118class EmailMessage(object):
     119    """
     120    A container for email information.
     121    """
     122
     123    def __init__(self, to=None, from_email=settings.DEFAULT_FROM_EMAIL,
     124                 subject="", body="", connection=None):
     125        self.to = to or []
     126        self.from_email = from_email
     127        self.subject = subject
     128        self.body = body
     129
     130    def send(self, connection=None, fail_silently=False):
     131        """Send the email message."""
     132
     133        connection = connection or EmailConnection(fail_silently=fail_silently)
     134        connection.send_messages([self])
    76135
    77136def mail_admins(subject, message, fail_silently=False):
    78137    "Sends a message to the admins, as defined by the ADMINS setting."
    79     send_mail(settings.EMAIL_SUBJECT_PREFIX + subject, message, settings.SERVER_EMAIL, [a[1] for a in settings.ADMINS], fail_silently)
     138
     139    EmailMessage(
     140        subject=settings.EMAIL_SUBJECT_PREFIX + subject,
     141        body=message,
     142        from_email=settings.SERVER_EMAIL,
     143        to=[a[1] for a in settings.ADMINS],
     144    ).send(fail_silently=fail_silently)
    80145
    81146def mail_managers(subject, message, fail_silently=False):
    82147    "Sends a message to the managers, as defined by the MANAGERS setting."
    83     send_mail(settings.EMAIL_SUBJECT_PREFIX + subject, message, settings.SERVER_EMAIL, [a[1] for a in settings.MANAGERS], fail_silently)
     148
     149    EmailMessage(
     150        subject=settings.EMAIL_SUBJECT_PREFIX + subject,
     151        body=message,
     152        from_email=settings.SERVER_EMAIL,
     153        to=[a[1] for a in settings.MANAGERS],
     154    ).send(fail_silently=fail_silently)
Back to Top