]> git.openstreetmap.org Git - osqa.git/blob - forum/utils/mail.py
Some more improvements on the notifications, and applied two patches contributed...
[osqa.git] / forum / utils / mail.py
1 import email
2 import socket
3 import os
4
5 from email.mime.multipart import MIMEMultipart
6 from email.mime.text import MIMEText
7 from email.mime.image import MIMEImage
8
9 from django.core.mail import DNS_NAME
10 from smtplib import SMTP
11 import email.Charset
12 from forum import settings
13 from django.template import loader, Context, Template
14 from forum.utils.html import sanitize_html
15 from forum.context import application_settings
16 from forum.utils.html2text import HTML2Text
17 from threading import Thread
18
19 def send_msg_list(msgs, sender=None):
20     if len(msgs):
21         connection = SMTP(str(settings.EMAIL_HOST), str(settings.EMAIL_PORT),
22                 local_hostname=DNS_NAME.get_fqdn())
23
24         try:
25             if (bool(settings.EMAIL_USE_TLS)):
26                 connection.ehlo()
27                 connection.starttls()
28                 connection.ehlo()
29
30             if settings.EMAIL_HOST_USER and settings.EMAIL_HOST_PASSWORD:
31                 connection.login(str(settings.EMAIL_HOST_USER), str(settings.EMAIL_HOST_PASSWORD))
32
33             if sender is None:
34                 sender = str(settings.DEFAULT_FROM_EMAIL)
35
36             for email, msg in msgs:
37                 try:
38                     connection.sendmail(sender, [email], msg)
39                 except Exception, e:
40                     pass
41             try:
42                 connection.quit()
43             except socket.sslerror:
44                 connection.close()
45         except Exception, e:
46             pass
47
48 def html2text(s, ignore_tags=(), indent_width=4, page_width=80):
49     ignore_tags = [t.lower() for t in ignore_tags]
50     parser = HTML2Text(ignore_tags, indent_width, page_width)
51     parser.feed(s)
52     parser.close()
53     parser.generate()
54     return parser.result
55
56 def named(data):
57     if isinstance(data, (tuple, list)) and len(data) == 2:
58         return '%s <%s>' % data
59
60     return str(data)
61
62 def create_msg(subject, sender, recipient, html, text, images):
63     msgRoot = MIMEMultipart('related')
64     msgRoot['Subject'] = subject
65     msgRoot['From'] = named(sender)
66     msgRoot['To'] =  named(recipient)
67     msgRoot.preamble = 'This is a multi-part message from %s.' % unicode(settings.APP_SHORT_NAME).encode('utf8')
68
69     msgAlternative = MIMEMultipart('alternative')
70     msgRoot.attach(msgAlternative)
71
72     msgAlternative.attach(MIMEText(text, _charset='utf-8'))
73     msgAlternative.attach(MIMEText(html, 'html', _charset='utf-8'))
74
75     for img in images:
76         try:
77             fp = open(img[0], 'rb')
78             msgImage = MIMEImage(fp.read())
79             fp.close()
80             msgImage.add_header('Content-ID', '<'+img[1]+'>')
81             msgRoot.attach(msgImage)
82         except:
83             pass
84
85     return msgRoot.as_string()
86
87 def send_email(subject, recipients, template, context={}, sender=None, images=[], threaded=True):
88     if sender is None:
89         sender = (unicode(settings.APP_SHORT_NAME), unicode(settings.DEFAULT_FROM_EMAIL))
90
91     if not len(images):
92         images = [(os.path.join(str(settings.UPFILES_FOLDER), os.path.basename(str(settings.APP_LOGO))), 'logo')]
93
94     context.update(application_settings(None))
95     html_body = loader.get_template(template).render(Context(context))
96     txt_body = html2text(html_body)
97
98     if isinstance(recipients, str):
99         recipients = [recipients]
100
101     msgs = []
102
103     for recipient in recipients:
104         if isinstance(recipient, str):
105             recipient_data = ('recipient', recipient)
106             recipient_context = None
107         elif isinstance(recipient, (list, tuple)) and len(recipient) == 2:
108             name, email = recipient
109             recipient_data = (name, email)
110             recipient_context = None
111         elif isinstance(recipient, (list, tuple)) and len(recipient) == 3:
112             name, email, recipient_context = recipient
113             recipient_data = (name, email)
114         else:
115             raise Exception('bad argument for recipients')
116
117         if recipient_context is not None:
118             recipient_context = Context(recipient_context)
119             msg_html = Template(html_body).render(recipient_context)
120             msg_txt = Template(txt_body).render(recipient_context)
121         else:
122             msg_html = html_body
123             msg_txt = txt_body
124
125         msg = create_msg(subject, sender, recipient_data, msg_html, msg_txt, images)
126         msgs.append((email, msg))
127
128     if threaded:
129         thread = Thread(target=send_msg_list,  args=[msgs])
130         thread.setDaemon(True)
131         thread.start()
132     else:
133         send_msg_list(msgs)
134
135
136 def send_template_email(recipients, template, context):
137     t = loader.get_template(template)
138     context.update(dict(recipients=recipients, settings=settings))
139     t.render(Context(context))
140
141 def create_and_send_mail_messages(messages):
142     sender = '%s <%s>' % (unicode(settings.APP_SHORT_NAME), unicode(settings.DEFAULT_FROM_EMAIL))
143
144     connection = SMTP(str(settings.EMAIL_HOST), str(settings.EMAIL_PORT),
145                 local_hostname=DNS_NAME.get_fqdn())
146
147     try:
148         if (bool(settings.EMAIL_USE_TLS)):
149             connection.ehlo()
150             connection.starttls()
151             connection.ehlo()
152
153         if settings.EMAIL_HOST_USER and settings.EMAIL_HOST_PASSWORD:
154             connection.login(str(settings.EMAIL_HOST_USER), str(settings.EMAIL_HOST_PASSWORD))
155
156         if sender is None:
157             sender = str(settings.DEFAULT_FROM_EMAIL)
158
159         for recipient, subject, html, text, media in messages:
160             msgRoot = MIMEMultipart('related')
161             msgRoot.set_charset('utf-8')
162             msgRoot['Subject'] = subject
163             msgRoot['From'] = sender
164             msgRoot['To'] =  '%s <%s>' % (recipient.username, recipient.email)
165             msgRoot.preamble = 'This is a multi-part message from %s.' % unicode(settings.APP_SHORT_NAME).encode('utf8')
166
167             msgAlternative = MIMEMultipart('alternative')
168             msgRoot.attach(msgAlternative)
169
170             msgAlternative.attach(MIMEText(text))
171             msgAlternative.attach(MIMEText(html, 'html'))
172
173             for alias, location in media.items():
174                 fp = open(location, 'rb')
175                 msgImage = MIMEImage(fp.read())
176                 fp.close()
177                 msgImage.add_header('Content-ID', '<'+alias+'>')
178                 msgRoot.attach(msgImage)
179
180             try:
181                 connection.sendmail(sender, [recipient.email], msgRoot.as_string())
182             except Exception, e:
183                 pass
184
185         try:
186             connection.quit()
187         except socket.sslerror:
188             connection.close()
189     except:
190         pass