Skip to content

Commit afe3676

Browse files
committed
Teach send_simple_mail about sending HTML email
If a HTML body is specified, the plaintext and html bodies will be sent as a multipart/alternative MIME object. Also teach it to add attachments with Content-ID and overriding the Content-Disposition, to make it possible to reference images attached using cid: type URLs.
1 parent 4e71d1a commit afe3676

File tree

1 file changed

+27
-7
lines changed

1 file changed

+27
-7
lines changed

pgweb/mailqueue/util.py

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from email.mime.nonmultipart import MIMENonMultipart
44
from email.utils import formatdate, formataddr
55
from email.utils import make_msgid
6-
from email import encoders
6+
from email import encoders, charset
77
from email.header import Header
88

99
from .models import QueuedMail
@@ -15,7 +15,14 @@ def _encoded_email_header(name, email):
1515
return email
1616

1717

18-
def send_simple_mail(sender, receiver, subject, msgtxt, attachments=None, usergenerated=False, cc=None, replyto=None, sendername=None, receivername=None, messageid=None, suppress_auto_replies=True, is_auto_reply=False):
18+
# Default for utf-8 in python is to encode subject with "shortest" and body with "base64". For our texts,
19+
# make it always quoted printable, for easier reading and testing.
20+
_utf8_charset = charset.Charset('utf-8')
21+
_utf8_charset.header_encoding = charset.QP
22+
_utf8_charset.body_encoding = charset.QP
23+
24+
25+
def send_simple_mail(sender, receiver, subject, msgtxt, attachments=None, usergenerated=False, cc=None, replyto=None, sendername=None, receivername=None, messageid=None, suppress_auto_replies=True, is_auto_reply=False, htmlbody=None, headers={}):
1926
# attachment format, each is a tuple of (name, mimetype,contents)
2027
# content should be *binary* and not base64 encoded, since we need to
2128
# use the base64 routines from the email library to get a properly
@@ -44,14 +51,27 @@ def send_simple_mail(sender, receiver, subject, msgtxt, attachments=None, userge
4451
elif not usergenerated:
4552
msg['Auto-Submitted'] = 'auto-generated'
4653

47-
msg.attach(MIMEText(msgtxt, _charset='utf-8'))
54+
for h in headers.keys():
55+
msg[h] = headers[h]
56+
57+
if htmlbody:
58+
mpart = MIMEMultipart("alternative")
59+
mpart.attach(MIMEText(msgtxt, _charset=_utf8_charset))
60+
mpart.attach(MIMEText(htmlbody, 'html', _charset=_utf8_charset))
61+
msg.attach(mpart)
62+
else:
63+
# Just a plaintext body, so append it directly
64+
msg.attach(MIMEText(msgtxt, _charset='utf-8'))
4865

4966
if attachments:
50-
for filename, contenttype, content in attachments:
51-
main, sub = contenttype.split('/')
67+
for a in attachments:
68+
main, sub = a['contenttype'].split('/')
5269
part = MIMENonMultipart(main, sub)
53-
part.set_payload(content)
54-
part.add_header('Content-Disposition', 'attachment; filename="%s"' % filename)
70+
part.set_payload(a['content'])
71+
part.add_header('Content-Disposition', a.get('disposition', 'attachment; filename="%s"' % a['filename']))
72+
if 'id' in a:
73+
part.add_header('Content-ID', a['id'])
74+
5575
encoders.encode_base64(part)
5676
msg.attach(part)
5777

0 commit comments

Comments
 (0)