=== modified file 'django/core/mail.py'
--- django/core/mail.py	2007-02-26 05:09:04 +0000
+++ django/core/mail.py	2007-03-18 04:22:25 +0000
@@ -1,4 +1,6 @@
-# Use this module for e-mailing.
+"""
+Tools for sending emails.
+"""
 
 from django.conf import settings
 from email.MIMEText import MIMEText
@@ -34,6 +36,119 @@
             val = Header(val, settings.DEFAULT_CHARSET)
         MIMEText.__setitem__(self, name, val)
 
+class EmailConnection(object):
+    """An SMTP connection."""
+
+    def __init__(self, host=None, port=None, username=None, password=None,
+                 fail_silently=False):
+        if host is None:
+            self.host = settings.EMAIL_HOST
+        if port is None:
+            self.port = settings.EMAIL_PORT
+        if username is None:
+        	self.username = settings.EMAIL_HOST_USER
+        if password is None:
+	        self.password = settings.EMAIL_HOST_PASSWORD
+        self.fail_silently = fail_silently
+        self.connection = None
+
+    def open(self):
+        """Open the connection to the email server."""
+
+        # Nothing to do if the connection is already open.
+        if self.connection:
+            return
+        try:
+            self.connection = smtplib.SMTP(self.host, self.port)
+            if self.username and self.password:
+                self.connection.login(self.username, self.password)
+        except:
+            if self.fail_silently:
+                return
+            raise
+
+    def close(self):
+        """Close the connection to the email server."""
+
+        # Python versions < 2.5 do not allow try...except...finally,
+        # so we nest a try...except in a try...finally here for backwards
+        # compatibility.
+        try:
+            try:
+                self.connection.quit()
+            except:
+                if self.fail_silently:
+                    return
+                raise
+        finally:
+            self.connection = None
+
+    def send_messages(self, email_messages):
+        """
+        Send one or more EmailMessage objects and return the number of email
+        messages sent.
+        """
+
+        if not email_messages:
+            return
+        self.open()
+        num_sent = 0
+        for message in email_messages:
+            sent = self._send(message)
+            if sent:
+                num_sent += 1
+        self.close()
+        return num_sent
+
+    def _send(self, email_message):
+        """A helper method that does the actual sending."""
+
+        if not email_message.to:
+            return False
+        msg = SafeMIMEText(email_message.body, 'plain',
+                           settings.DEFAULT_CHARSET)
+        msg['Subject'] = email_message.subject
+        msg['From'] = email_message.from_email
+        msg['To'] = ', '.join(email_message.to)
+        msg['Date'] = formatdate()
+        msg['Message-ID'] = self._message_id()
+        try:
+            self.connection.sendmail(email_message.from_email,
+                                     email_message.to, msg.as_string())
+        except:
+            if not self.fail_silently:
+                raise
+        return True
+
+    def _message_id(self):
+        """Generate a message ID."""
+
+        # Python 2.3 doesn't have random.getrandbits().
+        try:
+            random_bits = str(random.getrandbits(64))
+        except AttributeError:
+            random_bits = ''.join([random.choice('1234567890') for i in range(19)])
+        return "<%d.%s@%s>" % (time.time(), random_bits, DNS_NAME)
+
+class EmailMessage(object):
+    """
+    A container for email information.
+    """
+
+    def __init__(self, to=None, from_email=None, subject="", body="",
+                 connection=None):
+        self.to = to or []
+        if from_email is None:
+            self.from_email = settings.DEFAULT_FROM_EMAIL
+        self.subject = subject
+        self.body = body
+
+    def send(self, connection=None, fail_silently=False):
+        """Send the email message."""
+
+        connection = connection or EmailConnection(fail_silently=fail_silently)
+        return connection.send_messages([self])
+
 def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None):
     """
     Easy wrapper for sending a single message to a recipient list. All members
@@ -42,11 +157,14 @@
     If auth_user is None, the EMAIL_HOST_USER setting is used.
     If auth_password is None, the EMAIL_HOST_PASSWORD setting is used.
     """
-    if auth_user is None:
-        auth_user = settings.EMAIL_HOST_USER
-    if auth_password is None:
-        auth_password = settings.EMAIL_HOST_PASSWORD
-    return send_mass_mail([[subject, message, from_email, recipient_list]], fail_silently, auth_user, auth_password)
+    connection = EmailConnection(username=auth_user, password=auth_password,
+                                 fail_silently=fail_silently)
+    return EmailMessage(
+        subject=subject,
+        body=message,
+        from_email=from_email,
+        to=recipient_list,
+    ).send(connection=connection)
 
 def send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None):
     """
@@ -58,51 +176,33 @@
     If auth_user is None, the EMAIL_HOST_USER setting is used.
     If auth_password is None, the EMAIL_HOST_PASSWORD setting is used.
     """
-    if auth_user is None:
-        auth_user = settings.EMAIL_HOST_USER
-    if auth_password is None:
-        auth_password = settings.EMAIL_HOST_PASSWORD
-    try:
-        server = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT)
-        if auth_user and auth_password:
-            server.login(auth_user, auth_password)
-    except:
-        if fail_silently:
-            return
-        raise
-    num_sent = 0
-    for subject, message, from_email, recipient_list in datatuple:
-        if not recipient_list:
-            continue
-        from_email = from_email or settings.DEFAULT_FROM_EMAIL
-        msg = SafeMIMEText(message, 'plain', settings.DEFAULT_CHARSET)
-        msg['Subject'] = subject
-        msg['From'] = from_email
-        msg['To'] = ', '.join(recipient_list)
-        msg['Date'] = formatdate()
-        try:
-            random_bits = str(random.getrandbits(64))
-        except AttributeError: # Python 2.3 doesn't have random.getrandbits().
-            random_bits = ''.join([random.choice('1234567890') for i in range(19)])
-        msg['Message-ID'] = "<%d.%s@%s>" % (time.time(), random_bits, DNS_NAME)
-        try:
-            server.sendmail(from_email, recipient_list, msg.as_string())
-            num_sent += 1
-        except:
-            if not fail_silently:
-                raise
-    try:
-        server.quit()
-    except:
-        if fail_silently:
-            return
-        raise
-    return num_sent
+    connection = EmailConnection(username=auth_user, password=auth_password,
+                                 fail_silently=fail_silently)
+    messages = [EmailMessage(
+                   subject=subject,
+                   body=message,
+                   from_email=from_email,
+                   to=recipient_list,
+                   ) for subject, message, from_email, recipient_list \
+                     in datatuple]
+    return connection.send_messages(messages)
 
 def mail_admins(subject, message, fail_silently=False):
     "Sends a message to the admins, as defined by the ADMINS setting."
-    send_mail(settings.EMAIL_SUBJECT_PREFIX + subject, message, settings.SERVER_EMAIL, [a[1] for a in settings.ADMINS], fail_silently)
+
+    EmailMessage(
+        subject=settings.EMAIL_SUBJECT_PREFIX + subject,
+        body=message,
+        from_email=settings.SERVER_EMAIL,
+        to=[a[1] for a in settings.ADMINS],
+    ).send(fail_silently=fail_silently)
 
 def mail_managers(subject, message, fail_silently=False):
     "Sends a message to the managers, as defined by the MANAGERS setting."
-    send_mail(settings.EMAIL_SUBJECT_PREFIX + subject, message, settings.SERVER_EMAIL, [a[1] for a in settings.MANAGERS], fail_silently)
+
+    EmailMessage(
+        subject=settings.EMAIL_SUBJECT_PREFIX + subject,
+        body=message,
+        from_email=settings.SERVER_EMAIL,
+        to=[a[1] for a in settings.MANAGERS],
+    ).send(fail_silently=fail_silently)

