X-Git-Url: https://git.openstreetmap.org./osqa.git/blobdiff_plain/a0d8de9db45ebc5f3c13779df19ffac842b9d96b..0a49c0f0860e251ec73d1b8d3d38be3f67dbbe82:/forum/utils/mail.py diff --git a/forum/utils/mail.py b/forum/utils/mail.py index 8f6ee50..115fc10 100644 --- a/forum/utils/mail.py +++ b/forum/utils/mail.py @@ -1,15 +1,22 @@ import email import socket import os - -from email.mime.multipart import MIMEMultipart -from email.mime.text import MIMEText -from email.mime.image import MIMEImage -from email.header import Header -import email.Charset +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 @@ -17,161 +24,63 @@ from forum.context import application_settings from forum.utils.html2text import HTML2Text from threading import Thread -def send_msg_list(msgs, sender=None): - if len(msgs): - connection = SMTP(str(settings.EMAIL_HOST), str(settings.EMAIL_PORT), - local_hostname=DNS_NAME.get_fqdn()) - - try: - 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)) - - if sender is None: - sender = str(settings.DEFAULT_FROM_EMAIL) - - for email, msg in msgs: - try: - connection.sendmail(sender, [email], msg) - except Exception, e: - pass - try: - connection.quit() - except socket.sslerror: - connection.close() - except Exception, e: - pass - -def html2text(s, ignore_tags=(), indent_width=4, page_width=80): - ignore_tags = [t.lower() for t in ignore_tags] - parser = HTML2Text(ignore_tags, indent_width, page_width) - parser.feed(s) - parser.close() - parser.generate() - return parser.result - -def named(data): - if isinstance(data, (tuple, list)) and len(data) == 2: - return '%s <%s>' % data - - return str(data) - -def create_msg(subject, sender, recipient, html, text, images): - msgRoot = MIMEMultipart('related') - msgRoot['Subject'] = subject - msgRoot['From'] = named(sender) - msgRoot['To'] = named(recipient) - msgRoot.preamble = 'This is a multi-part message from %s.' % unicode(settings.APP_SHORT_NAME).encode('utf8') - - msgAlternative = MIMEMultipart('alternative') - msgRoot.attach(msgAlternative) +def send_template_email(recipients, template, context, sender=None): + t = loader.get_template(template) + context.update(dict(recipients=recipients, settings=settings, sender=sender)) + t.render(Context(context)) - msgAlternative.attach(MIMEText(text, _charset='utf-8')) - msgAlternative.attach(MIMEText(html, 'html', _charset='utf-8')) +def create_connection(): + connection = SMTP(str(settings.EMAIL_HOST), str(settings.EMAIL_PORT), + local_hostname=DNS_NAME.get_fqdn()) - for img in images: - try: - fp = open(img[0], 'rb') - msgImage = MIMEImage(fp.read()) - fp.close() - msgImage.add_header('Content-ID', '<'+img[1]+'>') - msgRoot.attach(msgImage) - except: - pass + if bool(settings.EMAIL_USE_TLS): + connection.ehlo() + connection.starttls() + connection.ehlo() - return msgRoot.as_string() - -def send_email(subject, recipients, template, context={}, sender=None, images=[], threaded=True): - if sender is None: - sender = (unicode(settings.APP_SHORT_NAME), unicode(settings.DEFAULT_FROM_EMAIL)) - - if not len(images): - images = [(os.path.join(str(settings.UPFILES_FOLDER), os.path.basename(str(settings.APP_LOGO))), 'logo')] - - context.update(application_settings(None)) - html_body = loader.get_template(template).render(Context(context)) - txt_body = html2text(html_body) - - if isinstance(recipients, str): - recipients = [recipients] - - msgs = [] - - for recipient in recipients: - if isinstance(recipient, str): - recipient_data = ('recipient', recipient) - recipient_context = None - elif isinstance(recipient, (list, tuple)) and len(recipient) == 2: - name, email = recipient - recipient_data = (name, email) - recipient_context = None - elif isinstance(recipient, (list, tuple)) and len(recipient) == 3: - name, email, recipient_context = recipient - recipient_data = (name, email) - else: - raise Exception('bad argument for recipients') - - if recipient_context is not None: - recipient_context = Context(recipient_context) - msg_html = Template(html_body).render(recipient_context) - msg_txt = Template(txt_body).render(recipient_context) - else: - msg_html = html_body - msg_txt = txt_body - - msg = create_msg(subject, sender, recipient_data, msg_html, msg_txt, images) - msgs.append((email, msg)) - - if threaded: - thread = Thread(target=send_msg_list, args=[msgs]) - thread.setDaemon(True) - thread.start() - else: - send_msg_list(msgs) + 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 send_template_email(recipients, template, context): - t = loader.get_template(template) - context.update(dict(recipients=recipients, settings=settings)) - t.render(Context(context)) -def create_and_send_mail_messages(messages): +def create_and_send_mail_messages(messages, sender_data=None): 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)) + + if sender_data == None: + sender.append('<%s>' % unicode(settings.DEFAULT_FROM_EMAIL)) + sender = u'%s <%s>' % (unicode(settings.APP_SHORT_NAME), unicode(settings.DEFAULT_FROM_EMAIL)) + else: + sender.append('<%s>' % unicode(sender_data['email'])) + sender = u'%s <%s>' % (unicode(sender_data['name']), unicode(sender_data['email'])) + + + reply_to = unicode(settings.DEFAULT_REPLY_TO_EMAIL) try: - 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)) + 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) + to = Header(u"%s <%s>" % (recipient.username, recipient.email), 'utf-8') 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') @@ -189,12 +98,22 @@ def create_and_send_mail_messages(messages): try: connection.sendmail(sender, [recipient.email], msgRoot.as_string()) + except SMTPRecipientsRefused, e: + logging.error("Email address not accepted. Exception: %s" % e) except Exception, e: - pass + 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: - pass + logging.error('Email sending has failed: %s' % e)