]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/utils/mail.py
Adds an option to set a reply-to address on emails
[osqa.git] / forum / utils / mail.py
index 1dc2209f81b21e87dc8ea095ca4ca9dcea9ef470..cecb5b4c240b1961ae119ec4e07e85c47e1e0996 100644 (file)
-import email\r
-import socket\r
-import os\r
-\r
-from email.MIMEMultipart import MIMEMultipart\r
-from email.MIMEText import MIMEText\r
-from email.MIMEImage import MIMEImage\r
-\r
-from django.core.mail import DNS_NAME\r
-from smtplib import SMTP\r
-import email.Charset\r
-from django.conf import settings\r
-from django.template import loader, Context, Template\r
-from forum.utils.html import sanitize_html\r
-from forum.context import application_settings\r
-from forum.utils.html2text import HTML2Text\r
-from threading import Thread\r
-\r
-def send_msg_list(msgs, sender=None):\r
-    if len(msgs):\r
-        connection = SMTP(str(settings.EMAIL_HOST), str(settings.EMAIL_PORT),\r
-                local_hostname=DNS_NAME.get_fqdn())\r
-\r
-        try:\r
-            if (bool(settings.EMAIL_USE_TLS)):\r
-                connection.ehlo()\r
-                connection.starttls()\r
-                connection.ehlo()\r
-\r
-            if settings.EMAIL_HOST_USER and settings.EMAIL_HOST_PASSWORD:\r
-                connection.login(str(settings.EMAIL_HOST_USER), str(settings.EMAIL_HOST_PASSWORD))\r
-\r
-            if sender is None:\r
-                sender = str(settings.DEFAULT_FROM_EMAIL)\r
-\r
-            for email, msg in msgs:\r
-                try:\r
-                    connection.sendmail(sender, [email], msg)\r
-                except Exception, e:\r
-                    pass\r
-            try:\r
-                connection.quit()\r
-            except socket.sslerror:\r
-                connection.close()\r
-        except Exception, e:\r
-            pass\r
-\r
-def html2text(s, ignore_tags=(), indent_width=4, page_width=80):\r
-    ignore_tags = [t.lower() for t in ignore_tags]\r
-    parser = HTML2Text(ignore_tags, indent_width, page_width)\r
-    parser.feed(s)\r
-    parser.close()\r
-    parser.generate()\r
-    return parser.result\r
-\r
-def named(data):\r
-    if isinstance(data, (tuple, list)) and len(data) == 2:\r
-        return '%s <%s>' % data\r
-\r
-    return str(data)\r
-\r
-def create_msg(subject, sender, recipient, html, text, images):\r
-    msgRoot = MIMEMultipart('related')\r
-    msgRoot['Subject'] = subject\r
-    msgRoot['From'] = named(sender)\r
-    msgRoot['To'] =  named(recipient)\r
-    msgRoot.preamble = 'This is a multi-part message from %s.' % str(settings.APP_SHORT_NAME)\r
-\r
-    msgAlternative = MIMEMultipart('alternative')\r
-    msgRoot.attach(msgAlternative)\r
-\r
-    msgAlternative.attach(MIMEText(text, _charset='utf-8'))\r
-    msgAlternative.attach(MIMEText(html, 'html', _charset='utf-8'))\r
-\r
-    for img in images:\r
-        try:\r
-            fp = open(img[0], 'rb')\r
-            msgImage = MIMEImage(fp.read())\r
-            fp.close()\r
-            msgImage.add_header('Content-ID', '<'+img[1]+'>')\r
-            msgRoot.attach(msgImage)\r
-        except:\r
-            pass\r
-\r
-    return msgRoot.as_string()\r
-\r
-def send_email(subject, recipients, template, context={}, sender=None, images=[], threaded=True):\r
-    if sender is None:\r
-        sender = (str(settings.APP_SHORT_NAME), str(settings.DEFAULT_FROM_EMAIL))\r
-\r
-    if not len(images):\r
-        images = [(os.path.join(str(settings.UPFILES_FOLDER), os.path.basename(str(settings.APP_LOGO))), 'logo')]\r
-\r
-    context.update(application_settings(None))\r
-    html_body = loader.get_template(template).render(Context(context))\r
-    txt_body = html2text(html_body)\r
-\r
-    if isinstance(recipients, str):\r
-        recipients = [recipients]\r
-\r
-    msgs = []\r
-\r
-    for recipient in recipients:\r
-        if isinstance(recipient, str):\r
-            recipient_data = ('recipient', recipient)\r
-            recipient_context = None\r
-        elif isinstance(recipient, (list, tuple)) and len(recipient) == 2:\r
-            name, email = recipient\r
-            recipient_data = (name, email)\r
-            recipient_context = None\r
-        elif isinstance(recipient, (list, tuple)) and len(recipient) == 3:\r
-            name, email, recipient_context = recipient\r
-            recipient_data = (name, email)\r
-        else:\r
-            raise Exception('bad argument for recipients')\r
-\r
-        if recipient_context is not None:\r
-            recipient_context = Context(recipient_context)\r
-            msg_html = Template(html_body).render(recipient_context)\r
-            msg_txt = Template(txt_body).render(recipient_context)\r
-        else:\r
-            msg_html = html_body\r
-            msg_txt = txt_body\r
-\r
-        msg = create_msg(subject, sender, recipient_data, msg_html, msg_txt, images)\r
-        msgs.append((email, msg))\r
-\r
-    if threaded:\r
-        thread = Thread(target=send_msg_list,  args=[msgs])\r
-        thread.setDaemon(True)\r
-        thread.start()\r
-    else:\r
-        send_msg_list(msgs)
\ No newline at end of file
+import email
+import socket
+import os
+import logging
+
+try:
+    from email.mime.multipart import MIMEMultipart
+    from email.mime.text import MIMEText
+    from email.mime.image import MIMEImage
+    from email.header import Header
+except:
+    from email.MIMEMultipart import MIMEMultipart
+    from email.MIMEText import MIMEText
+    from email.MIMEImage import MIMEImage
+    from email.Header import Header
+
+from django.core.mail import DNS_NAME
+from smtplib import SMTP
+from smtplib import SMTPRecipientsRefused
+from forum import settings
+from django.template import loader, Context, Template
+from forum.utils.html import sanitize_html
+from forum.context import application_settings
+from forum.utils.html2text import HTML2Text
+from threading import Thread
+
+def send_template_email(recipients, template, context):
+    t = loader.get_template(template)
+    context.update(dict(recipients=recipients, settings=settings))
+    t.render(Context(context))
+
+def create_connection():
+    connection = SMTP(str(settings.EMAIL_HOST), str(settings.EMAIL_PORT),
+                          local_hostname=DNS_NAME.get_fqdn())
+
+    if (bool(settings.EMAIL_USE_TLS)):
+        connection.ehlo()
+        connection.starttls()
+        connection.ehlo()
+
+    if settings.EMAIL_HOST_USER and settings.EMAIL_HOST_PASSWORD:
+        connection.login(str(settings.EMAIL_HOST_USER), str(settings.EMAIL_HOST_PASSWORD))
+
+    return connection
+
+
+def create_and_send_mail_messages(messages):
+    if not settings.EMAIL_HOST:
+        return
+
+    sender = Header(unicode(settings.APP_SHORT_NAME), 'utf-8')
+    sender.append('<%s>' % unicode(settings.DEFAULT_FROM_EMAIL))
+    sender = u'%s <%s>' % (unicode(settings.APP_SHORT_NAME), unicode(settings.DEFAULT_FROM_EMAIL))
+
+    reply_to = unicode(settings.DEFAULT_REPLY_TO_EMAIL)
+
+    try:
+        connection = None
+
+        if sender is None:
+            sender = str(settings.DEFAULT_FROM_EMAIL)
+
+        for recipient, subject, html, text, media in messages:
+            if connection is None:
+                connection = create_connection()
+
+            msgRoot = MIMEMultipart('related')
+
+            msgRoot['Subject'] = Header(subject, 'utf-8')
+            msgRoot['From'] = sender
+
+            to = Header(recipient.username, 'utf-8')
+            to.append('<%s>' % recipient.email)
+            msgRoot['To'] = to
+
+            if reply_to:
+                msgRoot['Reply-To'] = reply_to
+
+            msgRoot.preamble = 'This is a multi-part message from %s.' % unicode(settings.APP_SHORT_NAME).encode('utf8')
+
+            msgAlternative = MIMEMultipart('alternative')
+            msgRoot.attach(msgAlternative)
+
+            msgAlternative.attach(MIMEText(text.encode('utf-8'), _charset='utf-8'))
+            msgAlternative.attach(MIMEText(html.encode('utf-8'), 'html', _charset='utf-8'))
+
+            for alias, location in media.items():
+                fp = open(location, 'rb')
+                msgImage = MIMEImage(fp.read())
+                fp.close()
+                msgImage.add_header('Content-ID', '<'+alias+'>')
+                msgRoot.attach(msgImage)
+
+            try:
+                connection.sendmail(sender, [recipient.email], msgRoot.as_string())
+            except SMTPRecipientsRefused, e:
+                logging.error("Email address not accepted.  Exception: %s" % e)
+            except Exception, e:
+                logging.error("Couldn't send mail using the sendmail method: %s" % e)
+                try:
+                    connection.quit()
+                except Exception, e:
+                    logging.error(e)
+                finally:
+                    connection = None
+
+        try:
+            connection.quit()
+        except AttributeError:
+            pass
+        except socket.sslerror:
+            connection.close()
+    except Exception, e:
+        logging.error('Email sending has failed: %s' % e)