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