X-Git-Url: https://git.openstreetmap.org./osqa.git/blobdiff_plain/07fe485fb0a119fb87f8ec948185b5acdd65300e..e25a52bd2e384683c99b6e57647b829dba3bf5a2:/forum/utils/mail.py diff --git a/forum/utils/mail.py b/forum/utils/mail.py index 4d11f85..4ab2a69 100644 --- a/forum/utils/mail.py +++ b/forum/utils/mail.py @@ -1,133 +1,114 @@ -import email -import socket -import os - -from email.MIMEMultipart import MIMEMultipart -from email.MIMEText import MIMEText -from email.MIMEImage import MIMEImage - -from django.core.mail import DNS_NAME -from smtplib import SMTP -import email.Charset -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_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) - - msgAlternative.attach(MIMEText(text, _charset='utf-8')) - msgAlternative.attach(MIMEText(html, 'html', _charset='utf-8')) - - 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 - - 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) \ 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)