Ticket #1090: 0001-FEATURE-Use-the-python-email-module.patch
File 0001-FEATURE-Use-the-python-email-module.patch, 7.9 KB (added by pedersen, 2 years ago) |
---|
-
indico/MaKaC/common/mail.py
From 441ad80ed4d0786622a44a9fcb33a2c415fb2345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Pedersen?= <bjoern.pedersen@frm2.tum.de> Date: Wed, 19 Sep 2012 10:48:50 +0200 Subject: [PATCH 1/4] [FEATURE] Use the python email module Use the python email module to generate emails not only as plain text, but as MIME with attachments and HTML as well. Attachment definition is still a bit rough, but currently for non-text types a file path has to be used. --- indico/MaKaC/common/mail.py | 93 ++++++++++++++++++++-- .../MaKaC/webinterface/common/baseNotificator.py | 3 + indico/MaKaC/webinterface/mail.py | 35 ++++++-- 3 files changed, 119 insertions(+), 12 deletions(-) diff --git a/indico/MaKaC/common/mail.py b/indico/MaKaC/common/mail.py index bf64cde..ffe0f13 100644
a b 19 19 20 20 import smtplib 21 21 from email.utils import formatdate 22 from email import encoders 23 from email.message import Message 24 from email.mime.audio import MIMEAudio 25 from email.mime.base import MIMEBase 26 from email.mime.image import MIMEImage 27 from email.mime.multipart import MIMEMultipart 28 from email.mime.text import MIMEText 29 from email.header import Header 30 from email.charset import add_charset 31 from email import Charset 32 # don#t encode utf-8 as base64, use quoted-printable! 33 # as this sets a module global, needs to be done only once 34 add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8') 35 36 22 37 23 38 from MaKaC.common import Config 24 39 from MaKaC.errors import MaKaCError … … class GenericMailer: 59 74 60 75 @staticmethod 61 76 def _prepare(notification): 77 COMMASPACE = " ," 62 78 fromAddr=notification.getFromAddr() 63 79 # what are these two loops for?? 64 80 for to in notification.getToList() : … … class GenericMailer: 68 84 if len(cc) == 0 : 69 85 notification.getCCList().remove(cc) 70 86 71 to =", ".join(notification.getToList())72 cc =""87 to = COMMASPACE.join(notification.getToList()) 88 cc = "" 73 89 if len(notification.getCCList())>0: 74 cc ="Cc: %s\r\n"%", ".join(notification.getCCList())90 cc = COMMASPACE.join(notification.getCCList()) 75 91 if not to and not cc: 76 92 return 77 93 … … class GenericMailer: 81 97 ct = "text/plain" 82 98 subject=notification.getSubject() 83 99 body=notification.getBody() 84 msg="""Content-Type: %s; charset=\"utf-8\"\r\nFrom: %s\r\nTo: %s\r\n%sSubject: %s\r\nDate: %s\r\n\r\n%s"""%(ct, fromAddr,\ 85 to,cc,subject,formatdate(localtime=True),body) 100 try: 101 bodyHTML=notification.getBodyHTML() 102 except AttributeError: 103 bodyHTML = None 104 try: 105 attachments = notification.getAttachments() 106 except AttributeError: 107 attachments = None 108 109 110 target = None 111 if attachments: 112 outer = MIMEMultipart() 113 elif bodyHTML: 114 outer = MIMEMultipart('alternative') 115 target = outer 116 else: 117 outer = MIMEText(body, 'plain','utf-8') 118 target = outer 119 120 if bodyHTML: 121 msg = target or MIMEMultipart('alternative') 122 part1HTML = MIMEText(bodyHTML, 'html','utf-8') 123 part1Plain = MIMEText(body, 'plain', 'utf-8') 124 # Attach parts into message container. 125 # According to RFC 2046, the last part of a multipart message, in this case 126 # the HTML message, is best and preferred. 127 msg.attach(part1Plain) 128 msg.attach(part1HTML) 129 else: 130 msg = target or MIMEText(body, 'plain','utf-8') 131 132 outer['Subject'] = Header(subject,'utf-8') 133 outer['To'] = to 134 outer['CC'] = cc 135 outer['From'] = fromAddr 136 137 if outer != msg: 138 outer.attach(msg) 139 140 #add iteration over attachments 141 #for text type, the content should be the payload string, 142 #for all other types the content should be the path to a (possibly temporary) file 143 if attachments: 144 for ctype, vpath, content in attachments: 145 146 maintype, subtype = ctype.split('/', 1) 147 if maintype == 'text': 148 # Note: we should handle calculating the charset 149 msg = MIMEText(content , _subtype=subtype) 150 elif maintype == 'image': 151 with open(content, 'rb') as fp: 152 msg = MIMEImage(fp.read(), _subtype=subtype) 153 elif maintype == 'audio': 154 with open(content, 'rb') as fp: 155 msg = MIMEAudio(fp.read(), _subtype=subtype) 156 else: 157 with open(content, 'rb') as fp: 158 msg = MIMEBase(maintype, subtype) 159 msg.set_payload(fp.read()) 160 # Encode the payload using Base64 161 encoders.encode_base64(msg) 162 # Set the filename parameter 163 msg.add_header('Content-Disposition', 'attachment', filename=vpath) 164 outer.attach(msg) 165 166 86 167 toList = notification.getToList() 87 168 ccList = notification.getCCList() 88 169 if hasattr(notification, 'getBCCList'): … … class GenericMailer: 90 171 else: 91 172 bccList = [] 92 173 return { 93 'msg': msg,174 'msg': outer.as_string(True), 94 175 'toList': toList, 95 176 'ccList': ccList, 96 177 'bccList': bccList, -
indico/MaKaC/webinterface/common/baseNotificator.py
diff --git a/indico/MaKaC/webinterface/common/baseNotificator.py b/indico/MaKaC/webinterface/common/baseNotificator.py index ba574c1..4926fff 100644
a b class Notification: 58 58 def getBody(self): 59 59 return self._body 60 60 61 def getBodyHTML(self): 62 return None 63 61 64 def setToList(self,newList): 62 65 self._toList=[] 63 66 for to in newList: -
indico/MaKaC/webinterface/mail.py
diff --git a/indico/MaKaC/webinterface/mail.py b/indico/MaKaC/webinterface/mail.py index 06c026c..f78fedb 100644
a b class GenericNotification : 60 60 self._bccList = [] 61 61 self._subject = "" 62 62 self._body = "" 63 self.bodyHTML = "" 63 64 self._contenttype = "text/plain" 65 self._attachments = [] 64 66 else : 65 self._fromAddr = data.get("fromAddr", 66 self._toList = data.get("toList", 67 self._ccList = data.get("ccList", 67 self._fromAddr = data.get("fromAddr","") 68 self._toList = data.get("toList",[]) 69 self._ccList = data.get("ccList",[]) 68 70 self._bccList = data.get("bccList", []) 69 self._subject = data.get("subject", "") 70 self._body = data.get("body", "") 71 self._contenttype = data.get("content-type", "text/plain") 71 self._subject = data.get("subject","") 72 self._body = data.get("body","") 73 self._bodyHTML = data.get("bodyHTML","") 74 self._attachments = data.get("attachments",[]) 75 defaultContentType = "text/html" if self._bodyHTML else "text/plain" 76 self._contenttype = data.get("content-type",defaultContentType) 72 77 73 78 def getContentType(self): 74 79 return self._contenttype … … class GenericNotification : 130 135 self._body = body 131 136 return True 132 137 138 def getBodyHTML(self): 139 return self._bodyHTML 140 141 def setBodyHTML(self, bodyHTML): 142 if bodyHTML is None : 143 return False 144 self._bodyHTML = bodyHTML 145 return True 146 147 def getAttachments(self): 148 return self._bodyHTML 149 150 def setAttachments(self, attachments): 151 if attachments is None : 152 return False 153 self._attachments = attachments 154 return True 155 133 156 134 157 class Mailer: 135 158