def getAttachments(msg,attachmentDirPath): for filename in os.listdir(attachmentDirPath): path = os.path.join(attachmentDirPath, filename) if not os.path.isfile(path): continue contentType, encoding = mimetypes.guess_type(path) if contentType is None or encoding is not None: contentType = 'application/octet-stream' mainType, subType = contentType.split('/', 1) fp = open(path, 'rb') if mainType == 'text': attachment = MIMEText(fp.read()) elif mainType == 'image': attachment = MIMEImage(fp.read(),_subType=subType) elif mainType == 'audio': attachment = MIMEAudio(fp.read(),_subType=subType) else: attachment = MIMEBase(mainType, subType) attachment.set_payload(fp.read()) encode_base64(attachment) fp.close() attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(path)) msg.attach(attachment)
def getAttachment(attachmentFilePath): contentType, encoding = mimetypes.guess_type(attachmentFilePath) if contentType is None or encoding is not None: contentType = 'application/octet-stream' mainType, subType = contentType.split('/', 1) file = open(attachmentFilePath, 'rb') if mainType == 'text': attachment = MIMEText(file.read()) elif mainType == 'message': attachment = email.message_from_file(file) elif mainType == 'image': attachment = MIMEImage(file.read(), _subType=subType) elif mainType == 'audio': attachment = MIMEAudio(file.read(), _subType=subType) else: attachment = MIMEBase(mainType, subType) attachment.set_payload(file.read()) encode_base64(attachment) file.close() ## 设置附件头 attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachmentFilePath)) return attachment
def encodeOptimally(part, exact=True): """Encode a message part as needed. If the part is more than 10% high-bit characters, it will be encoded using base64 encoding. If the contents are 7-bit and exact is False, the part will not be encoded. Otherwise, the message will be encoded as quoted-printable. If quoted-printable encoding is used, exact will cause all line-ending characters to be quoted. :param part: The message part to encode. :param exact: If True, the encoding will ensure newlines are not mangled. If False, 7-bit attachments will not be encoded. """ # If encoding has already been done by virtue of a charset being # previously specified, then do nothing. if 'Content-Transfer-Encoding' in part: return orig_payload = part.get_payload() if not exact and is_ascii_only(orig_payload): return # Payloads which are completely ascii need no encoding. quopri_bytes = b2a_qp(orig_payload, istext=not exact) # If 10% of characters need to be encoded, len is 1.2 times # the original len. If more than 10% need encoding, the result # is unlikely to be readable. if len(quopri_bytes) < len(orig_payload) * 1.2: part.set_payload(quopri_bytes) part['Content-Transfer-Encoding'] = 'quoted-printable' else: encode_base64(part)
def getAttachments(msg, attachmentDirPath): for filename in os.listdir(attachmentDirPath): path = os.path.join(attachmentDirPath, filename) if not os.path.isfile(path): continue contentType, encoding = mimetypes.guess_type(path) if contentType is None or encoding is not None: contentType = 'application/octet-stream' mainType, subType = contentType.split('/', 1) fp = open(path, 'rb') if mainType == 'text': attachment = MIMEText(fp.read()) elif mainType == 'image': attachment = MIMEImage(fp.read(), _subType=subType) elif mainType == 'audio': attachment = MIMEAudio(fp.read(), _subType=subType) else: attachment = MIMEBase(mainType, subType) attachment.set_payload(fp.read()) encode_base64(attachment) fp.close() attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(path)) msg.attach(attachment)
def compose(self, From, To, body, attaches, **headers): from email.MIMEMultipart import MIMEMultipart from email.MIMEText import MIMEText from email.MIMEBase import MIMEBase from email.Encoders import encode_base64 message = MIMEMultipart() message['To'] = formataddr(To, self.charset) message['From'] = formataddr(From, self.charset) self._setHeaders(message, **headers) message.preamble = "Multipart message" message.epilogue = "" body = isinstance(body, unicode) and body.encode(self.charset) or body text = MIMEText(body, _charset=self.charset) message.attach(text) for ctype, filename, fileobj in attaches: maintype, subtype = ctype.split('/', 1) attach = MIMEBase(maintype, subtype) attach.set_payload(fileobj.read()) encode_base64(attach) attach.add_header("Content-Disposition", "attachment", filename=filename) message.attach(attach) return message
def make_attach(path): path = os.path.abspath(path) contentType, encoding = mimetypes.guess_type(path) if contentType is None or encoding is not None: contentType = "application/octet-stream" main_type, sub_type = contentType.split("/", 1) f = open(path, "rb") bytes = f.read() f.close() if main_type == "text": attachment = MIMEText(bytes) elif main_type == "message": attachment = email.message_from_string(bytes) elif main_type == "image": attachment = MIMEImage(bytes, sub_type) attachment.add_header("Content-ID", "".join(("<", os.path.basename(path), ">"))) elif main_type == "audio": print sub_type attachment = MIMEAudio(bytes, sub_type) else: attachment = MIMEBase(main_type, sub_type) attachment.set_payload(bytes) encode_base64(attachment) attachment.add_header("Content-Disposition", "attachment", filename=os.path.basename(path)) return attachment
def _getAttachment(self, attachmentFilePath): contentType, encoding = mimetypes.guess_type(attachmentFilePath) if contentType is None or encoding is not None: contentType = 'application/octet-stream' mainType, subType = contentType.split('/', 1) file = open(attachmentFilePath, 'rb') if mainType == 'text': attachment = MIMEText(file.read()) elif mainType == 'message': attachment = email.message_from_file(file) elif mainType == 'image': attachment = MIMEImage(file.read(),_subType=subType) elif mainType == 'audio': attachment = MIMEAudio(file.read(),_subType=subType) else: attachment = MIMEBase(mainType, subType) attachment.set_payload(file.read()) encode_base64(attachment) file.close() attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachmentFilePath)) return attachment
def attach_mail_file(msg, filename, name): if os.path.exists(filename): fp = open(filename, "rb") to_attach = MIMEBase("application", "octet-stream") to_attach.set_payload(fp.read()) encode_base64(to_attach) to_attach.add_header("Content-Disposition", "attachment", filename=name) fp.close() msg.attach(to_attach)
def makeAttachment(attachedFile, Outfile): ctype = 'application/octet-stream' fileIn = open(attachedFile, 'rb') attachment = MIMEBase('application', 'octet-stream') attachment.set_payload(fileIn.read()) encode_base64(attachment) fileIn.close attachment.add_header('Content-Disposition', 'attachment',filename=Outfile) return attachment
def get_attachment(self, attachment_path): content_type, encoding = mimetypes.guess_type(attachment_path) if content_type is None or encoding is not None: content_type = 'application/octet-stream' main_type, sub_type = content_type.split('/', 1) with open(attachment_path, 'rb') as attachment_file: attachment = MIMEBase(main_type, sub_type) attachment.set_payload(attachment_file.read()) encode_base64(attachment) attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachment_path)) return attachment
def send_email(host, port, sender, password, recipients, subject, body, attachments=None): """Sends an email (optionally with attachments). This function does not return anything. It is not unit tested because it sends an actual email, and thus is difficult to test. This code is largely based on the code found here: http://www.blog.pythonlibrary.org/2010/05/14/how-to-send-email-with-python/ http://segfault.in/2010/12/sending-gmail-from-python/ Taken from Clout's (https://github.com/qiime/clout) util module. Arguments: host - the STMP server to send the email with port - the port number of the SMTP server to connect to sender - the sender email address (i.e. who this message is from). This will be used as the username when logging into the SMTP server password - the password to log into the SMTP server with recipients - a list of email addresses to send the email to subject - the subject of the email body - the body of the email attachments - a list of 2-element tuples, where the first element is the filename that will be used for the email attachment (as the recipient will see it), and the second element is the file to be attached """ msg = MIMEMultipart() msg['From'] = sender msg['To'] = ', '.join(recipients) msg['Subject'] = subject msg['Date'] = formatdate(localtime=True) if attachments is not None: for attachment_name, attachment_f in attachments: part = MIMEBase('application', 'octet-stream') part.set_payload(attachment_f.read()) encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % attachment_name) msg.attach(part) part = MIMEText('text', 'plain') part.set_payload(body) msg.attach(part) server = SMTP(host, port) server.ehlo() server.starttls() server.ehlo server.login(sender, password) server.sendmail(sender, recipients, msg.as_string()) server.quit()
def postProcessMessage(self, message): """Encode message as base64 and set content disposition """ value = self._query() if value is not None: filename = value.filename if filename: message.add_header('Content-Disposition', 'attachment') message.set_param('filename', filename.encode('utf-8'), header='Content-Disposition', charset='utf-8') encode_base64(message)
def send_email(host, port, sender, password, recipients, subject, body, attachments=None): """Sends an email (optionally with attachments). This function does not return anything. It is not unit tested because it sends an actual email, and thus is difficult to test. This code is largely based on the code found here: http://www.blog.pythonlibrary.org/2010/05/14/how-to-send-email-with-python/ http://segfault.in/2010/12/sending-gmail-from-python/ Arguments: host - the STMP server to send the email with port - the port number of the SMTP server to connect to sender - the sender email address (i.e. who this message is from). This will be used as the username when logging into the SMTP server password - the password to log into the SMTP server with recipients - a list of email addresses to send the email to subject - the subject of the email body - the body of the email attachments - a list of 2-element tuples, where the first element is the filename that will be used for the email attachment (as the recipient will see it), and the second element is the file to be attached """ msg = MIMEMultipart() msg['From'] = sender msg['To'] = ', '.join(recipients) msg['Subject'] = subject msg['Date'] = formatdate(localtime=True) if attachments is not None: for attachment_name, attachment_f in attachments: part = MIMEBase('application', 'octet-stream') part.set_payload(attachment_f.read()) encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % attachment_name) msg.attach(part) part = MIMEText('text', 'plain') part.set_payload(body) msg.attach(part) server = SMTP(host, port) server.ehlo() server.starttls() server.ehlo server.login(sender, password) server.sendmail(sender, recipients, msg.as_string()) server.quit()
def postProcessMessage(self, message): """Encode message as base64 and set content disposition """ value = self._query() if value is not None: filename = value.filename if filename: message.add_header('Content-Disposition', 'attachment') message.set_param('filename', filename.encode('utf-8'), header='Content-Disposition', charset='utf-8' ) encode_base64(message)
def emailBackup(messageSubject, messageSender, messageRecipient, zipfilePath): zip = MIMEBase.MIMEBase("application", "zip") zip.set_payload(open(zipfilePath, "rb").read()) encode_base64(zip) zip.add_header("Content-Disposition", "attachment", filename=os.path.basename(zipfile)) message = MIMEMultipart() message["Subject"] = messageSubject message["From"] = messageSender message["To"] = messageRecipient message.attach(zip) s = smtplib.SMTP() s.connect() s.sendmail(messageSender, messageRecipient, message.as_string()) s.close()
def send_email(address, log): # TODO debug it as attachment 0 byte! import smtplib from email.mime.text import MIMEText from email.Encoders import encode_base64 from email.MIMEMultipart import MIMEMultipart SUB_HEAD = 'QA result' FROM = 'qa_sw' MESG = 'Test result' msg = '' with open('/etc/ssmtp/ssmtp.conf', 'rb') as f: while msg.find('AuthUser='******'User='******'AuthPass='******'Pass='******'rb') attachment = MIMEText('test') attachment.set_payload(f.read()) print '+++' print attachment print '+++++' encode_base64(attachment) f.close() attachment.add_header('Content-Disposition','attachment',\ filename=os.path.basename(log)) msg = MIMEMultipart() #MIMEText('QA result') msg['Subject'] = 'proba email' msg['From'] = 'invenshure_qa' msg['To'] = address msg.attach(MIMEText('QA log')) msg.attach(attachment) print msg s = smtplib.SMTP('smtp.gmail.com', 587) s.ehlo() s.starttls() s.ehlo() s.login(guser, passwd) s.sendmail('QA', [address], msg.as_string()) s.quit()
def _construct_attach_(self, msg): # create the MIMEBASE instance and make a attach contype = "application/octet-stream" maintype, subtype = contype.split("/") # read the attach file and format data = open(self.attach) file_msg = MIMEBase(maintype, subtype) file_msg.set_payload(data.read()) data.close() encode_base64(file_msg) # set the title of the attach basename = os.path.basename(self.attach) file_msg.add_header("Content-Disposition", "attachment", filename=basename) msg.attach(file_msg) return msg
def send_mail(to, subject, text, attach): ### if settings.DEBUG: logger.debug(u"\n{}\n{}\n{}\n".format(to, subject, text)) return ### try: msg = MIMEMultipart('related') organization = settings.MAIL_SENDER_ORGANIZATION mailer = settings.MAIL_SENDER_MAILER msg['Message-ID'] = msgid() msg['Organization'] = make_header([(organization, 'UTF-8')]) msg['X-Mailer'] = make_header([(mailer, 'UTF-8')]) msg['From'] = make_header([(mailer, 'UTF-8'), ('<' + settings.MAIL_SENDER_SENDER + '>', 'us-ascii')]) msg['To'] = make_header([(to, 'us-ascii')]) msg['Subject'] = make_header([(subject, 'UTF-8')]) msg.preamble = "This is a multi-part message in MIME format." msg.epilogue = "End of message" # alternative part msgAlternative = MIMEMultipart('alternative') msg.attach(msgAlternative) msgText = MIMEText(text, '', 'utf-8') msgAlternative.attach(msgText) # html part to_attach = MIMEText(text.encode('utf-8'), 'html', 'utf-8') msgAlternative.attach(to_attach) if attach: part = MIMEBase('application', 'octet-stream') part.set_payload(open(attach, 'rb').read()) encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(attach)) msg.attach(part) mailServer = smtplib.SMTP(settings.MAIL_SENDER_SERVER, settings.MAIL_SENDER_PORT) mailServer.ehlo() mailServer.starttls() mailServer.ehlo() mailServer.login(settings.MAIL_SENDER_USER, settings.MAIL_SENDER_PASSWORD) mailServer.sendmail(settings.MAIL_SENDER_SENDER, to, msg.as_string()) # Should be mailServer.quit(), but that crashes... mailServer.close() except Exception as e: logger.error(u'\n\nMessage to "{}" with subject "{}" was not sended\nException message: "{}"\n'.format(to, subject, e.message)) return
def _construct_attach_(self, msg): # create the MIMEBASE instance and make a attach contype = 'application/octet-stream' maintype, subtype = contype.split('/') # read the attach file and format data = open(self.attach, 'rb').read() file_msg = MIMEBase(maintype, subtype) file_msg.set_payload(data) encode_base64(file_msg) # set the title of the attach basename = os.path.basename(self.attach) file_msg.add_header('Content-Disposition', 'attachment', filename=basename) msg.attach(file_msg) return msg
def sendReport(send_to, subject, reportFile, zipFile=""): '''Send a HTML report by mail. send_to is the address of the mail subject is the subject of the mail reportFile is the HTML report sent as body of the mail zipFile is the name of an optional zip file that is attached to the mail The mail is sent from the email address of the user running the function. An error message is printed in case of issues sending the mail. ''' send_from = os.getenv('USER') + "@cisco.com" msg = MIMEMultipart() msg["From"] = send_from msg["To"] = send_to msg["Cc"] = "*****@*****.**" #msg["Bcc"] = "*****@*****.**" msg["Subject"] = subject msg['Date'] = formatdate(localtime=True) body = MIMEText(open(reportFile).read(), 'plain') body['Content-Transfer-Encoding']='quoted-printable' msg.attach(body) if zipFile != "": attachment = MIMEBase('application', 'x-zip-compressed', name=os.path.basename(zipFile)) attachment.set_payload(open(zipFile).read()) encode_base64(attachment) msg.attach(attachment) server = smtplib.SMTP('localhost') try: print "Going to send email from", send_from, " to ", send_to failed = server.sendmail(send_from, [send_to, "*****@*****.**"], msg.as_string()) server.close() except Exception, e: errorMsg = "Unable to send email. Error: %s" % str(e) print errorMsg
def get_attachment(attachment_file_path): content_type, encoding = mimetypes.guess_type(attachment_file_path) if content_type is None or encoding is not None: content_type = 'application/octet-stream' main_type, sub_type = content_type.split('/', 1) file = open(attachment_file_path, 'rb') attachment = MIMEBase(main_type, sub_type) attachment.set_payload(file.read()) encode_base64(attachment) file.close() attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachment_file_path)) return attachment
def add_file(self, theFile=None, data=None, filename=None, content_type=None): "add a Zope file or Image to ourselves as an attachment" if theFile and data is not None: raise TypeError( 'A file-like object was passed as well as data to create a file' ) if (data is None) != (not filename): raise TypeError('Both data and filename must be specified') if data is not None: if content_type is None: content_type, enc = guess_content_type(filename, data) elif isinstance(theFile, File): filename = theFile.getId() data = str(theFile.data) content_type = content_type or theFile.content_type elif isinstance(theFile, file): filename = cookId(theFile.name) data = theFile.read() if content_type is None: content_type, enc = guess_content_type(filename, data) elif isinstance(theFile, FileUpload): filename = cookId(theFile.filename) data = theFile.read() headers = theFile.headers if content_type is None: if 'content-type' in headers: content_type = headers['content-type'] else: content_type, enc = guess_content_type(filename, data) else: raise TypeError('Unknown object type found: %r' % theFile) msg = MIMEBase(*content_type.split('/')) msg.set_payload(data) encode_base64(msg) msg.add_header('Content-ID', '<%s>' % \ ''.join(['%s' % ord(i) for i in filename])) msg.add_header('Content-Disposition', 'attachment', filename=filename) self.attach(msg)
def addFile(self,filePath,fileName): try: mainType,subType=mimetypes.guess_type()[0].split('/') except: mainType="application" subType="None" fd=open(filePath,"rb") if mainType=="text": msgAttr=MIMEText(fd.read()) elif mainType=="image": msgAttr=MIMEImage(fd.read(),subType) elif mainType=="audio": msgAttr=MIMEAudio(fd.read(),subType) else: msgAttr=MIMEBase(mainType,subType) msgAttr.set_payload(fd.read()) encode_base64(msgAttr) msgAttr["Content-Disposition"]="attachment;filename=%s" %fileName.encode('gbk') fd.close() return msgAttr
def addFile(): try: mainType,subType=mimetypes.guess_type(filename)[0].split('/') except: mainType="application" subType="None" fd=open(filename,"rb") if mainType=="text": msgAttr=MIMEText(fd.read()) #elif mainType=="image": # msgAttr=MIMEImage(fd.read(),_subtype=subType) # elif mainType=="audio": # msgAttr=MIMEAudio(fd.read(),_subtype=subType) else: msgAttr=MIMEBase(mainType,subType) msgAttr.set_payload(fd.read()) encode_base64(msgAttr) msgAttr["Content-Disposition"]="attachment;filename=%s" %unicode(os.path.basename(filename),"utf8").encode("gbk") fd.close() return msgAttr
def getAttachment(attachmentFilePath): contentType, encoding = mimetypes.guess_type(attachmentFilePath) if contentType is None or encoding is not None: contentType = "application/octet-stream" mainType, subType = contentType.split("/", 1) file = open(attachmentFilePath, "rb") if mainType == "text": attachment = MIMEText(file.read()) elif mainType == "message": attachment = email.message_from_file(file) elif mainType == "image": attachment = MIMEImage(file.read(), _subType=subType) elif mainType == "audio": attachment = MIMEAudio(file.read(), _subType=subType) else: attachment = MIMEBase(mainType, subType) attachment.set_payload(file.read()) encode_base64(attachment) file.close() attachment.add_header("Content-Disposition", "attachment", filename=os.path.basename(attachmentFilePath)) return attachment
def getAttachment(attachmentFilePath,size): if isinstance(size,str): size=int(size) if not os.path.exists(attachmentFilePath): warn('Attachment path is invalid: '+attachmentFilePath) contentType, encoding = mimetypes.guess_type(attachmentFilePath) print "ContentType:",contentType,"\n encoding:",encoding,"\n path:",attachmentFilePath if contentType is None or encoding is not None: print "Doing the octet stream encoding." contentType = 'application/octet-stream' mainType, subType = contentType.split('/', 1) fp = open(attachmentFilePath, 'rb') if mainType == 'text': attachment = MIMEText(fp.read()) elif mainType == 'message': attachment = email.message_from_file(fp) # these produce an empty attachment" elif mainType == 'image': # this corrupts the image that is ultimately sent out # attachment = MIMEImage(fp.read(),_subType=subType) if size: fp.close() newAttachmentFilePath = resize_image(attachmentFilePath,max_dimension = size) fp = open(newAttachmentFilePath, 'rb') # elif mainType == 'audio': # attachment = MIMEAudio(fp.read(),_subType=subType) attachment = MIMEBase(mainType, subType) else: attachment = MIMEBase(mainType, subType) attachment.set_payload(fp.read()) encode_base64(attachment) fp.close() attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachmentFilePath)) return attachment
def addFile(self, filePath, fileName): try: mainType, subType = mimetypes.guess_type()[0].split('/') except: mainType = "application" subType = "None" fd = open(filePath, "rb") if mainType == "text": msgAttr = MIMEText(fd.read()) elif mainType == "image": msgAttr = MIMEImage(fd.read(), subType) elif mainType == "audio": msgAttr = MIMEAudio(fd.read(), subType) else: msgAttr = MIMEBase(mainType, subType) msgAttr.set_payload(fd.read()) encode_base64(msgAttr) msgAttr[ "Content-Disposition"] = "attachment;filename=%s" % fileName.encode( 'gbk') fd.close() return msgAttr
def send_mail(self): msg = MIMEMultipart() msg['Subject'] = unicode(self.subject) msg['From'] = self.user msg['To'] = ",".join(self.recevier) if self.attachment != None: for i in self.attachment: try: file = open(i, 'rb') except IOError as e: print '%s : not fount'%(i) exit() else: file_msg = MIMEBase('application', 'octet-stream') file_msg.set_payload(file.read( )) encode_base64(file_msg) file_msg.add_header("Content-Disposition","attachment",filename=i) file.close( ) msg.attach(file_msg) if self.imgfile != None: #imglist = '' for i in self.imgfile: try: imgfile = open(i,'rb') except IOError as e: print '%s not fount'%(i) exit() else: img = MIMEImage(imgfile.read()) img.add_header('Content-ID',i) msg.attach(img) msg.attach(MIMEText(self.content,'html',_charset="utf8")) s = smtplib.SMTP(self.server) s.login(self.user,self.password) s.sendmail(self.user,self.recevier,msg.as_string()) s.quit()
def addFile(): try: mainType, subType = mimetypes.guess_type(filename)[0].split('/') except: mainType = "application" subType = "None" fd = open(filename, "rb") if mainType == "text": msgAttr = MIMEText(fd.read()) #elif mainType=="image": # msgAttr=MIMEImage(fd.read(),_subtype=subType) # elif mainType=="audio": # msgAttr=MIMEAudio(fd.read(),_subtype=subType) else: msgAttr = MIMEBase(mainType, subType) msgAttr.set_payload(fd.read()) encode_base64(msgAttr) msgAttr["Content-Disposition"] = "attachment;filename=%s" % unicode( os.path.basename(filename), "utf8").encode("gbk") fd.close() return msgAttr
def getAttachment(path, filename): ctype, encoding = mimetypes.guess_type(path) if ctype is None or encoding is not None: ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) fp = open(path, 'rb') if maintype == 'text': attach = MIMEText(fp.read(),_subtype=subtype) elif maintype == 'message': attach = email.message_from_file(fp) elif maintype == 'image': attach = MIMEImage(fp.read(),_subtype=subtype) elif maintype == 'audio': attach = MIMEAudio(fp.read(),_subtype=subtype) else: print maintype, subtype attach = MIMEBase(maintype, subtype) attach.set_payload(fp.read()) encode_base64(attach) fp.close attach.add_header('Content-Disposition', 'attachment', filename=filename) return attach
def sendMail(subject, text, attachmentFilePath): msg = MIMEMultipart() msg['From'] = gmailUser msg['To'] = recipient msg['Subject'] = subject msg.attach(MIMEText(open(attachmentFilePath,"rb").read(), 'html')) for file in [attachmentFilePath]: part = MIMEBase('application', "octet-stream") print file part.set_payload( open(file,"rb").read() ) encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file)) msg.attach(part) mailServer = smtplib.SMTP('smtp.gmail.com', 587) mailServer.ehlo() mailServer.starttls() mailServer.ehlo() mailServer.login(gmailUser, gmailPassword) mailServer.sendmail(gmailUser, recipient, msg.as_string()) mailServer.close() print('Sent email(%s) to %s' % (subject, recipient))
def send_email(from_address='', to_addresses=None, msg_text='', subject='', attachments=None, logger=log): """ Sends an email to the given address list, with the supplied message text. An optional list of attachments can be provided as well, to keep the main email concise. :param from_address: string containing the email address that the message is sent from. :param to_addresses: list of strings containing destination email addresses, or a string containing one address :param msg_text: A string containing the full text of the message to send. :param subject: A string containing the subject line of the email. :param attachments: A list of (filename, payload, mimetype) tuples, where: -filename is the name the attachment will be saved as on the client, not a local file name. -payload is the entire content of the attachment (a PNG image, zip file, etc) -mimetype is the type string, and defaults to 'text/plain' if omitted from the tuple :param logger: An optional logger object to use for logging messages, instead of the default logger. :return: """ if attachments is None: attachments = [] if not to_addresses: logger.error( 'Must specify a list of email addresses to send the email to.') return False msg = MIMEMultipart() msg['From'] = from_address msg['To'] = ', '.join(to_addresses) msg['Date'] = formatdate(localtime=True) msg['Subject'] = subject msg.attach(MIMEText(msg_text)) for attachspec in attachments: if type(attachspec) != tuple: logger.error( 'attachments must be a tuple of (filename, payload, mimetype), where payload is the file contents.' ) return False try: if len(attachspec) == 2: filename, payload = attachspec if filename.endswith('.xml'): mimetype = 'text/xml' else: mimetype = 'text/plain' else: filename, payload, mimetype = attachspec if mimetype: mimemain, mimesub = mimetype.split('/') else: mimemain = 'text' mimesub = 'plain' except ValueError: logger.error( 'attachments must be a tuple of (filename, payload, mimetype), where payload is the file contents.' ) return False part = MIMEBase(mimemain, mimesub) part.set_payload(payload) encode_base64(part) part.add_header( 'Content-Disposition', 'attachment; filename="%s"' % os.path.basename(filename)) msg.attach(part) smtp = None try: smtp = smtplib.SMTP(MAILHOST) errordict = smtp.sendmail(from_address, to_addresses, msg.as_string()) for destaddress, sending_error in errordict.items(): logger.error('Error sending email to %s: %s' % (destaddress, sending_error)) except smtplib.SMTPException: logger.error('Email could not be sent:') finally: if smtp is not None: smtp.close()
def sendEmail(self, email_address): try: print "[Email client] - Entered a method that sends an Rapp email" smtp = Constants.smtp_service port = int('587') print "[Email client] - Creating an object smtp.SMTP with smtp =",smtp, "and port=",port server= smtplib.SMTP(smtp , port) # Account data email_user = Constants.email_address email_pwd = Constants.email_pswd if len(email_address)!=0: print "[Email client] - An email address is set to %s" %email_address email_to=email_address else: print "[Email client] - An email address is not specified!" email_to = Constants.email_address print "[Email client] - Sending email to %s" %email_to return subject = "[RAPP message] - Nao sending " text_attach = "Sending an email from NAO" audio_nao_attach = Constants.test_recorded_path image_nao_attach=Constants.test_data_path+Constants.test_image_name attach=audio_nao_attach print "[Email client] - path to audio attachments:", audio_nao_attach print "[Email client] - path to image attachments:", image_nao_attach print "[Email client] - preparing content of a message" msg = MIMEMultipart() msg['From'] = email_user msg['To'] = email_to msg['Subject'] = subject print "[Email client] - Attaching files" if attach: # Attaching to a message an Rapp recorded audio print "[Email client] - Attaching audio" part = MIMEBase('application', 'octet-stream') part.set_payload(open(attach, 'rb').read()) print "[Email client] - Encoding audio" encode_base64(part) part.add_header('Content-Disposition','attachment; filename=%s' % os.path.basename(attach)) msg.attach(part) # Attaching to a message an Rapp image print "[Email client] - Attaching image" part = MIMEBase('application', 'octet-stream') part.set_payload(open(image_nao_attach, 'rb').read()) print "[Email client] - Encoding image" encode_base64(part) part.add_header('Content-Disposition','attachment; filename="%s"' % os.path.basename(image_nao_attach)) msg.attach(part) # Attaching to a message a body part = MIMEText(text_attach, 'plain') msg.attach(part) if( port != "" ): mailServer = smtplib.SMTP(smtp, port) else: mailServer = smtplib.SMTP(smtp) print "[Send Email] - logging into a server" mailServer.ehlo() mailServer.starttls() mailServer.ehlo() mailServer.login(email_user, email_pwd) print "[Send Email] - sending an email" mailServer.sendmail(email_user, email_to,msg.as_string()) mailServer.close() return 1 except Exception, e: print "[Send Email] - Exception %s"%str(e)
def write_mime(self, file, attach_treshold=5, extra_headers={}, skip_keys=None): """Write MIME/Multipart RFC 2822 formatted data into file. file must be a file-like object, not a path. If a value is a string or a CompressedValue, it is written directly. Otherwise it must be a tuple containing the source file and an optional boolean value (in that order); the first argument can be a file name or a file-like object, which will be read and its content will become the value of this key. The file will be gzip compressed, unless the key already ends in .gz. attach_treshold specifies the maximum number of lines for a value to be included into the first inline text part. All bigger values (as well as all non-ASCII ones) will become an attachment. Extra MIME preamble headers can be specified, too, as a dictionary. skip_keys is a set/list specifying keys which are filtered out and not written to the destination file. """ keys = self.data.keys() keys.sort() text = "" attachments = [] if "ProblemType" in keys: keys.remove("ProblemType") keys.insert(0, "ProblemType") for k in keys: if skip_keys and k in skip_keys: continue v = self.data[k] attach_value = None # compressed values are ready for attaching in gzip form if isinstance(v, CompressedValue): attach_value = v.gzipvalue # if it's a tuple, we have a file reference; read the contents # and gzip it elif not hasattr(v, "find"): attach_value = "" if hasattr(v[0], "read"): f = v[0] # file-like object else: f = open(v[0]) # file name if k.endswith(".gz"): attach_value = f.read() else: io = StringIO() gf = gzip.GzipFile(k, mode="wb", fileobj=io) while True: block = f.read(1048576) if block: gf.write(block) else: gf.close() break attach_value = io.getvalue() f.close() # binary value elif self._is_binary(v): if k.endswith(".gz"): attach_value = v else: attach_value = CompressedValue(v, k).gzipvalue # if we have an attachment value, create an attachment if attach_value: att = MIMEBase("application", "x-gzip") if k.endswith(".gz"): att.add_header("Content-Disposition", "attachment", filename=k) else: att.add_header("Content-Disposition", "attachment", filename=k + ".gz") att.set_payload(attach_value) encode_base64(att) attachments.append(att) else: # plain text value if type(v) == type(u""): # convert unicode to UTF-8 str v = v.encode("UTF-8") lines = len(v.splitlines()) if lines == 1: v = v.rstrip() text += "%s: %s\n" % (k, v) elif lines <= attach_treshold: text += "%s:\n " % k if not v.endswith("\n"): v += "\n" text += v.strip().replace("\n", "\n ") + "\n" else: # too large, separate attachment att = MIMEText(v, _charset="UTF-8") att.add_header("Content-Disposition", "attachment", filename=k + ".txt") attachments.append(att) # create initial text attachment att = MIMEText(text, _charset="UTF-8") att.add_header("Content-Disposition", "inline") attachments.insert(0, att) msg = MIMEMultipart() for k, v in extra_headers.iteritems(): msg.add_header(k, v) for a in attachments: msg.attach(a) print >> file, msg.as_string()
def _get_sync(self, view, shareId, peerId, name, op): try: view.refresh(None, None, False) if shareId is not None: share = view[shareId] peerId = share.conduit.peerId toRepoId = share.repoId collection = share.contents name = collection.displayName uuid = collection.itsUUID version = share.localVersion else: collection, name, uuid = self.findCollection(view, name, None) toRepoId = None version = 0 replyTo = view[self.client.account].imap.replyToAddress.emailAddress share = self.findShare(view, collection, toRepoId, peerId) changes = self.computeChanges(view, version, collection, share) if op == 'sync' and not changes: share.localVersion = view.itsVersion + 1 view.commit() return None message = MIMEMultipart() message['From'] = replyTo message['Reply-To'] = replyTo message['To'] = peerId message['Subject'] = 'Chandler sent "%s" collection' %(name) message['X-chandler'] = 'p2p' textPart = MIMEBase('text', 'plain') textPart.set_payload('Chandler sent "%s"' %(name)) message.attach(textPart) attachment = MIMEBase('application', 'octet-stream') builder = TreeBuilder() dom = ElementTreeDOM() data = dom.openElement(builder, 'data') keys = set() for key, (_changes, status) in changes.iteritems(): if key not in keys: attrs = { 'uuid': key.str64() } if status & CItem.DELETED: attrs['status'] = 'deleted' item = dom.openElement(data, 'item', **attrs) else: if key in collection: attrs['status'] = 'member' item = dom.openElement(data, 'item', **attrs) share.format.exportProcess(dom, key, item, changes, keys) dom.closeElement(data, 'item') elif key in collection: item = dom.openElement(data, 'item', uuid=key.str64(), status='member') dom.closeElement(data, 'item') dom.closeElement(builder, 'data') out = StringIO() ElementTree(builder.close()).write(out, 'utf-8') data = compress(out.getvalue()) out.close() message['X-chandler-p2p-name'] = name message['X-chandler-p2p-from'] = self._repoId.str64() if toRepoId is not None: message['X-chandler-p2p-to'] = toRepoId.str64() message['X-chandler-p2p-item'] = "%s-%d" %(uuid.str64(), view.itsVersion) message['X-chandler-p2p-op'] = 'sync' attachment.set_payload(data) encode_base64(attachment) attachment.add_header('Content-Disposition', 'attachment', name=name) message.attach(attachment) except: view.cancel() raise share.localVersion = view.itsVersion + 1 share.established = True share.ackPending = True view.commit() return message
fp.close() elif maintype == 'image': fp = open(path, 'rb') msg = MIMEImage(fp.read(), _subtype=subtype) fp.close() elif maintype == 'audio': fp = open(path, 'rb') msg = MIMEAudio(fp.read(), _subtype=subtype) fp.close() else: fp = open(path, 'rb') msg = MIMEBase(maintype, subtype) msg.set_payload(fp.read()) fp.close() # Encode the payload using Base64 encode_base64(msg) # Set the filename parameter msg.add_header('Content-Disposition', 'attachment', filename=os.path.split(path)[1]) mail_obj.attach(msg) except Exception, e: print "** Exception **" print e pass s = smtplib.SMTP('10.113.2.107') s.set_debuglevel(0); __SendMailResult = "%04d/%02d/%02d %02d:%02d:%02d\t\t" % (datetime.now().year, datetime.now().month, datetime.now().day, datetime.now().hour, datetime.now().minute, datetime.now().second)
def add_a_post(groupId, siteId, replyToId, topic, message, tags, email, uploadedFiles, context, request): result = {'error': False, 'message': "Message posted.", 'id': ''} site_root = context.site_root() assert site_root userInfo = createObject('groupserver.LoggedInUser', context) siteObj = getattr(site_root.Content, siteId) groupObj = getattr(siteObj.groups, groupId) messages = getattr(groupObj, 'messages') assert messages listManager = messages.get_xwfMailingListManager() assert listManager groupList = getattr(listManager, groupObj.getId()) assert groupList #audit = WebPostAuditor(groupObj) #audit.info(POST, topic) # Step 1, check if the user can post userPostingInfo = getMultiAdapter((groupObj, userInfo), IGSPostingUser) if not userPostingInfo.canPost: raise 'Forbidden', userPostingInfo.status # --=mpj17-- Bless WebKit. It adds a file, even when no file has # been specified; if the files are empty, do not add the files. uploadedFiles = [f for f in uploadedFiles if f] # Step 2, Create the message # Step 2.1 Body message = message.encode('utf-8') if uploadedFiles: msg = MIMEMultipart() msgBody = MIMEText(message, 'plain', 'utf-8') # As God intended. msg.attach(msgBody) else: msg = MIMEText(message, 'plain', 'utf-8') # Step 2.2 Headers # msg['To'] set below # TODO: Add the user's name. The Header class will be needed # to ensure it is escaped properly. msg['From'] = unicode(Addressee(userInfo, email)).encode('ascii', 'ignore') msg['Subject'] = topic # --=mpj17=-- This does not need encoding. tagsList = tagProcess(tags) tagsString = ', '.join(tagsList) if tagsString: msg['Keywords'] = tagsString if replyToId: msg['In-Reply-To'] = replyToId # msg['Reply-To'] set by the list # Step 2.3 Attachments for f in uploadedFiles: # --=mpj17=-- zope.formlib has already read the data, so we # seek to the beginning to read it all again :) f.seek(0) data = f.read() if data: t = f.headers.getheader('Content-Type', 'application/octet-stream') mimePart = MIMENonMultipart(*t.split('/')) mimePart.set_payload(data) mimePart['Content-Disposition'] = 'attachment' filename = removePathsFromFilenames(f.filename) mimePart.set_param('filename', filename, 'Content-Disposition') encode_base64(mimePart) # Solves a lot of problems. msg.attach(mimePart) # Step 3, check the moderation. # --=mpj17=-- This changes *how* we send the message to the # mailing list. No, really. via_mailserver = False moderatedlist = groupList.get_moderatedUserObjects(ids_only=True) moderated = groupList.getValueFor('moderated') # --=rrw=--if we are moderated _and_ we have a moderatedlist, only # users in the moderated list are moderated if moderated and moderatedlist and (userInfo.id in moderatedlist): log.warn('User "%s" posted from web while moderated' % userInfo.id) via_mailserver = True # --=rrw=-- otherwise if we are moderated, everyone is moderated elif moderated and not (moderatedlist): log.warn('User "%s" posted from web while moderated' % userInfo.id) via_mailserver = True errorM = 'The post was not added to the topic '\ '<code class="topic">%s</code> because a post with the same '\ 'body already exists in the topic.' % topic # Step 4, send the message. for list_id in messages.getProperty('xwf_mailing_list_ids', []): curr_list = listManager.get_list(list_id) msg['To'] = curr_list.getValueFor('mailto') if via_mailserver: # If the message is being moderated, we have to emulate # a post via email so it can go through the moderation # subsystem. mailto = curr_list.getValueFor('mailto') try: send_email(email, mailto, msg.as_string()) except BadRequest as e: result['error'] = True result['message'] = errorM log.error(e.encode('ascii', 'ignore')) break result['error'] = True result['message'] = 'Your message has been sent to the '\ 'moderators for approval.' break else: # Send the message directly to the mailing list because # it is not moderated try: request = {'Mail': msg.as_string()} r = groupList.manage_listboxer(request) result['message'] = \ '<a href="/r/topic/%s#post-%s">Message '\ 'posted.</a>' % (r, r) except BadRequest as e: result['error'] = True result['message'] = errorM log.error(e) break except DuplicateMessageError as e: result['error'] = True result['message'] = errorM break if (not r): # --=mpj17=-- This could be lies. result['error'] = True result['message'] = errorM break return result
def add_a_post(groupId, siteId, replyToId, topic, message, tags, email, uploadedFiles, context, request): result = { 'error': False, 'message': "Message posted.", 'id': ''} site_root = context.site_root() assert site_root userInfo = createObject('groupserver.LoggedInUser', context) siteObj = getattr(site_root.Content, siteId) groupObj = getattr(siteObj.groups, groupId) messages = getattr(groupObj, 'messages') assert messages listManager = messages.get_xwfMailingListManager() assert listManager groupList = getattr(listManager, groupObj.getId()) assert groupList #audit = WebPostAuditor(groupObj) #audit.info(POST, topic) # Step 1, check if the user can post userPostingInfo = getMultiAdapter((groupObj, userInfo), IGSPostingUser) if not userPostingInfo.canPost: raise 'Forbidden', userPostingInfo.status # --=mpj17-- Bless WebKit. It adds a file, even when no file has # been specified; if the files are empty, do not add the files. uploadedFiles = [f for f in uploadedFiles if f] # Step 2, Create the message # Step 2.1 Body message = message.encode('utf-8') if uploadedFiles: msg = MIMEMultipart() msgBody = MIMEText(message, 'plain', 'utf-8') # As God intended. msg.attach(msgBody) else: msg = MIMEText(message, 'plain', 'utf-8') # Step 2.2 Headers # msg['To'] set below # TODO: Add the user's name. The Header class will be needed # to ensure it is escaped properly. msg['From'] = unicode(Addressee(userInfo, email)).encode('ascii', 'ignore') msg['Subject'] = topic # --=mpj17=-- This does not need encoding. tagsList = tagProcess(tags) tagsString = ', '.join(tagsList) if tagsString: msg['Keywords'] = tagsString if replyToId: msg['In-Reply-To'] = replyToId # msg['Reply-To'] set by the list # Step 2.3 Attachments for f in uploadedFiles: # --=mpj17=-- zope.formlib has already read the data, so we # seek to the beginning to read it all again :) f.seek(0) data = f.read() if data: t = f.headers.getheader('Content-Type', 'application/octet-stream') mimePart = MIMENonMultipart(*t.split('/')) mimePart.set_payload(data) mimePart['Content-Disposition'] = 'attachment' filename = removePathsFromFilenames(f.filename) mimePart.set_param('filename', filename, 'Content-Disposition') encode_base64(mimePart) # Solves a lot of problems. msg.attach(mimePart) # Step 3, check the moderation. # --=mpj17=-- This changes *how* we send the message to the # mailing list. No, really. via_mailserver = False moderatedlist = groupList.get_moderatedUserObjects(ids_only=True) moderated = groupList.getValueFor('moderated') # --=rrw=--if we are moderated _and_ we have a moderatedlist, only # users in the moderated list are moderated if moderated and moderatedlist and (userInfo.id in moderatedlist): log.warn('User "%s" posted from web while moderated' % userInfo.id) via_mailserver = True # --=rrw=-- otherwise if we are moderated, everyone is moderated elif moderated and not(moderatedlist): log.warn('User "%s" posted from web while moderated' % userInfo.id) via_mailserver = True errorM = 'The post was not added to the topic '\ '<code class="topic">%s</code> because a post with the same '\ 'body already exists in the topic.' % topic # Step 4, send the message. for list_id in messages.getProperty('xwf_mailing_list_ids', []): curr_list = listManager.get_list(list_id) msg['To'] = curr_list.getValueFor('mailto') if via_mailserver: # If the message is being moderated, we have to emulate # a post via email so it can go through the moderation # subsystem. mailto = curr_list.getValueFor('mailto') try: send_email(email, mailto, msg.as_string()) except BadRequest as e: result['error'] = True result['message'] = errorM log.error(e.encode('ascii', 'ignore')) break result['error'] = True result['message'] = 'Your message has been sent to the '\ 'moderators for approval.' break else: # Send the message directly to the mailing list because # it is not moderated try: request = {'Mail': msg.as_string()} r = groupList.manage_listboxer(request) result['message'] = \ '<a href="/r/topic/%s#post-%s">Message '\ 'posted.</a>' % (r, r) except BadRequest as e: result['error'] = True result['message'] = errorM log.error(e) break except DuplicateMessageError as e: result['error'] = True result['message'] = errorM break if (not r): # --=mpj17=-- This could be lies. result['error'] = True result['message'] = errorM break return result
def write_mime(self, file, attach_treshold=5, extra_headers={}, skip_keys=None): '''Write MIME/Multipart RFC 2822 formatted data into file. file must be a file-like object, not a path. If a value is a string or a CompressedValue, it is written directly. Otherwise it must be a tuple containing the source file and an optional boolean value (in that order); the first argument can be a file name or a file-like object, which will be read and its content will become the value of this key. The file will be gzip compressed, unless the key already ends in .gz. attach_treshold specifies the maximum number of lines for a value to be included into the first inline text part. All bigger values (as well as all non-ASCII ones) will become an attachment. Extra MIME preamble headers can be specified, too, as a dictionary. skip_keys is a set/list specifying keys which are filtered out and not written to the destination file. ''' keys = self.data.keys() keys.sort() text = '' attachments = [] if 'ProblemType' in keys: keys.remove('ProblemType') keys.insert(0, 'ProblemType') for k in keys: if skip_keys and k in skip_keys: continue v = self.data[k] attach_value = None # compressed values are ready for attaching in gzip form if isinstance(v, CompressedValue): attach_value = v.gzipvalue # if it's a tuple, we have a file reference; read the contents # and gzip it elif not hasattr(v, 'find'): attach_value = '' if hasattr(v[0], 'read'): f = v[0] # file-like object else: f = open(v[0]) # file name if k.endswith('.gz'): attach_value = f.read() else: io = StringIO() gf = gzip.GzipFile(k, mode='wb', fileobj=io) while True: block = f.read(1048576) if block: gf.write(block) else: gf.close() break attach_value = io.getvalue() f.close() # binary value elif self._is_binary(v): if k.endswith('.gz'): attach_value = v else: attach_value = CompressedValue(v, k).gzipvalue # if we have an attachment value, create an attachment if attach_value: att = MIMEBase('application', 'x-gzip') if k.endswith('.gz'): att.add_header('Content-Disposition', 'attachment', filename=k) else: att.add_header('Content-Disposition', 'attachment', filename=k + '.gz') att.set_payload(attach_value) encode_base64(att) attachments.append(att) else: # plain text value if type(v) == type(u''): # convert unicode to UTF-8 str v = v.encode('UTF-8') lines = len(v.splitlines()) if lines == 1: v = v.rstrip() text += '%s: %s\n' % (k, v) elif lines <= attach_treshold: text += '%s:\n ' % k if not v.endswith('\n'): v += '\n' text += v.strip().replace('\n', '\n ') + '\n' else: # too large, separate attachment att = MIMEText(v, _charset='UTF-8') att.add_header('Content-Disposition', 'attachment', filename=k + '.txt') attachments.append(att) # create initial text attachment att = MIMEText(text, _charset='UTF-8') att.add_header('Content-Disposition', 'inline') attachments.insert(0, att) msg = MIMEMultipart() for k, v in extra_headers.iteritems(): msg.add_header(k, v) for a in attachments: msg.attach(a) print >> file, msg.as_string()
def _get_sync(self, view, shareId, peerId, name, op): try: view.refresh(None, None, False) if shareId is not None: share = view[shareId] peerId = share.conduit.peerId toRepoId = share.repoId collection = share.contents name = collection.displayName uuid = collection.itsUUID version = share.localVersion else: collection, name, uuid = self.findCollection(view, name, None) toRepoId = None version = 0 replyTo = view[ self.client.account].imap.replyToAddress.emailAddress share = self.findShare(view, collection, toRepoId, peerId) changes = self.computeChanges(view, version, collection, share) if op == 'sync' and not changes: share.localVersion = view.itsVersion + 1 view.commit() return None message = MIMEMultipart() message['From'] = replyTo message['Reply-To'] = replyTo message['To'] = peerId message['Subject'] = 'Chandler sent "%s" collection' % (name) message['X-chandler'] = 'p2p' textPart = MIMEBase('text', 'plain') textPart.set_payload('Chandler sent "%s"' % (name)) message.attach(textPart) attachment = MIMEBase('application', 'octet-stream') builder = TreeBuilder() dom = ElementTreeDOM() data = dom.openElement(builder, 'data') keys = set() for key, (_changes, status) in changes.iteritems(): if key not in keys: attrs = {'uuid': key.str64()} if status & CItem.DELETED: attrs['status'] = 'deleted' item = dom.openElement(data, 'item', **attrs) else: if key in collection: attrs['status'] = 'member' item = dom.openElement(data, 'item', **attrs) share.format.exportProcess(dom, key, item, changes, keys) dom.closeElement(data, 'item') elif key in collection: item = dom.openElement(data, 'item', uuid=key.str64(), status='member') dom.closeElement(data, 'item') dom.closeElement(builder, 'data') out = StringIO() ElementTree(builder.close()).write(out, 'utf-8') data = compress(out.getvalue()) out.close() message['X-chandler-p2p-name'] = name message['X-chandler-p2p-from'] = self._repoId.str64() if toRepoId is not None: message['X-chandler-p2p-to'] = toRepoId.str64() message['X-chandler-p2p-item'] = "%s-%d" % (uuid.str64(), view.itsVersion) message['X-chandler-p2p-op'] = 'sync' attachment.set_payload(data) encode_base64(attachment) attachment.add_header('Content-Disposition', 'attachment', name=name) message.attach(attachment) except: view.cancel() raise share.localVersion = view.itsVersion + 1 share.established = True share.ackPending = True view.commit() return message