def sendMail(document, ext, mtime, mail_config): msg = MIMEMultipart() msg["Subject"] = "New Scan!" msg["From"] = mail_config.mail_from msg["To"] = mail_config.mail_to mime_type = mime.from_buffer(document).split("/", 1) attachment = MIMENonMultipart(mime_type[0], mime_type[1]) attachment.add_header("Content-Disposition", "attachment", filename="scan-{timestamp}.{ext}".format( timestamp=mtime.strftime("%Y_%m_%d-%H%M%S"), ext=ext)) attachment.set_payload(document) encoders.encode_base64(attachment) msg.attach(attachment) msg.attach( MIMEText("""Hey! I found a new scan on your printer. You can find it in the attachments :) Regards Scan-Bot """)) s = smtplib.SMTP(mail_config.host, mail_config.port) s.starttls() s.login(mail_config.user, mail_config.password) s.send_message(msg)
def send(self, document: Document): server = smtplib.SMTP_SSL(self.server, self.ssl_port) server.login(self.user, self.password) message = MIMEMultipart("alternative") message["Subject"] = f"Nuovo documento '{document.title}'" message["From"] = self.user message["To"] = ",".join(self.to) environment = Environment(loader=FileSystemLoader( searchpath=self.templates_directory)) text_template = environment.get_template("document.text.jinja2") html_template = environment.get_template("document.html.jinja2") env = {"document": document} part1 = MIMEText(text_template.render(env), "plain") part2 = MIMEText(html_template.render(env), "html") message.attach(part1) message.attach(part2) for attachment in document.attachments: type_, subtype = attachment.content_type.split("/") mime = MIMENonMultipart(_maintype=type_, _subtype=subtype) mime.set_payload(attachment.bytes_) mime.add_header("Content-Disposition", "attachment", filename=attachment.name) encoders.encode_base64(mime) message.attach(mime) server.sendmail(self.user, self.to, message.as_string()) server.close()
def sendPDF(fileName, email): smtp_ssl_host = 'smtp.gmail.com' smtp_ssl_port = 465 username = '******' password = '******' sender = '*****@*****.**' targets = [email] msg = MIMEMultipart() msg['Subject'] = 'Study Plan' msg['From'] = sender msg['To'] = ', '.join(targets) #Source for PDF send: https://bugs.python.org/issue9040 fp = open(fileName, 'rb') attach = MIMENonMultipart('application', 'pdf') payload = base64.b64encode(fp.read()).decode('ascii') attach.set_payload(payload) attach['Content-Transfer-Encoding'] = 'base64' fp.close() attach.add_header('Content-Disposition', 'attachment', filename = 'StudyPlan.pdf') msg.attach(attach) #End of found fix server = smtplib.SMTP_SSL(smtp_ssl_host, smtp_ssl_port) server.login(username, password) server.sendmail(sender, targets, msg.as_string()) server.quit() return "Sent study plan to: " + email
def upload(self, filename): name = os.path.basename(filename) size = os.path.getsize(filename) cype = guess_type(name) if not cype or not cype[0]: cype = "text/plain" else: cype = cype[0] url = ("https://www.googleapis.com/upload/drive/v2/files?" "uploadType=multipart") message = MIMEMultipart('mixed') # Message should not write out it's own headers. setattr(message, '_write_headers', lambda self: None) msg = MIMENonMultipart('application', 'json; charset=UTF-8') msg.set_payload(json.dumps({"title": name, #.replace("'", r"\'"), "mimeType": cype})) message.attach(msg) msg = MIMENonMultipart(*cype.split('/')) msg.add_header("Content-Transfer-Encoding", "binary") msg.set_payload(open(filename).read()) message.attach(msg) body = message.as_string() bd = message.get_boundary() hd = {"Content-Type": 'multipart/related; boundary="%s"' % bd} res = self.auth_http("POST", url, body, hd) ret = res.read() pprint(ret)
def send_simple_mail(sender, receiver, subject, msgtxt, sending_username, attachments=None): # attachment format, each is a tuple of (name, mimetype,contents) # content should already be base64 encoded msg = MIMEMultipart() msg['Subject'] = subject msg['To'] = receiver msg['From'] = sender msg['Date'] = formatdate(localtime=True) msg['User-Agent'] = 'pgcommitfest' if sending_username: msg['X-cfsender'] = sending_username msg.attach(MIMEText(msgtxt, _charset='utf-8')) if attachments: for filename, contenttype, content in attachments: main,sub = contenttype.split('/') part = MIMENonMultipart(main,sub) part.set_payload(content) part.add_header('Content-Disposition', 'attachment; filename="%s"' % filename) encoders.encode_base64(part) msg.attach(part) # Just write it to the queue, so it will be transactionally rolled back QueuedMail(sender=sender, receiver=receiver, fullmsg=msg.as_string()).save()
def upload(self, filename): name = os.path.basename(filename) size = os.path.getsize(filename) cype = guess_type(name) if not cype or not cype[0]: cype = "text/plain" else: cype = cype[0] url = ("https://www.googleapis.com/upload/drive/v2/files?" "uploadType=multipart") message = MIMEMultipart('mixed') # Message should not write out it's own headers. setattr(message, '_write_headers', lambda self: None) msg = MIMENonMultipart('application', 'json; charset=UTF-8') msg.set_payload(json.dumps({"title": name, #.replace("'", r"\'"), "mimeType": cype})) message.attach(msg) msg = MIMENonMultipart(*cype.split('/')) msg.add_header("Content-Transfer-Encoding", "binary") msg.set_payload(open(filename).read()) message.attach(msg) body = message.as_string() bd = message.get_boundary() hd = {"Content-Type": 'multipart/related; boundary="%s"' % bd} res = self.auth_http("POST", url, body, hd) ret = res.read() pprint(ret) return
def send_simple_mail(sender, receiver, subject, msgtxt, attachments=None, bcc=None, sendername=None, receivername=None): # attachment format, each is a tuple of (name, mimetype,contents) # content should be *binary* and not base64 encoded, since we need to # use the base64 routines from the email library to get a properly # formatted output message msg = MIMEMultipart() msg['Subject'] = subject msg['To'] = _encoded_email_header(receivername, receiver) msg['From'] = _encoded_email_header(sendername, sender) msg['Date'] = formatdate(localtime=True) msg.attach(MIMEText(msgtxt, _charset='utf-8')) if attachments: for filename, contenttype, content in attachments: main, sub = contenttype.split('/') part = MIMENonMultipart(main, sub) part.set_payload(content) part.add_header('Content-Disposition', 'attachment; filename="%s"' % filename) encoders.encode_base64(part) msg.attach(part) # Just write it to the queue, so it will be transactionally rolled back QueuedMail(sender=sender, receiver=receiver, subject=subject, fullmsg=msg.as_string()).save() # Any bcc is just entered as a separate email if bcc: if type(bcc) is list or type(bcc) is tuple: bcc = set(bcc) else: bcc = set((bcc, )) for b in bcc: QueuedMail(sender=sender, receiver=b, subject=subject, fullmsg=msg.as_string()).save()
def send_simple_mail(sender, receiver, subject, msgtxt, attachments=None, bcc=None, sendername=None, receivername=None): # attachment format, each is a tuple of (name, mimetype,contents) # content should be *binary* and not base64 encoded, since we need to # use the base64 routines from the email library to get a properly # formatted output message msg = MIMEMultipart() msg['Subject'] = subject msg['To'] = _encoded_email_header(receivername, receiver) msg['From'] = _encoded_email_header(sendername, sender) msg['Date'] = formatdate(localtime=True) msg.attach(MIMEText(msgtxt, _charset='utf-8')) if attachments: for filename, contenttype, content in attachments: main,sub = contenttype.split('/') part = MIMENonMultipart(main,sub) part.set_payload(content) part.add_header('Content-Disposition', 'attachment; filename="%s"' % filename) encoders.encode_base64(part) msg.attach(part) # Just write it to the queue, so it will be transactionally rolled back QueuedMail(sender=sender, receiver=receiver, fullmsg=msg.as_string()).save() # Any bcc is just entered as a separate email if bcc: QueuedMail(sender=sender, receiver=bcc, fullmsg=msg.as_string()).save()
def send_simple_mail(sender, receiver, subject, msgtxt, attachments=None, usergenerated=False): # attachment format, each is a tuple of (name, mimetype,contents) # content should be *binary* and not base64 encoded, since we need to # use the base64 routines from the email library to get a properly # formatted output message msg = MIMEMultipart() msg['Subject'] = subject msg['To'] = receiver msg['From'] = sender msg['Date'] = formatdate(localtime=True) msg['Message-ID'] = make_msgid() msg.attach(MIMEText(msgtxt, _charset='utf-8')) if attachments: for filename, contenttype, content in attachments: main,sub = contenttype.split('/') part = MIMENonMultipart(main,sub) part.set_payload(content) part.add_header('Content-Disposition', 'attachment; filename="%s"' % filename) encoders.encode_base64(part) msg.attach(part) # Just write it to the queue, so it will be transactionally rolled back QueuedMail(sender=sender, receiver=receiver, fullmsg=msg.as_string(), usergenerated=usergenerated).save()
def post(self, request): context = self.get_context_data() form, user = context['form'], request.user if not form.is_valid(): return self.get(request) s = smtplib.SMTP(settings.EMAIL_HOST, settings.EMAIL_PORT) s.starttls() if settings.EMAIL_HOST_USER: s.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD) sender = "%s %s (via OxPoints Editor) <%s>" % (user.first_name, user.last_name, user.email) recipients = ['%s <%s>' % manager for manager in settings.MANAGERS] msg = MIMEMultipart() msg['Subject'] = form.cleaned_data['subject'] msg['From'] = sender msg['To'] = ', '.join(recipients) msg.attach(MIMEText(form.cleaned_data['message'], 'plain')) if request.FILES.get('related_file'): related_file = request.FILES['related_file'] attachment = MIMENonMultipart(*related_file.content_type.split('/', 1)) attachment.add_header('Content-Disposition', 'attachment', filename=related_file.name) attachment.set_payload(related_file.read()) msg.attach(attachment) s.sendmail(sender, recipients, msg.as_string()) return redirect(reverse('core:request') + '?sent=true')
def get_content_block(self, f): binding_map = { '.xlsx': ('application', 'vnd.openxmlformats-officedocument.spreadsheetml.sheet'), '.xls': ('application', 'vnd.ms-excel'), '.csv': ('text', 'csv'), '.json': ('application', 'json'), '.syslog': ('text', 'syslog') } # Check the file extension to see if it is a supported type name_part, ext_part = os.path.splitext(f.name) if ext_part.lower() == '.xml': cb = tm11.ContentBlock(tm11.ContentBinding(t.CB_STIX_XML_101), f.read()) else: binding_tuple = binding_map.get(ext_part.lower(), None) if not binding_tuple: logger.error('File extension not supported: %s. Supported extensions: %s' % (ext_part, binding_map.keys())) return # Read the file and create a MIME message for it maintype = binding_tuple[0] subtype = binding_tuple[1] # Note: This is MIME subtype, not TAXII subtype mime_msg = MIMENonMultipart(maintype, subtype) mime_msg.add_header('Content-Disposition', 'attachment', filename=f.name) mime_msg.set_payload(f.read()) encode_base64(mime_msg) cb = tm11.ContentBlock('%s/%s' % (maintype, subtype), mime_msg.as_string()) return cb
def attach(self, name, data=None, maintype=None, subtype=None, inline=False, filename=None, encoding=None): """Attach a file to this message. :param name: Path to the file to attach if data is None, or the name of the file if the ``data`` argument is given :param data: Contents of the file to attach, or None if the data is to be read from the file pointed to by the ``name`` argument :type data: bytes or a file-like object :param maintype: First part of the MIME type of the file -- will be automatically guessed if not given :param subtype: Second part of the MIME type of the file -- will be automatically guessed if not given :param inline: Whether to set the Content-Disposition for the file to "inline" (True) or "attachment" (False) :param filename: The file name of the attached file as seen by the user in his/her mail client. :param encoding: Value of the Content-Encoding MIME header (e.g. "gzip" in case of .tar.gz, but usually empty) """ self._dirty = True if not maintype: maintype, guessed_encoding = guess_type(name) encoding = encoding or guessed_encoding if not maintype: maintype, subtype = 'application', 'octet-stream' else: maintype, _, subtype = maintype.partition('/') part = MIMENonMultipart(maintype, subtype) part.add_header('Content-Transfer-Encoding', 'base64') if encoding: part.add_header('Content-Encoding', encoding) if data is None: with open(name, 'rb') as fp: value = fp.read() name = os.path.basename(name) elif isinstance(data, bytes): value = data elif hasattr(data, 'read'): value = data.read() else: raise TypeError("Unable to read attachment contents") part.set_payload(base64.encodestring(value)) if not filename: filename = name filename = os.path.basename(filename) if inline: part.add_header('Content-Disposition', 'inline', filename=filename) part.add_header('Content-ID', '<%s>' % filename) self.embedded.append(part) else: part.add_header('Content-Disposition', 'attachment', filename=filename) self.attachments.append(part)
def sendmail(text, sender, subject, archive=None): if not c.has_option('commitmsg', 'destination'): return if c.has_option('commitmsg', 'replyto'): pieces = [] for p in c.get('commitmsg', 'replyto').split(','): pp = p.strip() if pp == '$committer': if sender: pieces.append(sender.strip()) # Don't add fallback sender as committer else: pieces.append(pp) replyto = ', '.join(pieces) else: replyto = None if not sender: # No sender specified, so use fallback sender = cfg.get('commitmsg', 'fallbacksender') (sender_name, sender_address) = email.utils.parseaddr(sender) if c.has_option('commitmsg', 'forcesenderaddr'): sender_address = c.get('commitmsg', 'forcesenderaddr') if sender_name: fullsender = "{0} <{1}>".format(sender_name, sender_address) else: fullsender = sender_address for m in c.get('commitmsg', 'destination').split(','): msg = MIMEMultipart() msg['From'] = fullsender msg['To'] = m msg['Subject'] = subject if replyto: msg['Reply-To'] = replyto # Don't specify utf8 when doing debugging, because that will encode the output # as base64 which is completely useless on the console... if debug == 1: msg.attach(MIMEText(text)) else: msg.attach(MIMEText(text, _charset='utf-8')) if archive: part = MIMENonMultipart('application', 'x-gzip') part.set_payload(archive) part.add_header('Content-Disposition', 'attachment; filename="archive.tar.gz"') encoders.encode_base64(part) msg.attach(part) allmail.append({ 'sender': sender_address, 'to': m, 'msg': msg, })
def prepare_email_message(self): """ Returns a django ``EmailMessage`` or ``EmailMultiAlternatives`` object, depending on whether html_message is empty. """ if self.template is not None: engine = get_template_engine() subject = engine.from_string(self.template.subject).render(self.context) plaintext_message = engine.from_string(self.template.content).render(self.context) multipart_template = engine.from_string(self.template.html_content) html_message = multipart_template.render(self.context) else: subject = smart_text(self.subject) plaintext_message = self.message multipart_template = None html_message = self.html_message connection = connections[self.backend_alias or 'default'] if html_message: if plaintext_message: msg = EmailMultiAlternatives( subject=subject, body=plaintext_message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=self.headers, connection=connection) msg.attach_alternative(html_message, "text/html") else: msg = EmailMultiAlternatives( subject=subject, body=html_message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=self.headers, connection=connection) msg.content_subtype = 'html' if hasattr(multipart_template, 'attach_related'): multipart_template.attach_related(msg) else: msg = EmailMessage( subject=subject, body=plaintext_message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=self.headers, connection=connection) for attachment in self.attachments.all(): if attachment.headers: mime_part = MIMENonMultipart(*attachment.mimetype.split('/')) mime_part.set_payload(attachment.file.read()) for key, val in attachment.headers.items(): try: mime_part.replace_header(key, val) except KeyError: mime_part.add_header(key, val) msg.attach(mime_part) else: msg.attach(attachment.name, attachment.file.read(), mimetype=attachment.mimetype or None) attachment.file.close() self._cached_email_message = msg return msg
def _send_batch_request(self, requests): """Sends a batch of requests to the server and processes the HTTP responses. Args: requests: List of GoogleComputeEngineBase.API_REQUEST named tuples. Must contain <= MAX_BATCH_SIZE elements. Raises: ValueError: If requests has more than MAX_BATCH_SIZE elements. Returns: List of GoogleComputeEngineBase.BATCH_RESPONSE named tuples, one for each element of request parameter. """ if len(requests) > MAX_BATCH_SIZE: raise ValueError('Too many requests provided' '(maximum is {0})'.format(MAX_BATCH_SIZE)) batch = _BatchApiRequest() base = urlparse.urlsplit(self.base_url) base_path = base.path.rstrip('/') for i, request in enumerate(requests): msg = MIMENonMultipart('application', 'http') msg.add_header('Content-ID', '<{0}>'.format(i)) msg.set_payload(self._serialize_batch_api_request(base_path, request)) batch.attach(msg) batch_string = batch.as_string() content_type = 'multipart/mixed; boundary="{0}"'.format( batch.get_boundary()) url = urlparse.urlunsplit((base.scheme, base.netloc, 'batch', self._create_url_query(None), None)) response, data = self._send_request(url, 'POST', batch_string, content_type) if response.status >= 300: error = gce.GceError( message=response.reason, status=response.status) return [error] * len(requests) # Return all errors. elif not data: error = gce.GceError( message='Server returned no data', status=response.status) return [error] * len(requests) # Return all errors. # Process successful response. data = 'content-type: {0}\r\n\r\n'.format(response['content-type']) + data parser = FeedParser() parser.feed(data) response = parser.close() responses = [] for part in response.get_payload(): responses.append(( int(RESPONSE_ID_REGEX.match(part['Content-ID']).group(1)), self._parse_batch_api_response(part.get_payload()))) responses.sort(key=lambda r: r[0]) return [r[1] for r in responses]
def send_to_email(self, header, total_fails): self.logger.info("Отправляем отчет на email.") print(self.mutt_enabled) if self.mutt_enabled: if "Отчет не сгенерирован" or "Данные обрабатываются" not in header: attach_file = '' else: attach_file = '-a "report/report.csv"' mailsubject = "Отчет по {} за {}. (Пропусков: {})".format( self.orgname, self.date, total_fails) cmd_send_by_email = ' echo "{}" | mutt {} -s "{}" -- {}'.format( header, attach_file, mailsubject, self.email) temp = subprocess.getoutput(cmd_send_by_email) self.logger.debug(temp) else: mailsubject = "Отчет по {} за {}. (Пропусков: {})".format( self.orgname, self.date, total_fails) sender = self.smtp_login passwd = self.smtp_passwd receiver = self.email msg = MIMEMultipart() msg['From'] = sender msg['To'] = receiver msg['Subject'] = mailsubject if "Отчет не сгенерирован" or "Данные обрабатываются" not in header: with open('report/report.csv', encoding='cp1251') as f: report_file = f.read() attachment = MIMENonMultipart('text', 'csv', charset='cp1251') attachment.add_header('Content-Disposition', 'attachment', filename='report.csv') attachment.set_payload(report_file.encode('cp1251')) msg.attach(attachment) msg_body = MIMEText(header) msg.attach(msg_body) smtp_server_name = self.smtp_server port = self.smtp_port if port == '465': server = smtplib.SMTP_SSL('{}:{}'.format( smtp_server_name, port)) else: server = smtplib.SMTP('{}:{}'.format(smtp_server_name, port)) server.starttls() # this is for secure reason server.login(sender, passwd) server.send_message(msg) server.quit()
def send_simple_mail(sender, receiver, subject, msgtxt, attachments=None, usergenerated=False, cc=None, replyto=None, sendername=None, receivername=None, messageid=None): # attachment format, each is a tuple of (name, mimetype,contents) # content should be *binary* and not base64 encoded, since we need to # use the base64 routines from the email library to get a properly # formatted output message msg = MIMEMultipart() msg['Subject'] = subject msg['To'] = _encoded_email_header(receivername, receiver) msg['From'] = _encoded_email_header(sendername, sender) if cc: msg['Cc'] = cc if replyto: msg['Reply-To'] = replyto msg['Date'] = formatdate(localtime=True) if messageid: msg['Message-ID'] = messageid else: msg['Message-ID'] = make_msgid() msg.attach(MIMEText(msgtxt, _charset='utf-8')) if attachments: for filename, contenttype, content in attachments: main, sub = contenttype.split('/') part = MIMENonMultipart(main, sub) part.set_payload(content) part.add_header('Content-Disposition', 'attachment; filename="%s"' % filename) encoders.encode_base64(part) msg.attach(part) # Just write it to the queue, so it will be transactionally rolled back QueuedMail(sender=sender, receiver=receiver, fullmsg=msg.as_string(), usergenerated=usergenerated).save() if cc: # Write a second copy for the cc, wihch will be delivered # directly to the recipient. (The sender doesn't parse the # message content to extract cc fields). QueuedMail(sender=sender, receiver=cc, fullmsg=msg.as_string(), usergenerated=usergenerated).save()
def send_report(self, short_description, additional_description, title, report): # Create message container - the correct MIME type is multipart/mixed to allow attachment. full_email = MIMEMultipart('mixed') full_email[ 'Subject'] = '[' + self.conf['subject_keyword'] + '] ' + title full_email['From'] = self.conf['from'] full_email['To'] = self.conf['to'] # Create the body of the message (a plain-text and an HTML version). body = MIMEMultipart('alternative') body.attach( MIMEText((short_description + "\n\n" + additional_description).encode('utf-8'), 'plain', _charset='utf-8')) body.attach( MIMEText(("""\ <html> <head></head> <body> <p>""" + short_description + """</p><br> """ + additional_description + """ </body> </html> """).encode('utf-8'), 'html', _charset='utf-8')) full_email.attach(body) # Create the attachment of the message in text/csv. attachment = MIMENonMultipart('text', 'csv', charset='utf-8') attachment.add_header('Content-Disposition', 'attachment', filename=report['filename']) cs = Charset('utf-8') cs.body_encoding = BASE64 attachment.set_payload(report['content'].encode('utf-8'), charset=cs) full_email.attach(attachment) # Send the message via SMTP server. s = smtplib.SMTP(self.conf['server'], self.conf['port']) if self.conf['tls'] == 'yes': s.starttls() if not self.conf['login'] == '': s.login(self.conf['login'], self.conf['password']) # sendmail function takes 3 arguments: sender's address, recipient's address # and message to send - here it is sent as one string. s.sendmail(self.conf['from'], self.conf['to'], full_email.as_string()) # self.logger.info('email sent') s.quit()
def send_report(self, date, short_description, additional_description, title, _filename): full_email = MIMEMultipart('mixed') full_email['Subject'] = date + " " + self.subject full_email['From'] = self.sender full_email['To'] = self.receipant email_addresses = self.receipant.split(',') # CSV FILE attachment = MIMENonMultipart('plain', 'csv', charset='utf-8') attachment.add_header('Content-Disposition', 'attachment', filename=_filename[39:len(_filename)]) attachment.set_payload(open(_filename, "rb").read()) full_email.attach(attachment) # HTML TABLE body = MIMEMultipart('alternative') body.attach( MIMEText( (short_description + additional_description).encode('utf-8'), 'html', _charset='utf-8')) body.attach( MIMEText(("""\ <html> <head></head> <body> <div style="text-align:center"> <strong> <h1><font color="red">""" + title + """</font></h1> <h4>""" + short_description + additional_description + """</h4> </strong> </div> </body> </html> """).encode('utf-8'), 'html', _charset='utf-8')) full_email.attach(body) s = smtplib.SMTP(self.server, self.port) if self.tls == 'yes': s.starttls() if not self.login == '': s.login(self.login, self.password) try: s.sendmail(self.sender, email_addresses, full_email.as_string()) s.quit() except SMTPException as e: print "ERROR %d: %s" % (e.args[0], e.args[1])
def _attachment_to_cdoc(self, content, content_type, encoder=encoders.encode_base64): major, sub = content_type.split('/') attachment = MIMENonMultipart(major, sub) attachment.set_payload(content) encoder(attachment) attachment.add_header('Content-Disposition', 'attachment', filename='does_not_matter.txt') pseudo_mail = MIMEMultipart() pseudo_mail.attach(attachment) tmp_mail = SoledadMailAdaptor().get_msg_from_string(MessageClass=Message, raw_msg=pseudo_mail.as_string()) cdoc = tmp_mail.get_wrapper().cdocs[1] return cdoc
def _generate_MIME_part(key, content, keytype, headers): if not keytype: try: content.encode("ascii") keytype = ("text", "plain") except UnicodeError: keytype = ("application", "octet-stream") submsg = MIMENonMultipart(*keytype) content_headers = {'name': key} if headers: content_headers.update(headers) submsg.add_header("Content-disposition", "form-data", **content_headers) submsg.set_payload(content) return submsg
def _form_email(self, recipient_data): """ Form the html email, including mimetype and headers. """ # instatiate the email object and assign headers email_message = MIMEMultipart('related') email_message.preamble = 'This is a multi-part message in MIME format.' if self.txt_path != "": txt = MIMEText(PyMailer._prepare_text(self.txt_path, recipient_data), 'plain', _charset='utf-8') # encoders.encode_quopri(txt) email_message.attach(txt) if self.html_path != "": html = MIMEText(PyMailer._prepare_text(self.html_path, recipient_data), 'html', _charset='utf-8') # encoders.encode_quopri(html) email_message.attach(html) for image in self.images: with open(image, 'rb') as f: imageMime = MIMEImage(f.read()) imageMime.add_header('Content-ID', '<%s>' % image) email_message.attach(imageMime) for attachment in self.attachments: with open(attachment[1], 'rb') as f: attachmentMime = MIMENonMultipart(attachment[0].split('/')[0], attachment[0].split('/')[1]) attachmentMime.set_payload(f.read()) if attachment[0].split('/')[0] == 'text': encoders.encode_quopri(attachmentMime) attachmentMime.add_header( 'Content-Disposition', 'attachment; filename=%s' % attachment[1]) email_message.attach(attachmentMime) email_message['From'] = recipient_data.get('sender') email_message['To'] = recipient_data.get('recipient') email_message['Subject'] = self.subject return email_message.as_string()
def prepare_email_message(self): """ Returns a django ``EmailMessage`` or ``EmailMultiAlternatives`` object, depending on whether html_message is empty. """ subject = smart_text(self.subject) if self.template is not None: _context = Context(self.context) subject = Template(self.template.subject).render(_context) message = Template(self.template.content).render(_context) html_message = Template(self.template.html_content).render(_context) else: subject = self.subject message = self.message html_message = self.html_message connection = connections[self.backend_alias or 'default'] if html_message: msg = EmailMultiAlternatives( subject=subject, body=message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=self.headers, connection=connection) msg.attach_alternative(html_message, "text/html") else: msg = EmailMessage( subject=subject, body=message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=self.headers, connection=connection) for attachment in self.attachments.all(): if attachment.headers: mime_part = MIMENonMultipart(*attachment.mimetype.split('/')) mime_part.set_payload(attachment.file.read()) for key, val in attachment.headers.items(): try: mime_part.replace_header(key, val) except KeyError: mime_part.add_header(key, val) msg.attach(mime_part) else: msg.attach(attachment.name, attachment.file.read(), mimetype=attachment.mimetype or None) attachment.file.close() self._cached_email_message = msg return msg
def createMessage(self, recipients): msg = MIMEMultipart() msg['Subject'] = yamlLoad['SendInfo']['Subject'] msg['From'] = Sender msg['To'] = recipients if args.v: print( colored("Delivering to " + recipients + ", from: " + sender, "yellow")) data = MIMEText(yamlLoad['SendInfo']['Body'], 'html') msg.attach(data) if args.v: print(colored("Message to be delivered: \n", "yellow")) print(colored(data, "white", "on_blue")) if args.p: try: payloadPath = args.p fp = open(payloadPath, 'rb') attach = MIMENonMultipart('application', 'exe') payload = base64.b64encode(fp.read()).decode('ascii') attach.set_payload(payload) attach['Content-Transfer-Encoding'] = 'base64' nameFile = yamlLoad['SendInfo']['Attachment'] attach.add_header('Content-Disposition', 'attachment', filename=nameFile) msg.attach(attach) fp.close() if args.v: print( colored("Name of attachment to be sent: " + nameFile, "yellow")) except: print(colored("Incorrect file path \n", "yellow")) if args.v: print(colored("Message created successfuly \n", "green")) message = msg.as_string() return message
def email_files(self): if os.getcwd() != self.filePathStorage: os.chdir(self.filePathStorage) try: # Changeable from the json object to_address = self.adr1 + ',' + self.adr2 + ',' + self.adr3 message = self.message subject = self.subject + " @" + str( self.current_date) # Added the date here since I needed it. files = [self.fileName1, self.fileName2, self.fileName3] server = smtplib.SMTP(str(self.host) + ":" + str(self.port)) server.starttls() server.login(self.host_usr, self.host_psw) # Setup the email header details msg = MIMEMultipart(From=self.host_usr, To=self.adr1 + ',' + self.adr2 + ',' + self.adr3, Date=formatdate(localtime=True), Subject=subject) # Setup backend email details msg['Subject'] = subject msg['To'] = self.adr1 + ',' + self.adr2 + ',' + self.adr3 msg.attach(MIMEText(message.replace('\\n', '\n'))) # Loop to attach all files in the files array for f in files: attachment = MIMENonMultipart('text', 'csv', charset='utf-8') attachment.set_payload(open(f, "rb").read()) encoders.encode_base64(attachment) attachment.add_header('Content-Disposition', 'attachment', filename=f) msg.attach(attachment) server.sendmail(self.host_usr, to_address, msg.as_string()) except smtplib.SMTPRecipientsRefused as e: print("Invalid address - {to_address}".format( to_address=self.adr1 + ',' + self.adr2 + ',' + self.adr3)) finally: print('Done') if server: server.quit()
def upload(self, filename): name = os.path.basename(filename) entry = self.get_info(name) if entry: self._delete(entry) #print "after check" size = os.path.getsize(filename) cype = guess_type(name) if not cype or not cype[0]: cype = "text/plain" else: cype = cype[0] url = "https://api.box.com/2.0/files/content" message = MIMEMultipart('mixed') # Message should not write out it's own headers. setattr(message, '_write_headers', lambda self: None) msg = MIMENonMultipart(*cype.split('/')) msg.add_header('Content-Disposition', 'form-data; name="f"; filename="%s"' % name) del msg["MIME-Version"] msg.set_payload(open(filename).read()) message.attach(msg) msg = MIMENonMultipart("text", "plain") msg.add_header('Content-Disposition', 'form-data; name="folder_id"') del msg["Content-Type"] del msg["MIME-Version"] msg.set_payload('0') message.attach(msg) body = message.as_string() #print body #return bd = message.get_boundary() hd = {"Content-Type": "multipart/form-data; boundary=%s" % bd} res = self.auth_http("POST", url, body, hd) ret = res.read() print(json.loads(ret)["entries"][0]['name'])
def to_message(message): text = None if message.body: text = MIMENonMultipart("text", "plain") payload = message.body ctenc = message.body_transfer_encoding if ctenc: payload = encode_string(ctenc, payload) text.add_header('Content-Transfer-Encoding', ctnec) text.set_payload(payload, message.body_charset) html = None if message.html: html = MIMENonMultipart("text", "html") payload = message.html ctenc = message.html_transfer_encoding if ctenc: payload = encode_string(ctenc, payload) html.add_header('Content-Transfer-Encoding', ctnec) html.set_payload(payload, message.html_charset) body = None if text and html: body = MIMEMultipart("alternative", _subparts=[html, text]) elif html: body = html elif text: body = text mail = None if len(message.attachments) > 1 or (body and message.attachments): mail = MIMEMultipart("mixed") if body: mail.attach(body) for attachment in message.attachments: mail.attach(attachment_to_message(attachment)) elif not body and message.attachments: mail = attachment_to_message(message.attachments[0]) elif body: mail = body return mail
def build_mms_body(metadata, attachments): """Build a MMS body based on metadata and attachments. MMS body is built as a multipart/mixed body whose first part is the metadata's JSON representation and the other parts are the attachments. """ body = MIMEMultipart(_subtype='mixed') # Add MMS metadata (root fields) as a json part part = MIMENonMultipart(_maintype='application', _subtype='json') part.add_header('Content-Transfer-Encoding', '8bit') part.set_payload(payload=json.dumps(metadata, ensure_ascii=False)) del(part['MIME-Version']) body.attach(part) for attachment in attachments: # Textual attachments if isinstance(attachment, basestring): part = MIMENonMultipart(_maintype='text', _subtype='plain') part.add_header('Content-Transfer-Encoding', '8bit') part.set_payload(payload=attachment, charset='utf-8') del(part['MIME-Version']) body.attach(part) # Binary attachments (image, audio or video) elif isinstance(attachment, (file, tuple, list)): if isinstance(attachment, file): mimetype = mimetypes.guess_type(attachment.name, strict=False)[0] payload = attachment.read() else: mimetype = attachment[0] payload = attachment[1] if not mimetype or not '/' in mimetype: error_str = "Invalid Content-Type '{0}' in attachment #{1}" raise ContentTypeError(error_str.format(mimetype, attachments.index(attachment))) maintype, subtype = mimetype.split('/') if not maintype in ('image', 'audio', 'video'): error_str = ("Unsupported Content-Type '{0}' in attachment #{1} " "(only image, audio or video are supported)") raise ContentTypeError(error_str.format(mimetype, attachments.index(attachment))) part = MIMENonMultipart(_maintype=maintype, _subtype=subtype) part.add_header('Content-Transfer-Encoding', 'binary') part.add_header('Content-Disposition', 'attachment') # , filename=os.path.basename(attachment.name)) part.set_payload(payload=payload) del(part['MIME-Version']) body.attach(part) return body
def get_content_block(self, f): binding_map = { '.xlsx': ('application', 'vnd.openxmlformats-officedocument.spreadsheetml.sheet'), '.xls': ('application', 'vnd.ms-excel'), '.csv': ('text', 'csv'), '.json': ('application', 'json'), '.syslog': ('text', 'syslog') } # Check the file extension to see if it is a supported type name_part, ext_part = os.path.splitext(f.name) if ext_part.lower() == '.xml': cb = tm11.ContentBlock(tm11.ContentBinding(t.CB_STIX_XML_101), f.read()) else: binding_tuple = binding_map.get(ext_part.lower(), None) if not binding_tuple: logger.error( 'File extension not supported: %s. Supported extensions: %s' % (ext_part, binding_map.keys())) return # Read the file and create a MIME message for it maintype = binding_tuple[0] subtype = binding_tuple[ 1] # Note: This is MIME subtype, not TAXII subtype mime_msg = MIMENonMultipart(maintype, subtype) mime_msg.add_header('Content-Disposition', 'attachment', filename=f.name) mime_msg.set_payload(f.read()) encode_base64(mime_msg) cb = tm11.ContentBlock('%s/%s' % (maintype, subtype), mime_msg.as_string()) return cb
def get_mime(cls, report, record, language): pool = Pool() Report = pool.get(report.report_name, type='report') with Transaction().set_context(language=language): ext, content, _, title = Report.execute([record.id], { 'action_id': report.id, }) name = '%s.%s' % (title, ext) mimetype, _ = mimetypes.guess_type(name) if mimetype: msg = MIMENonMultipart(*mimetype.split('/')) msg.set_payload(content) encode_base64(msg) else: msg = MIMEApplication(content) if not isinstance(name, str): name = name.encode('utf-8') if not isinstance(language, str): language = language.encode('utf-8') msg.add_header('Content-Disposition', 'attachment', filename=('utf-8', language, name)) return msg
def attach(self, name, data=None, maintype=None, subtype=None, inline=False): """Attach a file to this message. :param name: Path to the file to attach if data is None, or the name of the file if the ``data`` argument is given :param data: Contents of the file to attach, or None if the data is to be read from the file pointed to by the ``name`` argument :type data: bytes or a file-like object :param maintype: First part of the MIME type of the file -- will be automatically guessed if not given :param subtype: Second part of the MIME type of the file -- will be automatically guessed if not given :param inline: Whether to set the Content-Disposition for the file to "inline" (True) or "attachment" (False) """ self._dirty = True if not maintype: maintype, _ = guess_type(name) if not maintype: maintype, subtype = 'application', 'octet-stream' else: maintype, _, subtype = maintype.partition('/') part = MIMENonMultipart(maintype, subtype) if data is None: with open(name, 'rb') as fp: part.set_payload(fp.read()) name = os.path.basename(name) elif isinstance(data, bytes): part.set_payload(data) elif hasattr(data, 'read'): part.set_payload(data.read()) else: raise TypeError("Unable to read attachment contents") if inline: part.add_header('Content-Disposition', 'inline', filename=name) part.add_header('Content-ID', '<%s>' % name) self.embedded.append(part) else: part.add_header('Content-Disposition', 'attachment', filename=name) self.attachments.append(part)
def attach(self, name, data=None, maintype=None, subtype=None, inline=False): """Attach a file to this message. :param name: Path to the file to attach if data is None, or the name of the file if the ``data`` argument is given :param data: Contents of the file to attach, or None if the data is to be read from the file pointed to by the ``name`` argument :type data: bytes or a file-like object :param maintype: First part of the MIME type of the file -- will be automatically guessed if not given :param subtype: Second part of the MIME type of the file -- will be automatically guessed if not given :param inline: Whether to set the Content-Disposition for the file to "inline" (True) or "attachment" (False) """ self._dirty = True if not maintype: maintype, _ = guess_type(name) if not maintype: maintype, subtype = "application", "octet-stream" else: maintype, _, subtype = maintype.partition("/") part = MIMENonMultipart(maintype, subtype) if data is None: with open(name, "rb") as fp: part.set_payload(fp.read()) name = os.path.basename(name) elif isinstance(data, bytes): part.set_payload(data) elif hasattr(data, "read"): part.set_payload(data.read()) else: raise TypeError("Unable to read attachment contents") if inline: part.add_header("Content-Disposition", "inline", filename=name) part.add_header("Content-ID", "<%s>" % name) self.embedded.append(part) else: part.add_header("Content-Disposition", "attachment", filename=name) self.attachments.append(part)
def attachment_to_message(attachment): mtype, stype = attachment.content_type.split('/') if attachment.filename: msg = MIMENonMultipart(mtype, stype, name=attachment.filename) else: msg = MIMENonMultipart(mtype, stype) if attachment.disposition: if attachment.filename: msg.add_header('Content-Dispsition', attachment.disposition, filename=attachment.filename) else: msg.add_header('Content-Disposition', attachment.disposition) payload = attachment.data ctenc = attachment.transfer_encoding if ctenc: payload = encode_string(ctenc, payload) msg.add_header('Content-Transfer-Encoding', ctenc) msg.set_payload(payload, attachment.charset) return msg
def submit(self): """Submit a query and parse the response. @return: The data retrieved from api.php (a dict) """ paramstring = self.http_params() while True: action = self.params.get("action", "") simulate = self._simulate(action) if simulate: return simulate self.site.throttle(write=self.write) uri = self.site.scriptpath() + "/api.php" ssl = False if self.site.family.name in config.available_ssl_project: if action == "login" and config.use_SSL_onlogin: ssl = True elif config.use_SSL_always: ssl = True try: if self.mime: # construct a MIME message containing all API key/values container = MIMEMultipart(_subtype='form-data') for key in self.params: # key "file" requires special treatment in a multipart # message if key == "file": local_filename = self.params[key] filetype = mimetypes.guess_type(local_filename)[0] \ or 'application/octet-stream' file_content = file(local_filename, "rb").read() submsg = MIMENonMultipart(*filetype.split("/")) submsg.add_header("Content-disposition", "form-data", name=key, filename=local_filename) submsg.set_payload(file_content) else: try: self.params[key].encode("ascii") keytype = ("text", "plain") except UnicodeError: keytype = ("application", "octet-stream") submsg = MIMENonMultipart(*keytype) submsg.add_header("Content-disposition", "form-data", name=key) submsg.set_payload(self.params[key]) container.attach(submsg) # strip the headers to get the HTTP message body body = container.as_string() marker = "\n\n" # separates headers from body eoh = body.find(marker) body = body[ eoh + len(marker): ] # retrieve the headers from the MIME object mimehead = dict(container.items()) rawdata = http.request(self.site, uri, ssl, method="POST", headers=mimehead, body=body) else: rawdata = http.request(self.site, uri, ssl, method="POST", headers={'Content-Type': 'application/x-www-form-urlencoded'}, body=paramstring) ## import traceback ## traceback.print_stack() ## print rawdata except Server504Error: pywikibot.log(u"Caught HTTP 504 error; retrying") self.wait() continue #TODO: what other exceptions can occur here? except Exception, e: # for any other error on the http request, wait and retry pywikibot.error(traceback.format_exc()) pywikibot.log(u"%s, %s" % (uri, paramstring)) self.wait() continue if not isinstance(rawdata, unicode): rawdata = rawdata.decode(self.site.encoding()) pywikibot.debug(u"API response received:\n" + rawdata, _logger) if rawdata.startswith(u"unknown_action"): raise APIError(rawdata[:14], rawdata[16:]) try: result = json.loads(rawdata) except ValueError: # if the result isn't valid JSON, there must be a server # problem. Wait a few seconds and try again pywikibot.warning( "Non-JSON response received from server %s; the server may be down." % self.site) pywikibot.debug(rawdata, _logger) # there might also be an overflow, so try a smaller limit for param in self.params: if param.endswith("limit"): value = self.params[param] try: self.params[param] = str(int(value) // 2) pywikibot.output(u"Set %s = %s" % (param, self.params[param])) except: pass self.wait() continue if not result: result = {} if type(result) is not dict: raise APIError("Unknown", "Unable to process query response of type %s." % type(result), {'data': result}) if self['action'] == 'query': if 'userinfo' in result.get('query', ()): if hasattr(self.site, '_userinfo'): self.site._userinfo.update(result['query']['userinfo']) else: self.site._userinfo = result['query']['userinfo'] status = self.site._loginstatus # save previous login status if ( ("error" in result and result["error"]["code"].endswith("limit")) or (status >= 0 and self.site._userinfo['name'] != self.site._username[status])): # user is no longer logged in (session expired?) # reset userinfo, then make user log in again del self.site._userinfo self.site._loginstatus = -1 if status < 0: status = 0 # default to non-sysop login self.site.login(status) # retry the previous query continue if "warnings" in result: modules = [k for k in result["warnings"] if k != "info"] for mod in modules: if '*' in result["warnings"][mod]: text = result["warnings"][mod]['*'] elif 'html' in result["warnings"][mod]: # Bugzilla 49978 text = result["warnings"][mod]['html']['*'] else: # This is just a warning, we shouldn't raise an # exception because of it continue pywikibot.warning( u"API warning (%s): %s" % (mod, text)) if "error" not in result: return result if "*" in result["error"]: # help text returned result['error']['help'] = result['error'].pop("*") code = result["error"].pop("code", "Unknown") info = result["error"].pop("info", None) if code == "maxlag": lag = lagpattern.search(info) if lag: pywikibot.log( u"Pausing due to database lag: " + info) self.site.throttle.lag(int(lag.group("lag"))) continue if code in (u'internal_api_error_DBConnectionError', ): self.wait() continue # raise error try: pywikibot.log(u"API Error: query=\n%s" % pprint.pformat(self.params)) pywikibot.log(u" response=\n%s" % result) raise APIError(code, info, **result["error"]) except TypeError: raise RuntimeError(result)
def attach(self, name, data=None, maintype=None, subtype=None, inline=False, filename=None, filename_charset='', filename_language='', encoding=None): """Attach a file to this message. :param name: Path to the file to attach if data is None, or the name of the file if the ``data`` argument is given :param data: Contents of the file to attach, or None if the data is to be read from the file pointed to by the ``name`` argument :type data: bytes or a file-like object :param maintype: First part of the MIME type of the file -- will be automatically guessed if not given :param subtype: Second part of the MIME type of the file -- will be automatically guessed if not given :param inline: Whether to set the Content-Disposition for the file to "inline" (True) or "attachment" (False) :param filename: The file name of the attached file as seen by the user in his/her mail client. :param filename_charset: Charset used for the filename paramenter. Allows for attachment names with characters from UTF-8 or Latin 1. See RFC 2231. :param filename_language: Used to specify what language the filename is in. See RFC 2231. :param encoding: Value of the Content-Encoding MIME header (e.g. "gzip" in case of .tar.gz, but usually empty) """ self._dirty = True if not maintype: maintype, guessed_encoding = guess_type(name) encoding = encoding or guessed_encoding if not maintype: maintype, subtype = 'application', 'octet-stream' else: maintype, _, subtype = maintype.partition('/') part = MIMENonMultipart(maintype, subtype) part.add_header('Content-Transfer-Encoding', 'base64') if encoding: part.add_header('Content-Encoding', encoding) if data is None: with open(name, 'rb') as fp: value = fp.read() name = os.path.basename(name) elif isinstance(data, bytes): value = data elif hasattr(data, 'read'): value = data.read() else: raise TypeError("Unable to read attachment contents") part.set_payload(base64.encodestring(value)) if not filename: filename = name filename = os.path.basename(filename) if filename_charset or filename_language: if not filename_charset: filename_charset = 'utf-8' # See https://docs.python.org/2/library/email.message.html#email.message.Message.add_header # for more information. # add_header() in the email module expects its arguments to be ASCII strings. Go ahead and handle # the case where these arguments come in as unicode strings, since encoding ASCII strings # as UTF-8 can't hurt. if sys.version_info < (3, 0): filename = (filename_charset.encode('utf-8'), filename_language.encode('utf-8'), filename.encode('utf-8')) else: filename = (filename_charset, filename_language, filename) if inline: if sys.version_info < (3, 0): part.add_header('Content-Disposition'.encode('utf-8'), 'inline'.encode('utf-8'), filename=filename) part.add_header('Content-ID'.encode('utf-8'), '<%s>'.encode('utf-8') % filename) else: part.add_header('Content-Disposition', 'inline', filename=filename) part.add_header('Content-ID', '<%s>' % filename) self.embedded.append(part) else: if sys.version_info < (3, 0): part.add_header('Content-Disposition'.encode('utf-8'), 'attachment'.encode('utf-8'), filename=filename) else: part.add_header('Content-Disposition', 'attachment', filename=filename) self.attachments.append(part)
def build_email(mail_to, subject, body_text, mail_from='*****@*****.**', reply_to=None, attachments=None, mime_headers=None): """ Flexible Multipart MIME message builder. Implements message building using the "email" Python standard library https://docs.python.org/2/library/email-examples.html while following recommendations from https://stackoverflow.com/questions/3902455/smtp-multipart-alternative-vs-multipart-mixed .. seealso:: - http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52243 - http://mail.python.org/pipermail/tutor/1999-June/000259.html - http://www.bigbold.com/snippets/posts/show/2038 """ attachments = attachments or {} mime_headers = mime_headers or {} # ------------------------------------------ # envelope # ------------------------------------------ message = MIMEMultipart('mixed') # TODO: Add text for non MIME-aware MUAs #message.preamble = 'You will not see this in a MIME-aware mail reader.\n' # Address headers address_headers = { 'To': fix_addresslist(AddressList(mail_to)), 'From': AddressList(mail_from), 'Reply-To': AddressList(reply_to), } # Subject header mime_headers.update({'Subject': Header(s=subject, charset='utf-8')}) # Add address headers for key, item in address_headers.items(): if isinstance(item, AddressList): # v1 #for address in format_addresslist(item): # message[key] = address # v2 value = ', '.join(format_addresslist(item)) if value: message[key] = value # Add more headers for key, value in mime_headers.items(): #message.add_header(key, value) if value: message[key] = value # ------------------------------------------ # email body # ------------------------------------------ body_message = MIMEMultipart('alternative') # Start off with a text/plain part # https://stackoverflow.com/questions/3902455/smtp-multipart-alternative-vs-multipart-mixed body_part1 = MIMEText(body_text, _subtype='plain', _charset='utf-8') #body_part1.set_payload(body_text) #body_part1.set_charset('utf-8') body_message.attach(body_part1) message.attach(body_message) # TODO: Add a text/html part #body_part2 = MIMEText(body_html, 'html') # ------------------------------------------ # multipart attachments # ------------------------------------------ # from https://docs.python.org/2/library/email-examples.html for filename, payload in attachments.items(): # Guess the content type based on the file's extension. Encoding # will be ignored, although we should check for simple things like # gzip'd or compressed files. ctype, encoding = mimetypes.guess_type(filename, strict=False) #print('ctype, encoding:', ctype, encoding) if ctype is None or encoding is not None: # No guess could be made, or the file is encoded (compressed), so # use a generic bag-of-bits type. ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) #print('maintype, subtype:', maintype, subtype) # Create proper MIME part by maintype if maintype == 'application' and subtype in ['xml', 'json']: part = MIMENonMultipart(maintype, subtype, charset='utf-8') part.set_payload(payload.encode('utf-8'), 'utf-8') elif maintype == 'text': part = MIMEText(payload.encode('utf-8'), _subtype=subtype, _charset='utf-8') #part.set_charset('utf-8') elif maintype == 'image': part = MIMEImage(payload, _subtype=subtype) elif maintype == 'audio': part = MIMEAudio(payload, _subtype=subtype) else: part = MIMEBase(maintype, subtype) part.set_payload(payload) # Encode the payload using Base64 (Content-Transfer-Encoding) encoders.encode_base64(part) #part = MIMEBase(maintype, subtype, _charset='utf-8') # replace forward slashes by dashes filename_attachment = filename.lstrip('/\\').replace('/', '-') part.add_header('Content-Disposition', 'attachment', filename=filename_attachment.encode('utf-8')) #part.set_payload(payload.encode('utf-8')) #part.set_charset('utf-8') # Encode the payload using Base64 (Content-Transfer-Encoding) #encoders.encode_base64(part) # Add part to multipart message message.attach(part) payload = message.as_string() return payload
def attach(self, name, data=None, maintype=None, subtype=None, inline=False, filename=None, filename_charset='', filename_language='', encoding=None): """Attach a file to this message. :param name: Path to the file to attach if data is None, or the name of the file if the ``data`` argument is given :param data: Contents of the file to attach, or None if the data is to be read from the file pointed to by the ``name`` argument :type data: bytes or a file-like object :param maintype: First part of the MIME type of the file -- will be automatically guessed if not given :param subtype: Second part of the MIME type of the file -- will be automatically guessed if not given :param inline: Whether to set the Content-Disposition for the file to "inline" (True) or "attachment" (False) :param filename: The file name of the attached file as seen by the user in his/her mail client. :param filename_charset: Charset used for the filename paramenter. Allows for attachment names with characters from UTF-8 or Latin 1. See RFC 2231. :param filename_language: Used to specify what language the filename is in. See RFC 2231. :param encoding: Value of the Content-Encoding MIME header (e.g. "gzip" in case of .tar.gz, but usually empty) """ self._dirty = True if not maintype: maintype, guessed_encoding = guess_type(name) encoding = encoding or guessed_encoding if not maintype: maintype, subtype = 'application', 'octet-stream' else: maintype, _, subtype = maintype.partition('/') part = MIMENonMultipart(maintype, subtype) part.add_header('Content-Transfer-Encoding', 'base64') if encoding: part.add_header('Content-Encoding', encoding) if data is None: with open(name, 'rb') as fp: value = fp.read() name = os.path.basename(name) elif isinstance(data, bytes): value = data elif hasattr(data, 'read'): value = data.read() else: raise TypeError("Unable to read attachment contents") part.set_payload(base64.encodestring(value)) if not filename: filename = name filename = os.path.basename(filename) if filename_charset or filename_language: if not filename_charset: filename_charset = 'utf-8' # See https://docs.python.org/2/library/email.message.html#email.message.Message.add_header # for more information. # add_header() in the email module expects its arguments to be ASCII strings. Go ahead and handle # the case where these arguments come in as unicode strings, since encoding ASCII strings # as UTF-8 can't hurt. if sys.version_info < (3, 0): filename=(filename_charset.encode('utf-8'), filename_language.encode('utf-8'), filename.encode('utf-8')) else: filename=(filename_charset, filename_language, filename) if inline: part.add_header('Content-Disposition', 'inline', filename=filename) part.add_header('Content-ID', '<%s>' % filename) self.embedded.append(part) else: part.add_header('Content-Disposition', 'attachment', filename=filename) self.attachments.append(part)
def _send_batch_request(self, requests): """Sends a batch of requests to the server and processes the HTTP responses. Args: requests: List of GoogleComputeEngineBase.API_REQUEST named tuples. Must contain <= MAX_BATCH_SIZE elements. Raises: ValueError: If requests has more than MAX_BATCH_SIZE elements. Returns: List of GoogleComputeEngineBase.BATCH_RESPONSE named tuples, one for each element of request parameter. """ if len(requests) > MAX_BATCH_SIZE: raise ValueError('Too many requests provided' '(maximum is {0})'.format(MAX_BATCH_SIZE)) batch = _BatchApiRequest() base = urlparse.urlsplit(self.base_url) base_path = base.path.rstrip('/') for i, request in enumerate(requests): msg = MIMENonMultipart('application', 'http') msg.add_header('Content-ID', '<{0}>'.format(i)) msg.set_payload( self._serialize_batch_api_request(base_path, request)) batch.attach(msg) batch_string = batch.as_string() content_type = 'multipart/mixed; boundary="{0}"'.format( batch.get_boundary()) url = urlparse.urlunsplit((base.scheme, base.netloc, 'batch', self._create_url_query(None), None)) response, data = self._send_request(url, 'POST', batch_string, content_type) if response.status >= 300: error = gce.GceError(message=response.reason, status=response.status) return [error] * len(requests) # Return all errors. elif not data: error = gce.GceError(message='Server returned no data', status=response.status) return [error] * len(requests) # Return all errors. # Process successful response. data = 'content-type: {0}\r\n\r\n'.format( response['content-type']) + data parser = FeedParser() parser.feed(data) response = parser.close() responses = [] for part in response.get_payload(): responses.append( (int(RESPONSE_ID_REGEX.match(part['Content-ID']).group(1)), self._parse_batch_api_response(part.get_payload()))) responses.sort(key=lambda r: r[0]) return [r[1] for r in responses]
}, PURPOSE_SET_PASSWORD: { 'urlname': 'ResetPasswordConfirmation', 'subject': _l('Reset the password for your %(domain)s account'), 'template': 'reset/password-mail', }, PURPOSE_DELETE: { 'urlname': 'DeleteConfirmation', 'subject': _l('Delete your account on %(domain)s'), 'template': 'delete/mail', }, } log = logging.getLogger(__name__) pgp_version = MIMENonMultipart('application', 'pgp-encrypted') pgp_version.add_header('Content-Description', 'PGP/MIME version identification') pgp_version.set_payload('Version: 1\n') @python_2_unicode_compatible class RegistrationUser(AbstractBaseUser): # NOTE: MySQL only allows a 255 character limit jid = models.CharField(max_length=255, unique=True, verbose_name='JID') email = models.EmailField(null=True, blank=True) gpg_fingerprint = models.CharField(max_length=40, null=True, blank=True) # when the account was first registered registered = models.DateTimeField(auto_now_add=True) registration_method = models.SmallIntegerField(choices=REGISTRATION_CHOICES) # when the email was confirmed
def mock_send_request(path, method, body, content_type): self.assertEqual('POST', method) self.assertEqual('https://www.googleapis.com/batch', path) match = re.match('multipart/mixed; boundary="([^\"]+)"', content_type) self.assertTrue(match) parts = body.split('--{0}'.format(match.group(1))) self.assertEqual(gce_base.MAX_BATCH_SIZE + 2, len(parts)) self.assertEqual('', parts[0]) self.assertEqual('--', parts[-1]) parts = parts[1:-1] responses = [] for part in parts: headers, payload = part.split('\n\n', 1) headers = parse_headers(headers) self.assertEqual('application/http', headers['Content-Type']) content_id = headers['Content-ID'] self.assertTrue( content_id.startswith('<') and content_id.endswith('>')) content_id = content_id[1:-1] http_headers = payload.split('\n\n', 1)[0] split = http_headers.split( '\n', 1) # Try to split off the http command http_request = split[0] if len(split) > 1: headers = parse_headers(split[1]) verb, path = http_request.split(' ') self.assertEqual('GET', verb) name = re.match('.*/([^/]+)', path).group(1) payload = '{{ "kind": "compute#instance", "name": "{0}" }}'.format( name) msg = MIMENonMultipart('application', 'http') msg.add_header('Content-ID', '<response-{0}>'.format(content_id)) msg.set_payload( 'HTTP/1.1 200 OK\n' 'Content-Type: application/json; charset=UTF-8\n' 'Content-Length: {0}\n\n' '{1}'.format(len(payload), payload)) responses.append(msg) random.shuffle(responses) response = gce_base._BatchApiRequest() for r in responses: response.attach(r) response_string = response.as_string() boundary = response.get_boundary() response = httplib2.Response({ 'content-type': 'multipart/mixed; boundary="{0}"'.format(boundary), 'status': 200, 'reason': 'OK' }) return response, response_string
def prepare_email_message(self): """ Returns a django ``EmailMessage`` or ``EmailMultiAlternatives`` object, depending on whether html_message is empty. """ if get_override_recipients(): self.to = get_override_recipients() if self.template is not None: engine = get_template_engine() subject = engine.from_string(self.template.subject).render( self.context) plaintext_message = engine.from_string( self.template.content).render(self.context) multipart_template = engine.from_string(self.template.html_content) html_message = multipart_template.render(self.context) else: subject = smart_str(self.subject) plaintext_message = self.message multipart_template = None html_message = self.html_message connection = connections[self.backend_alias or 'default'] if isinstance(self.headers, dict) or self.expires_at: headers = dict(self.headers or {}) if self.expires_at: headers.update({ 'Expires': self.expires_at.strftime("%a, %-d %b %H:%M:%S %z") }) else: headers = None if html_message: if plaintext_message: msg = EmailMultiAlternatives(subject=subject, body=plaintext_message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=headers, connection=connection) msg.attach_alternative(html_message, "text/html") else: msg = EmailMultiAlternatives(subject=subject, body=html_message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=headers, connection=connection) msg.content_subtype = 'html' if hasattr(multipart_template, 'attach_related'): multipart_template.attach_related(msg) else: msg = EmailMessage(subject=subject, body=plaintext_message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=headers, connection=connection) for attachment in self.attachments.all(): if attachment.headers: mime_part = MIMENonMultipart(*attachment.mimetype.split('/')) mime_part.set_payload(attachment.file.read()) for key, val in attachment.headers.items(): try: mime_part.replace_header(key, val) except KeyError: mime_part.add_header(key, val) msg.attach(mime_part) else: msg.attach(attachment.name, attachment.file.read(), mimetype=attachment.mimetype or None) attachment.file.close() self._cached_email_message = msg return msg
def submit(self): """Submit a query and parse the response. @return: The data retrieved from api.php (a dict) """ while True: paramstring = self.http_params() action = self.params.get("action", "") simulate = self._simulate(action) if simulate: return simulate self.site.throttle(write=self.write) uri = self.site.scriptpath() + "/api.php" ssl = False if self.site.family.name in config.available_ssl_project: if action == "login" and config.use_SSL_onlogin: ssl = True elif config.use_SSL_always: ssl = True try: if self.mime: # construct a MIME message containing all API key/values container = MIMEMultipart(_subtype='form-data') for key in self.params: # key "file" requires special treatment in a multipart # message if key == "file": local_filename = self.params[key] filetype = mimetypes.guess_type(local_filename)[0] \ or 'application/octet-stream' file_content = file(local_filename, "rb").read() submsg = MIMENonMultipart(*filetype.split("/")) submsg.add_header("Content-disposition", "form-data", name=key, filename=local_filename) submsg.set_payload(file_content) else: try: self.params[key].encode("ascii") keytype = ("text", "plain") except UnicodeError: keytype = ("application", "octet-stream") submsg = MIMENonMultipart(*keytype) submsg.add_header("Content-disposition", "form-data", name=key) submsg.set_payload(self.params[key]) container.attach(submsg) # strip the headers to get the HTTP message body body = container.as_string() marker = "\n\n" # separates headers from body eoh = body.find(marker) body = body[eoh + len(marker):] # retrieve the headers from the MIME object mimehead = dict(list(container.items())) rawdata = http.request(self.site, uri, ssl, method="POST", headers=mimehead, body=body) else: rawdata = http.request( self.site, uri, ssl, method="POST", headers={ 'Content-Type': 'application/x-www-form-urlencoded' }, body=paramstring) # import traceback # traceback.print_stack() # print rawdata except Server504Error: pywikibot.log(u"Caught HTTP 504 error; retrying") self.wait() continue except FatalServerError: # This error is not going to be fixed by just waiting pywikibot.error(traceback.format_exc()) raise # TODO: what other exceptions can occur here? except Exception: # for any other error on the http request, wait and retry pywikibot.error(traceback.format_exc()) pywikibot.log(u"%s, %s" % (uri, paramstring)) self.wait() continue if not isinstance(rawdata, unicode): rawdata = rawdata.decode(self.site.encoding()) pywikibot.debug(u"API response received:\n" + rawdata, _logger) if rawdata.startswith(u"unknown_action"): raise APIError(rawdata[:14], rawdata[16:]) try: result = json.loads(rawdata) except ValueError: # if the result isn't valid JSON, there must be a server # problem. Wait a few seconds and try again pywikibot.warning( "Non-JSON response received from server %s; the server may be down." % self.site) pywikibot.debug(rawdata, _logger) # there might also be an overflow, so try a smaller limit for param in self.params: if param.endswith("limit"): value = self.params[param] try: self.params[param] = str(int(value) // 2) pywikibot.output(u"Set %s = %s" % (param, self.params[param])) except: pass self.wait() continue if not result: result = {} if not isinstance(result, dict): raise APIError("Unknown", "Unable to process query response of type %s." % type(result), data=result) if self['action'] == 'query': if 'userinfo' in result.get('query', ()): if hasattr(self.site, '_userinfo'): self.site._userinfo.update(result['query']['userinfo']) else: self.site._userinfo = result['query']['userinfo'] status = self.site._loginstatus # save previous login status if (("error" in result and result["error"]["code"].endswith("limit")) or (status >= 0 and self.site._userinfo['name'] != self.site._username[status])): # user is no longer logged in (session expired?) # reset userinfo, then make user log in again del self.site._userinfo self.site._loginstatus = -1 if status < 0: status = 0 # default to non-sysop login self.site.login(status) # retry the previous query continue if "warnings" in result: modules = [k for k in result["warnings"] if k != "info"] for mod in modules: if '*' in result["warnings"][mod]: text = result["warnings"][mod]['*'] elif 'html' in result["warnings"][mod]: # Bugzilla 49978 text = result["warnings"][mod]['html']['*'] else: # This is just a warning, we shouldn't raise an # exception because of it continue pywikibot.warning(u"API warning (%s): %s" % (mod, text)) if "error" not in result: return result if "*" in result["error"]: # help text returned result['error']['help'] = result['error'].pop("*") code = result["error"].pop("code", "Unknown") info = result["error"].pop("info", None) if code == "maxlag": lag = lagpattern.search(info) if lag: pywikibot.log(u"Pausing due to database lag: " + info) self.site.throttle.lag(int(lag.group("lag"))) continue if code.startswith(u'internal_api_error_'): self.wait() continue # bugs 46535, 62126, 64494 # maybe removed when it 46535 is solved if code == "failed-save" and action == 'wbeditentity': try: message = result["error"]["messages"]["0"]["name"] except KeyError: message = None if message == u'edit-already-exists': self.wait() continue # raise error try: pywikibot.log(u"API Error: query=\n%s" % pprint.pformat(self.params)) pywikibot.log(u" response=\n%s" % result) raise APIError(code, info, **result["error"]) except TypeError: raise RuntimeError(result)
'subject': _('Your new account on %(domain)s'), }, NEW_PURPOSE_SET_PASSWORD: { 'subject': _('Reset the password for your %(domain)s account'), }, NEW_PURPOSE_SET_EMAIL: { 'subject': _l('Confirm the email address for your %(domain)s account'), }, NEW_PURPOSE_DELETE: { 'subject': _l('Delete your account on %(domain)s'), }, } log = logging.getLogger(__name__) pgp_version = MIMENonMultipart('application', 'pgp-encrypted') pgp_version.add_header('Content-Description', 'PGP/MIME version identification') pgp_version.set_payload('Version: 1\n') @python_2_unicode_compatible class RegistrationUser(XmppBackendUser): # NOTE: MySQL only allows a 255 character limit jid = models.CharField(max_length=255, unique=True, verbose_name='JID') email = models.EmailField(null=True, blank=True) gpg_fingerprint = models.CharField(max_length=40, null=True, blank=True) # when the account was first registered registered = models.DateTimeField(auto_now_add=True) registration_method = models.SmallIntegerField( choices=REGISTRATION_CHOICES)
def send(cls, to='', cc='', bcc='', subject='', body='', files=None, record=None, reports=None, attachments=None): pool = Pool() User = pool.get('res.user') ActionReport = pool.get('ir.action.report') Attachment = pool.get('ir.attachment') transaction = Transaction() user = User(transaction.user) Model = pool.get(record[0]) record = Model(record[1]) body_html = HTML_EMAIL % { 'subject': subject, 'body': body, 'signature': user.signature or '', } content = MIMEMultipart('alternative') if html2text: body_text = HTML_EMAIL % { 'subject': subject, 'body': body, 'signature': '', } converter = html2text.HTML2Text() body_text = converter.handle(body_text) if user.signature: body_text += '\n-- \n' + converter.handle(user.signature) part = MIMEText(body_text, 'plain', _charset='utf-8') content.attach(part) part = MIMEText(body_html, 'html', _charset='utf-8') content.attach(part) if files or reports or attachments: msg = MIMEMultipart('mixed') msg.attach(content) if files is None: files = [] else: files = list(files) for report_id in (reports or []): report = ActionReport(report_id) Report = pool.get(report.report_name, type='report') ext, content, _, title = Report.execute([record.id], { 'action_id': report.id, }) name = '%s.%s' % (title, ext) if isinstance(content, str): content = content.encode('utf-8') files.append((name, content)) if attachments: files += [(a.name, a.data) for a in Attachment.browse(attachments)] for name, data in files: mimetype, _ = mimetypes.guess_type(name) if mimetype: attachment = MIMENonMultipart(*mimetype.split('/')) attachment.set_payload(data) encode_base64(attachment) else: attachment = MIMEApplication(data) attachment.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', name)) msg.attach(attachment) else: msg = content from_ = config.get('email', 'from') set_from_header(msg, from_, user.email or from_) msg['To'] = ', '.join(formataddr(a) for a in getaddresses([to])) msg['Cc'] = ', '.join(formataddr(a) for a in getaddresses([cc])) msg['Subject'] = Header(subject, 'utf-8') to_addrs = list( filter( None, map(str.strip, _get_emails(to) + _get_emails(cc) + _get_emails(bcc)))) sendmail_transactional(from_, to_addrs, msg, datamanager=SMTPDataManager(strict=True)) email = cls(recipients=to, recipients_secondary=cc, recipients_hidden=bcc, addresses=[{ 'address': a } for a in to_addrs], subject=subject, body=body, resource=record) email.save() with Transaction().set_context(_check_access=False): attachments_ = [] for name, data in files: attachments_.append( Attachment(resource=email, name=name, data=data)) Attachment.save(attachments_) return email
def send_email(smtp, recipients, cc, subject, content, csv_reports): """Sends an email with attachment. Refer to https://gist.github.com/BietteMaxime/f75ae41f7b4557274a9f Args: smtp: A dictionary containing smtp info: - smtp_url - smtp_auth_username # optional - smtp_auth_password # optional - smtp_from recipients: To whom to send the email. cc: To whom to cc the email. subject: Email subject. content: Email body content csv_reports: List of dictionaries containing "filename", "data" to construct CSV attachments. Returns: None """ if not isinstance(smtp, dict): logger.warning("smtp is not a dictionary. Skip.") return sender = smtp.get("smtp_from", None) smtp_url = smtp.get("smtp_url", None) smtp_auth_username = smtp.get("smtp_auth_username", None) smtp_auth_password = smtp.get("smtp_auth_password", None) if sender is None or smtp_url is None: logger.warning("Some fields in smtp %s is None. Skip.", smtp) return # Create message container - the correct MIME type is multipart/mixed # to allow attachment. full_email = MIMEMultipart("mixed") full_email["Subject"] = subject full_email["From"] = sender full_email["To"] = ", ".join(recipients) full_email["CC"] = ", ".join(cc) # Create the body of the message (a plain-text version). content = content.encode(ENCODING) content = MIMEText(content, "plain", _charset=ENCODING) full_email.attach(content) # Create the attachment of the message in text/csv. for report in csv_reports: attachment = MIMENonMultipart("text", "csv", charset=ENCODING) attachment.add_header("Content-Disposition", "attachment", filename=report["filename"]) cs = Charset(ENCODING) cs.body_encoding = BASE64 attachment.set_payload(report["data"].encode(ENCODING), charset=cs) full_email.attach(attachment) try: with smtplib.SMTP(smtp_url) as server: if smtp_auth_username is not None and smtp_auth_password is not None: server.starttls() server.login(smtp_auth_username, smtp_auth_password) receivers = recipients + cc server.sendmail(sender, receivers, full_email.as_string()) logger.info("Successfully sent email to %s and cc %s", ", ".join(recipients), ", ".join(cc)) except smtplib.SMTPAuthenticationError: logger.warning("The server didn\'t accept the user\\password " "combination.") except smtplib.SMTPServerDisconnected: logger.warning("Server unexpectedly disconnected") except smtplib.SMTPException as e: logger.exception("SMTP error occurred: %s", e)
def pgp_version(self): pgp_version = MIMENonMultipart('application', 'pgp-encrypted') pgp_version.add_header('Content-Description', 'PGP/MIME version identification') pgp_version.set_payload('Version: 1\n') return pgp_version