def mail(to, subject, text, attach=None, attach1=None): msg = MIMEMultipart() msg['From'] = gmail_user msg['To'] = to msg['Subject'] = subject msg.add_header('Content-Type','text/html') msg.attach(MIMEText(text, 'html')) #msg.attach(text) if attach: part = MIMEBase('application', 'octet-stream') part.set_payload(open(attach, 'rb').read()) encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(attach)) msg.attach(part) if attach1: part = MIMEBase('application', 'octet-stream') part.set_payload(open(attach1, 'rb').read()) encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(attach1)) msg.attach(part) mailServer = smtplib.SMTP("smtp.gmail.com", 587) mailServer.ehlo() mailServer.starttls() mailServer.ehlo() mailServer.login(gmail_user, gmail_pwd) mailServer.sendmail(gmail_user, to, msg.as_string()) mailServer.close()
class Mail: def __init__(self, to, subject, text, html, reply_to=""): self.smtp_server = settings.EMAIL_HOST self.sender = settings.EMAIL_HOST_USER self.sender_password = settings.EMAIL_HOST_PASSWORD self.receiver = to # Compose Email self.msg = MIMEMultipart('alternative') self.msg['Subject'] = subject self.msg['From'] = self.sender self.msg['To'] = self.receiver if reply_to: self.msg.add_header('reply-to', reply_to) # Attach parts into message container. # According to RFC 2046, the last part of a multipart message, in this case # the HTML message, is best and preferred. self.msg.attach(MIMEText(text, 'plain')) self.msg.attach(MIMEText(html, 'html')) def send(self): self.smtp = smtplib.SMTP_SSL(self.smtp_server) self.smtp.login(self.sender, self.sender_password) self.smtp.sendmail(self.sender, self.receiver, self.msg.as_string()) self.smtp.quit()
def send_email_to_kindle(receiver, filename): sender = "*****@*****.**" password = '******' smtp_server = 'smtp.126.com' msg = MIMEMultipart('related') msg['Subject'] = filename filepath = os.path.join(os.getcwd(), "static/book/" + filename) with open(filepath, "rb") as fp: file = fp.read() msg.set_payload(file, charset="utf-8") msg.add_header("Content-Type", "application/octet-stream") msg.add_header("Content-Disposition", "attachment", filename = filename) smtp = smtplib.SMTP(smtp_server) # smtp.connect('smtp.126.com') smtp.login(sender, password) # smtp.set_debuglevel(1) try: smtp.sendmail(sender, receiver, msg.as_string()) except Exception as e: print("fail") else: print("ok") finally: smtp.quit()
def email_msg(subject, msg_to, text, html): msg_from = '"Pager Duty Scheduling"' # Create message container - the correct MIME type is multipart/alternative. msg = MIMEMultipart("alternative") msg["Subject"] = subject msg["From"] = msg_from msg["To"] = "" if reply_to: msg.add_header("reply-to", reply_to) # Setup bcc email addresses bcc = [""] msg_to = filter(None, msg_to + bcc) part1 = MIMEText(text, "plain") msg.attach(part1) part2 = MIMEText(html, "html") msg.attach(part2) # Send the message via gmail SMTP server. s = smtplib.SMTP(config.get("SMTP", "server")) s.starttls() s.login(config.get("SMTP", "email"), config.get("SMTP", "password")) s.sendmail(msg_from, msg_to, msg.as_string()) s.quit()
def sendmail(new, sum): # me == my email address # you == recipient's email address me = "*****@*****.**" you = new.user_email # Create message container - the correct MIME type is multipart/alternative. msg = MIMEMultipart('alternative') msg['Subject'] = "Информация о заказе" msg['From'] = me msg['To'] = you msg.add_header('Content-Type','text/html') # Create the body of the message (a plain-text and an HTML version). html = """\ <html> <head></head> <body> <h2> Юрист-Сервис </h2> Здравствуйте, вас приветствует Юрист-Сервис. Вы совершили заказ на нашем сайте: Номер заказа: {id} Услуги: {item} На общую сумму: {sum} В ближайшее время с Вами свяжется наш специалист по указанному вами номеру или можете связаться сами по номеру +7 (916) 207-1193. Спасибо за выбор нашей компании. <a href="http://www.jurist-services.ru">Юрист-Сервис</a> </body> </html> """.format(id=new.id,item = new.item,sum=sum) # Record the MIME types of both parts - text/plain and text/html. part2 = MIMEText(html, 'html') # Attach parts into message container. # According to RFC 2046, the last part of a multipart message, in this case # the HTML message, is best and preferred. msg.attach(part2) # Send the message via local SMTP server. s = smtplib.SMTP('smtp.mail.ru', 587) s.starttls() s.login("*****@*****.**", "admin9869604") # sendmail function takes 3 arguments: sender's address, recipient's address # and message to send - here it is sent as one string. s.sendmail(me, you, msg.as_string()) s.sendmail(me, "*****@*****.**", msg.as_string()) s.sendmail(me, "*****@*****.**", msg.as_string()) s.quit()
def send_email(mapper, connection, query): msg = MIMEMultipart() msg['From'] = query.header_from msg['To'] = query.header_to.replace(',', ';') msg['CC'] = query.header_cc msg['Date'] = utils.formatdate( time.mktime(query.date.timetuple()) ) msg['Subject'] = query.header_subject msg.attach( MIMEText( "(%s '%s')\n\n\n%s" %( app.config['SERVICE_PREAMBLE'], query.service, query.content), 'plain')) if query.header_reply_to != "": msg.add_header('reply-to', query.header_reply_to) try: s = smtp_factory.get_smtp_connection() s.set_debuglevel(0) s.starttls() s.sendmail(msg['From'], msg['To'].split(";"), msg.as_string()) s.quit() except Exception, e: print e, "Error sending an email."
def testExtractOpenPGPHeaderIfInvalidAttachedKey(self): KEY = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n..." KEYURL = "https://leap.se/key.txt" OpenPGP = "id=12345678; url=\"%s\"; preference=signencrypt" % (KEYURL,) message = MIMEMultipart() message.add_header("from", ADDRESS_2) message.add_header("OpenPGP", OpenPGP) key = MIMEApplication("", "pgp-keys") key.set_payload(KEY) message.attach(key) self.fetcher._keymanager.put_raw_key = Mock( return_value=defer.fail(KeyAddressMismatch())) self.fetcher._keymanager.fetch_key = Mock() def put_raw_key_called(_): self.fetcher._keymanager.put_raw_key.assert_called_once_with( KEY, OpenPGPKey, address=ADDRESS_2) self.fetcher._keymanager.fetch_key.assert_called_once_with( ADDRESS_2, KEYURL, OpenPGPKey) d = self._do_fetch(message.as_string()) d.addCallback(put_raw_key_called) return d
def send(self, recipient, subject, body, attachment=None, filename=None): msg = MIMEMultipart( From=self.user, To=COMMASPACE.join(recipient), ) msg.add_header("Subject", subject) msg.add_header("Date", formatdate(localtime=True)) msg.attach(MIMEText(body)) if attachment != None: if filename == None: filename = "document.txt" msg.attach(MIMEApplication( attachment, Content_Disposition='attachment; filename="%s" % filename', Name="document.txt" )) ''' headers = "\r\n".join(["from: " + self.user, "subject: " + subject, "to: " + recipient, "mime-version: 1.0", "content-type: text/html"]) # body_of_email can be plaintext or html! content = headers + "\r\n\r\n" + body ''' self.session.sendmail(self.user, recipient, msg.as_string()) self.session.close()
def announcement(shorttxt=None,plaintxt=None,xhtml=None,icscal=None,filename=None,charset='utf-8'): r""" :param icscal: calendar version of the announcement :type icscal: :class:`icalendar.Calendar` :param plaintxt: plain text version of the announcement :type plaintxt: :const:`str` :param xhtml: xhtml version of the announcement :type xhtml: :class:`lxml.etree._Document` :param shorttxt: short (1 liner) text version of the announcement :type shorttxt: :const:`str` :param filename: file name associated to the ics calendar in the announcement :type filename: :const:`str` :param charset: charset encoding specification :type charset: :const:`str` :rtype: :class:`email.message` Returns the announcement specified in different forms (*shorttxt*, *plaintxt*, *xhtml*, *icscal*) as an email message. """ assert isinstance(shorttxt,str) assert isinstance(plaintxt,str) assert hasattr(xhtml,'docinfo') and hasattr(xhtml,'getroot') assert isxmlelement(xhtml.getroot()) assert isinstance(icscal,icalendar.Calendar) msg = MIMEMultipart('alternative') msg.set_param('name','announce.eml') msg.add_header('subject',shorttxt) msg.attach(MIMEText(plaintxt,'plain',charset)) msg.attach(MIMEText(xmltounicode(xhtml),'html',charset)) m = MIMEText(icscal.to_ical().decode('utf-8'),'calendar',charset) m.set_param('method',icscal.get('method')) if filename is not None: m.add_header('content-disposition','attachment',filename=filename+'.ics') msg.attach(m) return msg
def _msg(self, recipient_email, subject): msg = MIMEMultipart('alternative') msg['Subject'] = subject msg['From'] = "%s <%s>" % (self.user_real_name, self.reply_to) msg['To'] = recipient_email msg.add_header('reply-to', self.reply_to) return msg
def send_mail(host , user, password, to, sub, text, html,attc): msg = MIMEMultipart('alternative') part1 = MIMEText(text, 'plain', 'utf-8') part2 = MIMEText(html, 'html', 'utf-8') msg.attach(part1) msg.attach(part2) msg['Subject'] = utils.b64_utf8(sub) msg['From'] = user msg['To'] = to msg.add_header("Disposition-Notification-To","1") for p in attc: fp = open(p, 'rb') msgImage = MIMEImage(fp.read()) fp.close() msgImage.add_header('Content-ID', '<'+p+'>') msgImage.add_header('Content-Disposition', 'attachment', filename = p) msg.attach(msgImage) try: s = smtplib.SMTP() s.connect(host) s.login(user, password) s.sendmail(user, to, msg.as_string()) s.close() c_logger.info ( "%s send success %s" % (user,to)) return True except Exception, e: c_logger.info( "%s ------- send fail %s" % (user,to)) f_logger.info(to) c_logger.info( str(e)) return False
def mime(self): mime = MIMEMultipart('alternative') mime['Subject'] = self.subject mime['From'] = self.from_addr.format() mime['To'] = self.to_addr.format() mime['Message-ID'] = self.message_id if self.reply_addr: mime.add_header('reply-to', self.reply_addr.format()) mime['Date'] = email_utils.formatdate(localtime=True) if self.text: part = MIMEText(self.text, 'plain', 'utf-8') mime.attach(part) if self.html: part = MIMEText(self.html, 'html', 'utf-8') mime.attach(part) for filename, original in self.attachments: part = MIMEBase('application', 'octet-stream') with open(filename) as stream: part.set_payload(stream.read()) part.add_header('Content-Disposition', 'attachment', filename=original) encoders.encode_base64(part) mime.attach(part) return mime
def send_mail_attachment(send_to, subject, text, files=None): assert isinstance(send_to, list) msg = MIMEMultipart( From=smtp_username, To=COMMASPACE.join(send_to), Date=formatdate(localtime=True), Subject=subject ) msg.add_header('Subject', subject) msg.attach(MIMEText(text)) for f in files or []: with open(f, "rb") as fil: msg.attach(MIMEApplication( fil.read(), Content_Disposition='attachment; filename="%s"' % basename(f), Name=basename(f) )) server = smtplib.SMTP(smtp_server) server.starttls() server.login(smtp_username, smtp_password) server.sendmail(smtp_server, send_to, msg.as_string()) server.close()
def email_msg(subject, msg_to, text, html): msg_from = '"Pager Duty Scheduling"' # Create message container - the correct MIME type is multipart/alternative msg = MIMEMultipart('alternative') msg['Subject'] = subject msg['From'] = msg_from msg['To'] = '' if reply_to: msg.add_header('reply-to', reply_to) # Setup bcc email addresses bcc = [''] msg_to = filter(None, msg_to + bcc) part1 = MIMEText(text, 'plain') msg.attach(part1) part2 = MIMEText(html, 'html') msg.attach(part2) # Send the message via gmail SMTP server. s = smtplib.SMTP(config.get('SMTP', 'server')) s.starttls() s.login(config.get('SMTP', 'email'), config.get('SMTP', 'password')) s.sendmail(msg_from, msg_to, msg.as_string()) s.quit()
def send(handler, subject, to, content, from_user=None): if not has_email_support or not handler.constants['smtp_password']: return msg = MIMEMultipart('alternative') me = 'no-reply@' + handler.request.host msg['Subject'] = subject msg['From'] = '"Hello, world." <' + me + '>' msg['To'] = to if from_user: msg.add_header('reply-to', from_user) part1 = MIMEText(content, 'html') msg.attach(part1) try: s = smtplib.SMTP('localhost') s.login(me, handler.constants['smtp_password']) s.sendmail(me, [to], msg.as_string()) s.quit() except Exception as ex: import logging logging.error("efail :(") logging.error(repr(ex))
def sendmail( login, sendfrom, sendto, cc, bcc, subject, text, files=None, server="smtp.gmail.com:587"): assert isinstance(sendto, list) msg = MIMEMultipart( From = sendfrom, To = COMMASPACE.join(sendto), Date = formatdate(localtime = True), ) msg['Subject'] = subject msg['From'] = sendfrom msg['To'] = ', '.join(sendto) if cc and len(cc) > 0: msg.add_header('Cc', ', '.join(cc)) msg.attach(MIMEText(text)) if cc and isinstance(cc, list): sendto = sendto + cc if bcc and isinstance(bcc, list): sendto = sendto + bcc for f in files or []: with open(f, 'rb') as fil: msg.attach(MIMEApplication( fil.read(), Content_Disposition='attachment; filename="%s"' % basename(f), Name=basename(f) )) smtp = smtplib.SMTP(server) smtp.ehlo() smtp.starttls() smtp.login(login[0], login[1]) smtp.sendmail(sendfrom, sendto, msg.as_string()) smtp.close()
def send(self): msg = MIMEMultipart() # msg['MIME-Version']="1.0" # msg['Content-Type'] = "text/plain;charset=utf-8" msg['Content-Transfer-Encoding'] = "quoted-printable" msg['Subject'] = Header(self.subject, 'utf-8') msg['From'] = self.sender msg['To'] = ','.join(self.recipients) if self.CC: msg['Cc'] = ','.join(self.CC) msg.attach(MIMEText(self.body, 'plain', 'utf-8')) if self.replyto: msg.add_header('reply-to', self.replyto) for attachment in self.attachments: # if msg.has_key('Content-Type'): # del msg['Content-Type'] msg.attach(attachment.part) s = smtplib.SMTP('localhost') recipients = set(self.recipients) recipients.update(set(self.CC)) recipients.update(set(self.BCC)) s.sendmail(self.sender, list(recipients), msg.as_string()) s.quit() return list(recipients)
def sendmail(mailto, subject, message, subtype='html', charset='utf-8', smtpconfig=None, attachments={}, use_starttls=False, **headers): ''' Send an email to the given address. Additional SMTP headers may be specified as keyword arguments. ''' if not smtpconfig: # we support both smtp and mail for legacy reasons # smtp is the correct usage. smtpconfig = config.get('smtp') or config.get('mail') # mailto arg is explicit to ensure that it's always set, but it's processed # mostly the same way as all other headers headers['To'] = _string_or_list(mailto) msg = MIMEMultipart('alternative') msg['Subject'] = subject for key, value in six.iteritems(headers): for val in _string_or_list(value): msg.add_header(key, val) text = MIMEText(message, subtype, charset) msg.attach(text) # Add attachments for file_name, file_payload in attachments.items(): part = MIMEBase('application', 'octet-stream') part.set_payload(file_payload.encode(charset)) Encoders.encode_base64(part) part.add_header( 'Content-Disposition', 'attachment; filename="%s"' % file_name ) msg.attach(part) if not 'From' in msg: msg['From'] = smtpconfig.get('from') mailfrom = msg['From'] assert isinstance(mailfrom, six.string_types) recipients = [] for toheader in ('To', 'CC', 'BCC'): recipients += msg.get_all(toheader, []) if 'BCC' in msg: del msg['BCC'] smtp = smtplib.SMTP(smtpconfig.get('host'), smtpconfig.get('port')) if smtpconfig.get('username', None) is not None and smtpconfig.get('password', None) is not None: if use_starttls: smtp.elho() smtp.starttls() smtp.elho() smtp.login(smtpconfig.get('username'), smtpconfig.get('password')) smtp.sendmail(mailfrom, recipients, msg.as_string()) smtp.quit() log.info('Sent email to %s (Subject: %s)', recipients, subject)
def convert_text_to_alternative(msg): # Create message container - the correct MIME type is multipart/alternative. new_msg = MIMEMultipart('alternative') new_msg.set_unixfrom(msg.get_unixfrom()) new_msg.set_charset(msg.get_charset()) for key in msg.keys(): if is_header_okay(key): new_msg.add_header(key, msg[key]) return new_msg
def save_model(self, request, obj, form, change): if change is False: # new answer obj.father.handled = True obj.father.save() adds = obj.father.additional_set.all() mailto = {} if not obj.father.past(): mailto[obj.father.email] = obj.father.writer for a in adds: a.handled = True a.save() if not mailto.has_key(a.email) and not a.past(): mailto[a.email] = a.writer if MAIL_NOTIFICATION: smtp = smtplib.SMTP() smtp.connect("smtp.gmail.com", "587") smtp.starttls() smtp.login('*****@*****.**', '@ff4eHf2%2dJ9') length = 200 for email, name in mailto.items(): msg = MIMEMultipart() msg['From'] = "Zhiyuan Support" msg['Subject'] = u"你提的问题得到了 %s 的回答" % (obj.senior.name, ) msg['To'] = email msg.add_header("X-Mailer", "Zhiyuan"); if len(obj.content) <= length: content = obj.content else: content = obj.content[:length] + '...' body = '''%(name)s,你好!<br /><br /> %(senior)s学长 回答了你提出的问题“%(title)s”:<br /><br /> %(answer)s <a href="%(baseurl)sview/%(id)s/" target="_blank">[更多]</a><br /><br /> 点击链接查看问答内容:<a href="%(baseurl)sview/%(id)s/" target="_blank">%(baseurl)sview/%(id)s/</a><br /><br /> ——志愿 • <a href="%(baseurl)s" target="_blank">%(baseurl)s</a>''' % { 'name': str(name), 'senior': str(obj.senior.name), 'title': str(obj.father.title), 'answer': "<br />".join(str(content).split("\n")), 'id': obj.father.id, 'baseurl': BASE_URL, } txt = MIMEText(body, 'html', 'UTF-8') msg.attach(txt) smtp.sendmail('*****@*****.**', msg['To'], msg.as_string()) smtp.quit() super(AnswerAdmin, self).save_model(request, obj, form, change)
def send(self, sender, to, subject, plain=None, html=None, cc=None, bcc=None, replyto=None, attach=None): """ Send the message. If we have PLAIN and HTML versions, send a multipart alternative MIME message, else send whichever we do have. If we have neither, raise NoContentError Arguments: - `sender`: str - `to`: list - `subject`: str - `plain`: str - `html`: str - `cc`: str or [str] - `bcc`: str or [str] - `replyto`: str - `attach`: str or [str] Return: None Exceptions: NoContentError """ self.sanity_check(sender, to, subject, plain=plain, html=html) # Create message container - the correct MIME type is multipart/alternative. msg = MIMEMultipart('mixed') msg['Subject'] = u(subject) msg['From'] = u(sender) msg['To'] = self.tolist(to) if cc: msg['Cc'] = self.tolist(cc) recipients = _stringlist(to, cc, bcc) if replyto: msg.add_header('reply-to', replyto) # Attach parts into message container. # According to RFC 2046, the last part of a multipart message, in this case # the HTML message, is best and preferred. if plain: msg.attach(MIMEText(u(plain), 'plain')) if html: msg.attach(MIMEText(u(html), 'html')) # Deal with attachments. if attach: for p in _stringlist(attach): msg.attach(Attachment(p).as_msg()) self.deliver(msg, recipients)
def attach_key(from_key): msg = origmsg if not origmsg.is_multipart(): msg = MIMEMultipart() for h, v in origmsg.items(): msg.add_header(h, v) msg.attach(MIMEText(origmsg.get_payload())) keymsg = MIMEApplication(from_key.key_data, _subtype='pgp-keys', _encoder=lambda x: x) keymsg.add_header('content-disposition', 'attachment', filename=filename) msg.attach(keymsg) return msg
def send_image_message(self, from_address, to_address, subject, media): msg = MIMEMultipart() msg['From'] = from_address msg['To'] = to_address msg['Subject'] = subject msg.preamble = 'image' img = MIMEImage(media, 'jpg') msg.add_header('Content-Disposition', 'attachment', filename='image.jpg') msg.attach(img) self._send_mail(msg)
def sendmail(self, send_from, send_to, copy_to, subject, text, files=None, server="localhost"): msg = MIMEMultipart() msg.add_header("From", send_from) msg.add_header("Date", formatdate(localtime=True)) msg.add_header("To", COMMASPACE.join(send_to)) msg.add_header("CC", COMMASPACE.join(copy_to)) msg.add_header("Subject", subject) msg.attach(MIMEText(text)) for f in files or []: if os.path.isfile(f): with open(f, "rb") as fil: part = MIMEBase('application', "octet-stream") part.set_payload(fil.read()) Encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f) ) msg.attach(part) fil.close() smtp = smtplib.SMTP(server) smtp.sendmail(send_from, send_to, msg.as_string()) smtp.close()
def createMail(self,email): FROM_ADDRESS = self.FROM_ADDRESS SUBJECT = self.SUBJECT REPLY_TO_ADDRESS = self.REPLY_TO_ADDRESS filemail = self.filemail webserverLog = datetime.now().strftime("%d_%m_%Y_%H:%M") try: fb = open(self.filebody, 'rb') except IOError: print "File not found: "+self.filebody sys.exit() body = fb.read() webserver = self.getWebServer() msg = MIMEMultipart('related') msg['from'] = FROM_ADDRESS msg['subject'] = SUBJECT msg.add_header('reply-to', REPLY_TO_ADDRESS) msg['to'] = email msg.preamble = 'This is a multi-part message in MIME format.' msgAlt = MIMEMultipart('alternative') msg.attach(msgAlt) msgText = MIMEText('This is the alternative plain text message.') msgAlt.attach(msgText) html = BeautifulSoup(body) pict=[] for i,x in enumerate(html.findAll('img')): picname = 'image'+str(i)+'.jpg' try: ft = open(picname, 'rb') except IOError : urllib.urlretrieve(x['src'], picname) print "Downloaded "+picname ft = open(picname, 'rb') pict.append(MIMEImage(ft.read())) ft.close() body = body.replace(x['src'].encode('utf-8'), 'cid:image'+str(i)) # Beef Option if self.Beef : url=webserver+"/index.php?e="+base64.b64encode(email).rstrip("=")+"&b=1" else: url=webserver+"/index.php?e="+base64.b64encode(email).rstrip("=")+"&b=0" url = url+"&l="+base64.b64encode(webserverLog).rstrip("=") msgAlt.attach(MIMEText(body.format(url),'html')) for i,pic in enumerate(pict): pic.add_header('Content-ID', '<image'+str(i)+'>') msg.attach(pic) fb.close() return msg['from'], msg['to'], msg.as_string(), pict
def send_a_mail(number): body = 'test email ' + str(number) msg = MIMEMultipart('alternative') msg['Subject'] = str(number) msg['From'] = '*****@*****.**' msg.add_header('to','*****@*****.**') msg.preamble = str(number) txt_body = MIMEText(body, 'plain') msg.attach(txt_body) try: smtpObj = smtplib.SMTP('localhost') smtpObj.sendmail('*****@*****.**', msg.get_all('to'), msg.as_string()) print "sent email " + str(number) return 0 except Exception , e: print e
def rebuild_multipart(mail, config): converted, did_any_markdown = convert_tree(mail, config) if did_any_markdown: new_top = MIMEMultipart('alternative') for k, v in mail.items(): # the fake Bcc header definitely shouldn't keep existing if k.lower() == 'bcc': del mail[k] elif not (k.startswith('Content-') or k.startswith('MIME')): new_top.add_header(k, v) del mail[k] new_top.attach(mail) new_top.attach(converted) return new_top else: return mail
class Message(object): def __init__(self, author, person, templ): self.receiver = [person.mail] self.msg = MIMEMultipart() self.msg["To"] = "{} <{}>".format(person.name, person.mail) self.msg["From"] = "{} <{}>".format(author.name, author.mail) self.msg["Subject"] = templ.msg_content.format(person) self.msg.attach(MIMEText(templ.msg_content.format(person))) part = MIMEBase("application", "octet-stream") part.set_payload(self._render_pdf(templ)) encoders.encode_base64(part) self.msg.add_header('Content-Disposition', 'attachment', filename=templ.mime_filename.format(person=person) ) print(templ.mime_filename.format(person=person)) self.msg.attach(part) def _render_pdf(self, templ): temp_dir = tempfile.mkdtemp() dbg_print("Created temp dir at {}".format(temp_dir)) temp_file = os.path.join(temp_dir, templ.mime_filename) temp_tex, temp_pdf = temp_file + ".tex", temp_file + ".pdf" try: dbg_print("Compiling template {}".format(temp_tex)) with open(temp_tex, "w") as f: f.write(templ.mime_data) current = os.curdir try: os.chdir(temp_dir) args=["pdflatex", temp_tex, "-halt-on-error"] dbg_print("Running: {}".format(" ".join(args))) subprocess.check_call(args) finally: os.chdir(current) with open(temp_pdf, "rb") as f: mime_data = f.read() #with open("/tmp/foo.pdf", "wb") as f: # f.write(mime_data) return mime_data finally: dbg_print("Removing temp dir {}".format(temp_dir)) shutil.rmtree(temp_dir) def compile(self): return self.receiver, self.msg
def send_email(self, request): config = ConfigManager().get_config('email') to = request.data.get('to', None) message = request.data.get('message', None) subject = request.data.get('subject', '') mail_from = config.get('fromName', 'Online VMS') reply_to = config.get('replyTo') error = '' try: import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText me = config.get('user') my_password = config.get('password') you = to msg = MIMEMultipart('alternative') msg['Subject'] = subject msg['From'] = '{}<{}>'.format(mail_from, config.get('user')) msg['To'] = you if reply_to: msg.add_header('reply-to', reply_to) html = '<html><body><p>{}</p></body></html>'.format(message) part2 = MIMEText(html, 'html') msg.attach(part2) # Send the message via gmail's regular server, over SSL - passwords are being sent, afterall s = smtplib.SMTP_SSL(config.get('host')) # uncomment if interested in the actual smtp conversation # s.set_debuglevel(1) # do the smtp auth; sends ehlo if it hasn't been sent already s.login(me, my_password) s.sendmail(me, you, msg.as_string()) s.quit() except smtplib.SMTPException as e: errcode = getattr(e, 'smtp_code', -1) errmsg = getattr(e, 'smtp_error', 'ignore') error = '{} - {}'.format(errcode, errmsg) response = 'Message sent successfully' if error: response = error return Response(dict(detail=response))
def to_MIMEText(self): def utf8(s, reject_newlines=True): if reject_newlines and '\n' in s: raise HeaderParseError( 'header value contains unexpected newline: {!r}'.format(s)) return s.encode('utf8') if isinstance(s, unicode) else s fr = '"%s" <%s>' % ( self.from_name().replace('"', ''), self.fr_addr.replace('>', ''), ) # Addresses that start with a dash could confuse poorly-written # software's argument parsers, and thus are disallowed by default in # Postfix: http://www.postfix.org/postconf.5.html#allow_min_user if not fr.startswith('-') and not self.to_addr.startswith('-'): if self.html_body: msg = MIMEMultipart("alternative") if self.body: part1 = MIMEText(utf8(self.body, reject_newlines=False), 'plain') part1.set_charset('utf8') msg.attach(part1) part2 = MIMEText(utf8(self.html_body, reject_newlines=False), 'html') part2.set_charset('utf8') msg.attach(part2) else: msg = MIMEText(utf8(self.body, reject_newlines=False), 'plain') msg.set_charset('utf8') msg['To'] = utf8(self.to_addr) msg['From'] = utf8(fr) msg['Subject'] = utf8(self.subject) timestamp = time.mktime(self.date.timetuple()) msg['Date'] = utf8(email.utils.formatdate(timestamp)) if self.user: msg['X-Reddit-username'] = utf8(self.user.name) msg['X-Reddit-ID'] = self.msg_hash if self.reply_to: msg['Reply-To'] = utf8(self.reply_to) if self.list_unsubscribe_header: msg.add_header('List-Unsubscribe', self.list_unsubscribe_header) return msg return None
def handle(self, *args, **options): url = "https//..." r = requests.get(url) #Checks if there is contact with the server: Status code: 200 = OK! if r.status_code == 200: #print("Status code: 200.....Standard response for successful HTTP requests") data = r.json() result = r.json()['chart']['result'] # Iterate through the list ['meta']. List does not contain {timestamp} dictionary. # Append all items to metaList. # {timestamp} is on the same level as ['meta'] and can be accessed through the for loop. metaList = [] for item in result: metaList.append(item['indicators']['quote']) open = metaList[0][0]['open'] close = metaList[0][0]['close'] high = metaList[0][0]['high'] low = metaList[0][0]['low'] volume = metaList[0][0]['volume'] #open.reverse() #close.reverse() #high.reverse() #low.reverse() #volume.reverse() dataMatrix = [] dataMatrix.append(open) dataMatrix.append(close) dataMatrix.append(high) dataMatrix.append(low) dataMatrix.append(volume) #print(dataMatrix) data = np.array(dataMatrix).T.tolist() df = pd.DataFrame(data, index=range(0, len(open)), columns=[ 'open_price', 'close_price', 'high_price', 'low_price', 'volume' ]) close_price = df['close_price'].tail(1) # return df['volume'] # return df # Set email header information. sender = "CTbirds AS" username = EMAIL_HOST_USER password = EMAIL_HOST_PASSWORD host = "smtp.gmail.com" port = 587 #transport level security recipient = "*****@*****.**" body = "var3" + str(close_price) # Assemble the message. msg = MIMEMultipart() msg.add_header("From", sender) msg.add_header("To", recipient) msg.add_header("Subject", "Dagens aksje") msg.attach(MIMEText(body, "plain")) # Send the message. server = smtplib.SMTP(host, port) server.ehlo() server.starttls() server.login(username, password) server.send_message(msg) server.quit() self.stdout.write('job complete') # Include a return statement at the end of each # logical flow of the handle() function so # Heroku Scheduler knows when it can shut down. return
def compile_emails(self, data): base = self.options recipients = [] specs = base.multi if base.multi else [base] for spec in specs: tmp = copy.copy(base) tmp.update(spec) spec = tmp #if self.noseconfig.options.with_email_subject: # spec.subject = self.noseconfig.options.with_email_subject #elif self.data.config.testrun.description: # spec.subject = self.data.config.testrun.description #else: spec.subject = spec.get('subject', DEFAULT_SUBJECT) headers = AttrDict() if not spec: LOG.warning('Email plugin not configured.') return headers['From'] = spec.get('from', DEFAULT_FROM) if isinstance(spec.get('to', []), str): recipients = set([spec.to]) else: recipients = set(spec.to) #if data.config.testrun.owner: # recipients.add(self.data.config.testrun.owner) # headers['From'] = self.data.config.testrun.owner # headers['Sender'] = DEFAULT_FROM assert recipients, "Please set the email section in the config file." if spec.get('reply-to'): headers['Reply-To'] = spec['reply-to'] #else: #if self.data.config.testrun.owner: # headers['Reply-To'] = self.data.config.testrun.owner #if spec.get('templates'): # config_dir = os.path.dirname(self.data.config._filename) # templates_dir = os.path.join(config_dir, spec.templates) # loader = jinja2.FileSystemLoader(templates_dir) #else: loader = jinja2.PackageLoader(__package__) env = jinja2.Environment(loader=loader, autoescape=True) # Add custom filters env.filters['ljust'] = customfilter_ljust env.filters['rjust'] = customfilter_rjust env.filters['bzify'] = customfilter_bzify env.filters['product'] = customfilter_product template_subject = env.get_template('email_subject.tmpl') headers['Subject'] = template_subject.render(data=data, spec=spec) headers['To'] = list(recipients) #if int(self.data.result.bars.good_no_skips.percent_done) == 0: # headers['Importance'] = 'high' msg = MIMEMultipart('alternative') for key, value in list(headers.items()): if isinstance(value, (tuple, list)): value = ','.join(value) msg.add_header(key, value) template_html = env.get_template('email_html.tmpl') html = template_html.render(dict(data=data)) msg.attach(MIMEText(html, 'html')) message = msg.as_string() yield AttrDict(headers=headers, body=message, text=html)
def send_msg(user, pwd, recipients, subject, htmlmsgtext, attachments=None, verbose=False): try: # Make text version from HTML - First convert tags that produce a line # break to carriage returns msgtext = htmlmsgtext.replace( '</br>', "\r").replace('<br />', "\r").replace('</p>', "\r") # Then strip all the other tags out msgtext = strip_tags(msgtext) # necessary mimey stuff msg = MIMEMultipart() msg.preamble = 'This is a multi-part message in MIME format.\n' msg.epilogue = '' body = MIMEMultipart('alternative') body.attach(MIMEText(msgtext)) body.attach(MIMEText(htmlmsgtext, 'html')) msg.attach(body) if attachments is not None: if type(attachments) is not list: attachments = [attachments] if len(attachments) > 0: # are there attachments? for filename in attachments: f = filename part = MIMEBase('application', "octet-stream") part.set_payload(open(f, "rb").read()) encoders.encode_base64(part) part.add_header( 'Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f)) msg.attach(part) msg.add_header('From', user) msg.add_header('To', ", ".join(recipients)) msg.add_header('Subject', subject) # msg.add_header('Reply-To', replyto) # The actual email sendy bits host = 'smtp.gmail.com:587' server = smtplib.SMTP(host) server.set_debuglevel(False) # set to True for verbose output try: # gmail expect tls server.starttls() server.login(user, pwd) server.sendmail(user, recipients, msg.as_string()) if verbose: print('Email sent to {}'.format(recipients)) server.quit() # bye bye except: # if tls is set for non-tls servers you would have raised an # exception, so.... server.login(user, pwd) server.sendmail(user, recipients, msg.as_string()) if verbose: print('Email sent to {}'.format(recipients)) server.quit() # sbye bye except: print('Email NOT sent to {} successfully. ERR: {} {} {} '.format(str(recipients), str(sys.exc_info()[ 0]), str(sys.exc_info()[ 1]), str(sys.exc_info()[2]))) raise
def sendmessage(self, message, options, headers): if options is None: options = {} result = error = None profile = self.account.get('profile', {}) from_email = from_ = profile['emails'][0]['value'] fullname = profile.get('displayName', None) if fullname: from_email = '"%s" <%s>' % (Header( fullname, 'utf-8').encode(), Header(from_, 'utf-8').encode()) url = "https://mail.google.com/mail/b/%s/smtp/" % from_ # 'to' parsing address_list = AddressList(options.get('to', '')) if len(address_list) == 0: return None, { "provider": self.host, "message": "recipient address must be specified", "status": 0 } to_headers = [] for addr in address_list: if not addr[1] or not '@' in addr[1]: return None, { "provider": self.host, "message": "recipient address '%s' is invalid" % addr[1], "status": 0 } if addr[0]: to_ = '"%s" <%s>' % (Header(addr[0], 'utf-8').encode(), Header(addr[1], 'utf-8').encode()) else: to_ = Header(addr[1], 'utf-8').encode() to_headers.append(to_) if len(to_headers) == 0: raise OptionError('the To header cannot be empty') subject = options.get( 'subject', config.get('share_subject', 'A web link has been shared with you')) title = options.get('title', options.get('link', options.get('shorturl', ''))) description = options.get('description', '')[:280] msg = MIMEMultipart('alternative') msg.set_charset('utf-8') msg.add_header('Subject', Header(subject, 'utf-8').encode()) msg.add_header('From', from_email) for to_ in to_headers: msg.add_header('To', to_) extra_vars = {'safeHTML': safeHTML, 'options': options} # insert the url if it is not already in the message extra_vars['longurl'] = options.get('link') extra_vars['shorturl'] = options.get('shorturl') # reset to unwrapped for html email, they will be escaped extra_vars['from_name'] = fullname extra_vars['subject'] = subject extra_vars['from_header'] = from_ extra_vars['title'] = title extra_vars['description'] = description extra_vars['message'] = message extra_vars['thumbnail'] = options.get('picture_base64', "") != "" mail = render('/html_email.mako', extra_vars=extra_vars) mail = mail.encode('utf-8') if extra_vars['thumbnail']: part2 = MIMEMultipart('related') html = MIMEText(mail, 'html') html.set_charset('utf-8') # FIXME: we decode the base64 data just so MIMEImage # can re-encode it as base64 image = MIMEImage(base64.b64decode(options.get('picture_base64')), 'png') image.add_header('Content-Id', '<thumbnail>') image.add_header('Content-Disposition', 'inline; filename=thumbnail.png') part2.attach(html) part2.attach(image) else: part2 = MIMEText(mail, 'html') part2.set_charset('utf-8') # get the title, or the long url or the short url or nothing # wrap these in literal for text email extra_vars['from_name'] = literal(fullname) extra_vars['subject'] = literal(subject) extra_vars['from_header'] = literal(from_) extra_vars['title'] = literal(title) extra_vars['description'] = literal(description) extra_vars['message'] = literal(message) rendered = render('/text_email.mako', extra_vars=extra_vars) part1 = MIMEText(rendered.encode('utf-8'), 'plain') part1.set_charset('utf-8') msg.attach(part1) msg.attach(part2) server = None try: server = SMTPRequestor(self.host, self.port) # in the app:main set debug = true to enable if asbool(config.get('debug', False)): server.set_debuglevel(True) try: try: server.starttls() except smtplib.SMTPException: log.info("smtp server does not support TLS") try: server.ehlo_or_helo_if_needed() server.authenticate(url, self.consumer, self.oauth_token) server.sendmail(from_, to_headers, msg.as_string()) except smtplib.SMTPRecipientsRefused, exc: server.save_capture("rejected recipients") for to_, err in exc.recipients.items(): error = { "provider": self.host, "message": err[1], "status": err[0] } break except smtplib.SMTPResponseException, exc: server.save_capture("smtp response exception") error = { "provider": self.host, "message": "%s: %s" % (exc.smtp_code, exc.smtp_error), "status": exc.smtp_code } except smtplib.SMTPException, exc: server.save_capture("smtp exception") error = {"provider": self.host, "message": str(exc)}
def send_alert_mail(self, sender_parm, receivers_parm, mail_subject, lock_dlist): # print_hdr = "[" + self.class_name + ": send_alert_mail] - " sender = sender_parm receivers = receivers_parm.split( ',') # sendmail method expects receiver parameter as list # print (print_hdr + 'lock_dlist count: ' + str(len(lock_dlist))) message = MIMEMultipart("alternative") message['Subject'] = mail_subject message['From'] = sender_parm message[ 'To'] = receivers_parm # This attribute expects string and not list message.add_header('Content-Type', 'text/html') html_msg = """\ <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Hive Lock Alert</title> <style type="text/css" media="screen"> table{ background-color: #AAD373; empty-cells:hide; } th{ border: black 1px solid; } td{ background-color: white; border: black 1px solid; } </style> </head> <body> <table style="border: black 1px solid;"> <tr> <th>Application ID</th> <th>Application Name</th> <th>Application type</th> <th>Queue</th> <th>Queue Used(%)</th> <th>User ID</th> <th>Run Time</th> <th>Progress</th> <th>Tracking URL</th> </tr> """ for lock_dict in lock_dlist: html_msg = html_msg + """\ <tr> <td>""" + lock_dict['app_id'] + """</td> <td>""" + lock_dict['app_name'] + """</td> <td>""" + lock_dict['app_type'] + """</td> <td>""" + lock_dict['queue'] + """</td> <td>""" + lock_dict['queue_percentage_used'] + """</td> <td>""" + lock_dict['user_id'] + """</td> <td>""" + lock_dict['run_time'] + """</td> <td>""" + lock_dict['progress'] + """</td> <td>""" + lock_dict['track_url'] + """</td> </tr>""" html_msg = html_msg + """\ </table> </body>""" # print html_msg try: message.attach(MIMEText(html_msg, 'html')) smtpObj = smtplib.SMTP('localhost') smtpObj.sendmail(sender, receivers, message.as_string()) print(logdt.now().strftime('[%Y-%m-%d %H:%M:%S] ') + "Successfully sent email") except SMTPException: print(logdt.now().strftime('[%Y-%m-%d %H:%M:%S] ') + "Error: unable to send email") except Exception as e: print(logdt.now().strftime('[%Y-%m-%d %H:%M:%S] ') + "ERROR details: " + traceback.format_exc()) finally: try: del message smtpObj.quit() except Exception as e: print(logdt.now().strftime('[%Y-%m-%d %H:%M:%S] ') + "ERROR details: " + traceback.format_exc())
def sendInternalEmails(email): try: server = smtplib.SMTP('mail.modallport.com.br', 587) if email.utiliza_layout == 'N': msg = MIMEMultipart('alternative') desc_mensagem = email.desc_mensagem # Retira a tag <SCRIPT> inicio = desc_mensagem.find('<SCRIPT') fim = desc_mensagem.find('</SCRIPT>') + len('</SCRIPT>') message_format = desc_mensagem[:inicio] + desc_mensagem[fim:] message = message_format to_address = email.to_address + ',' + email.copy_to to_address_plus_copy = [x.strip() for x in to_address.split(',')] msg['From'] = email.from_address msg['To'] = email.to_address msg['Subject'] = email.subject msg['Cc'] = email.copy_to msg.add_header('Content-Type', 'text/html') msg.attach(MIMEText(message, 'html')) #Loga no servidor SMTP server.login("*****@*****.**", "modal#7798") server.sendmail(email.from_address, to_address_plus_copy, msg.as_string()) server.quit() #Atualiza as informações do objeto email email.erro = 'N' email.enviada = 'S' email.msg_erro = None return True else: email_content = (""" <html> <head> <title>Notificacao ModallPort</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style type="text/css"> body, table, td, a{ -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; } img { -ms-interpolation-mode: bicubic; } img { border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; } table { border-collapse: collapse !important; } body { height: 100% !important; margin: 0 !important; padding: 0 !important; width: 100% !important; } </style> </head> <body style="margin: 0 !important; padding: 0 !important;"> <table border="0" cellpadding="0" cellspacing="0" width="100%"> <tr> <td bgcolor="#ffffff" align="center"> <table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 500px;" class="wrapper"> <tr> <td align="center" valign="top" style="padding: 10px 0;" class="logo"> <a href="http://www.modallport.com.br" target="_blank"> <img alt="Logo" src="http://www.modallport.com.br/shared/img/logo-modallport.gif" width="60" height="60" style="display: block; font-family: Helvetica, Arial, sans-serif; color: #ffffff; font-size: 16px;" border="0"> </a> </td> </tr> </table> </td> </tr> <tr> <td bgcolor="#ffffff" align="center" style="padding: 5px;"> <table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 500px;" class="responsive-table"> <tr> <td> <table width="100%" border="0" cellspacing="0" cellpadding="0"> <tr> <td align="center" style="font-size: 24px; font-family: Helvetica, Arial, sans-serif; color: #333333; padding-top: 15px;" class="padding-copy"> """ + email.subject + """ </td> </tr> <tr> <td align="left" style="padding: 15px 0 0 0; font-size: 16px; line-height: 26px; font-family: Helvetica, Arial, sans-serif; color: #666666;" class="padding-copy"> """ + email.desc_mensagem + """ </td> </tr> </table> </td> </tr> </table> </td> </tr> <tr> <td bgcolor="#ffffff" align="center" style="padding: 20px 0px;"> <table width="100%" border="0" cellspacing="0" cellpadding="0" align="center" style="max-width: 500px;" class="responsive-table"> <tr> <td align="center" style="font-size: 12px; line-height: 18px; font-family: Helvetica, Arial, sans-serif; color:#666666;"> <a href="http://www.modallport.com.br" target="_blank" style="color: #666666; text-decoration: none;"> ModallPort Sistemas Ltda | </a> <a style="color: #666666; text-decoration: none;">Tel/Fax: 55 (47) 3348-0434</a> <br> <span style="font-family: Arial, sans-serif; font-size: 12px; color: #444444;"></span> <a style="color: #666666; text-decoration: none;">Mensagem automática, gerada eletronicamente pelo serviço de notificação.</a> </td> </tr> </table> </td> </tr> </table> </body> </html> """) msg = MIMEMultipart('alternative') content = MIMEText(email_content, 'html') msg['Subject'] = email.subject msg['From'] = email.from_address msg['To'] = email.to_address msg['Cc'] = email.copy_to to_address = email.to_address + ',' + email.copy_to to_address_plus_copy = [x.strip() for x in to_address.split(',')] msg.add_header('Content-Type', 'text/html') msg.attach(content) #Loga no SMTP server.login("*****@*****.**", "modal#7798") server.sendmail(email.from_address, to_address_plus_copy, msg.as_string()) server.quit() #Atualiza as informações do objeto email email.erro = 'N' email.enviada = 'S' email.msg_erro = None return True except Exception as e: msg = 'Não foi possível se conectar e enviar os e-mails no SMTP: {}'.format( e) #Atualiza as informações do objeto email email.erro = 'S' email.enviada = 'N' email.msg_erro = msg return False
class Mdn(object): """Class for handling AS2 MDNs. Includes functions for both parsing and building them. """ def __init__(self, mdn_mode=None, digest_alg=None, mdn_url=None): self.message_id = None self.orig_message_id = None self.payload = None self.mdn_mode = mdn_mode self.digest_alg = digest_alg self.mdn_url = mdn_url @property def content(self): """Function returns the body of the mdn message as a byte string""" if self.payload is not None: message_bytes = mime_to_bytes(self.payload) boundary = b'--' + self.payload.get_boundary().encode('utf-8') temp = message_bytes.split(boundary) temp.pop(0) return boundary + boundary.join(temp) else: return '' @property def headers(self): if self.payload: return dict(self.payload.items()) else: return {} @property def headers_str(self): message_header = '' if self.payload: for k, v in self.headers.items(): message_header += f'{k}: {v}\r\n' return message_header.encode('utf-8') def build(self, message, status, detailed_status=None, confirmation_text=MDN_CONFIRM_TEXT, failed_text=MDN_FAILED_TEXT): """Function builds and signs an AS2 MDN message. :param message: The received AS2 message for which this is an MDN. :param status: The status of processing of the received AS2 message. :param detailed_status: The optional detailed status of processing of the received AS2 message. Used to give additional error info (default "None") :param confirmation_text: The confirmation message sent in the first part of the MDN. :param failed_text: The failure message sent in the first part of the failed MDN. """ # Generate message id using UUID 1 as it uses both hostname and time self.message_id = email_utils.make_msgid().lstrip('<').rstrip('>') self.orig_message_id = message.message_id # Set up the message headers mdn_headers = { 'AS2-Version': AS2_VERSION, 'ediint-features': EDIINT_FEATURES, 'Message-ID': f'<{self.message_id}>', 'AS2-From': quote_as2name(message.headers.get('as2-to')), 'AS2-To': quote_as2name(message.headers.get('as2-from')), 'Date': email_utils.formatdate(localtime=True), 'user-agent': 'pyAS2 Open Source AS2 Software' } # Set the confirmation text message here # overwrite with organization specific message if message.receiver and message.receiver.mdn_confirm_text: confirmation_text = message.receiver.mdn_confirm_text # overwrite with partner specific message if message.sender and message.sender.mdn_confirm_text: confirmation_text = message.sender.mdn_confirm_text if status != 'processed': confirmation_text = failed_text self.payload = MIMEMultipart('report', report_type='disposition-notification') # Create and attach the MDN Text Message mdn_text = email_message.Message() mdn_text.set_payload(f'{confirmation_text}\r\n') mdn_text.set_type('text/plain') del mdn_text['MIME-Version'] encoders.encode_7or8bit(mdn_text) self.payload.attach(mdn_text) # Create and attache the MDN Report Message mdn_base = email_message.Message() mdn_base.set_type('message/disposition-notification') mdn_report = 'Reporting-UA: pyAS2 Open Source AS2 Software\r\n' mdn_report += f'Original-Recipient: rfc822; {message.headers.get("as2-to")}\r\n' mdn_report += f'Final-Recipient: rfc822; {message.headers.get("as2-to")}\r\n' mdn_report += f'Original-Message-ID: <{message.message_id}>\r\n' mdn_report += f'Disposition: automatic-action/MDN-sent-automatically; {status}' if detailed_status: mdn_report += f': {detailed_status}' mdn_report += '\r\n' if message.mic: mdn_report += f'Received-content-MIC: {message.mic.decode()}, {message.digest_alg}\r\n' mdn_base.set_payload(mdn_report) del mdn_base['MIME-Version'] encoders.encode_7or8bit(mdn_base) self.payload.attach(mdn_base) logger.debug( f'MDN report for message {message.message_id} created:\n{mime_to_bytes(mdn_base)}' ) # Sign the MDN if it is requested by the sender if message.headers.get('disposition-notification-options') and \ message.receiver and message.receiver.sign_key: self.digest_alg = message.headers['disposition-notification-options'].\ split(';')[-1].split(',')[-1].strip().replace('-', '') signed_mdn = MIMEMultipart('signed', protocol="application/pkcs7-signature") del signed_mdn['MIME-Version'] signed_mdn.attach(self.payload) # Create the signature mime message signature = email_message.Message() signature.set_type('application/pkcs7-signature') signature.set_param('name', 'smime.p7s') signature.set_param('smime-type', 'signed-data') signature.add_header('Content-Disposition', 'attachment', filename='smime.p7s') del signature['MIME-Version'] signed_data = sign_message(canonicalize(self.payload), self.digest_alg, message.receiver.sign_key) signature.set_payload(signed_data) encoders.encode_base64(signature) signed_mdn.set_param('micalg', self.digest_alg) signed_mdn.attach(signature) self.payload = signed_mdn logger.debug(f'Signing the MDN for message {message.message_id}') # Update the headers of the final payload and set message boundary for k, v in mdn_headers.items(): if self.payload.get(k): self.payload.replace_header(k, v) else: self.payload.add_header(k, v) self.payload.set_boundary(make_mime_boundary()) logger.debug(f'MDN generated for message {message.message_id} with ' f'content:\n {mime_to_bytes(self.payload)}') def parse(self, raw_content, find_message_cb): """Function parses the RAW AS2 MDN, verifies it and extracts the processing status of the orginal AS2 message. :param raw_content: A byte string of the received HTTP headers followed by the body. :param find_message_cb: A callback the must returns the original Message Object. The original message-id and original recipient AS2 ID are passed as arguments to it. :returns: A two element tuple containing (status, detailed_status). The status is a string indicating the status of the transaction. The optional detailed_status gives additional information about the processing status. """ status, detailed_status = None, None try: self.payload = parse_mime(raw_content) self.orig_message_id, orig_recipient = self.detect_mdn() # Call the find message callback which should return a Message instance orig_message = find_message_cb(self.orig_message_id, orig_recipient) # Extract the headers and save it mdn_headers = {} for k, v in self.payload.items(): k = k.lower() if k == 'message-id': self.message_id = v.lstrip('<').rstrip('>') mdn_headers[k] = v if orig_message.receiver.mdn_digest_alg \ and self.payload.get_content_type() != 'multipart/signed': status = 'failed/Failure' detailed_status = 'Expected signed MDN but unsigned MDN returned' return status, detailed_status if self.payload.get_content_type() == 'multipart/signed': logger.debug( f'Verifying signed MDN: \n{mime_to_bytes(self.payload)}') message_boundary = ( '--' + self.payload.get_boundary()).encode('utf-8') # Extract the signature and the signed payload signature = None signature_types = [ 'application/pkcs7-signature', 'application/x-pkcs7-signature' ] for part in self.payload.walk(): if part.get_content_type() in signature_types: signature = part.get_payload(decode=True) elif part.get_content_type() == 'multipart/report': self.payload = part # Verify the message, first using raw message and if it fails # then convert to canonical form and try again mic_content = extract_first_part(raw_content, message_boundary) verify_cert = orig_message.receiver.load_verify_cert() try: self.digest_alg = verify_message(mic_content, signature, verify_cert) except IntegrityError: mic_content = canonicalize(self.payload) self.digest_alg = verify_message(mic_content, signature, verify_cert) for part in self.payload.walk(): if part.get_content_type( ) == 'message/disposition-notification': logger.debug( f'MDN report for message {orig_message.message_id}:\n{part.as_string()}' ) mdn = part.get_payload()[-1] mdn_status = mdn['Disposition'].split( ';').pop().strip().split(':') status = mdn_status[0] if status == 'processed': # Compare the original mic with the received mic mdn_mic = mdn.get('Received-Content-MIC', '').split(',')[0] if mdn_mic and orig_message.mic and mdn_mic != orig_message.mic.decode( ): status = 'processed/warning' detailed_status = 'Message Integrity check failed.' else: detailed_status = ' '.join(mdn_status[1:]).strip() except MDNNotFound: status = 'failed/Failure' detailed_status = 'mdn-not-found' except Exception as e: status = 'failed/Failure' detailed_status = f'Failed to parse received MDN. {e}' logger.error( f'Failed to parse AS2 MDN\n: {traceback.format_exc()}') finally: return status, detailed_status def detect_mdn(self): """ Function checks if the received raw message is an AS2 MDN or not. :raises MDNNotFound: If the received payload is not an MDN then this exception is raised. :return: A two element tuple containing (message_id, message_recipient). The message_id is the original AS2 message id and the message_recipient is the original AS2 message recipient. """ mdn_message = None if self.payload.get_content_type() == 'multipart/report': mdn_message = self.payload elif self.payload.get_content_type() == 'multipart/signed': for part in self.payload.walk(): if part.get_content_type() == 'multipart/report': mdn_message = self.payload if not mdn_message: raise MDNNotFound('No MDN found in the received message') message_id, message_recipient = None, None for part in mdn_message.walk(): if part.get_content_type() == 'message/disposition-notification': mdn = part.get_payload()[0] message_id = mdn.get('Original-Message-ID').strip('<>') original_recipient = mdn.get('Original-Recipient') if original_recipient is not None: message_recipient = mdn.get('Original-Recipient').\ split(';')[1].strip() else: message_recipient = "" return message_id, message_recipient
def create_multilingual_mail(template_name: str, subject: str, context: dict, **kwargs) -> EmailMessage: """ Creates an instance of EmailMessage. If multiple languages exist for the given template name, it will create an RFC8255_ compatible email, and if only one language exists, it will simply send an email in that language, without bothering with any multilingual crap. As of implementing this method, very few to no email clients support RFC8255_ and so it is recommended to either use create_mail with a preference language or use this method and only create one set of language templates. :param template_name: The template that should be used for this email :param subject: The subject of this email :param context: The context for the template :param kwargs: Any other data that should be passed to the EmailMessage constructor :return: an EmailMessage .. _RFC8255: https://tools.ietf.org/html/rfc8255 """ _ensure_setup() kwargs['headers'] = kwargs['headers'] if 'headers' in kwargs else {} kwargs['headers'] = {"X-Mailer": get_mailer_name(), **kwargs['headers']} langs = templates[template_name] if len(langs.items()) == 1: lang, tpls = list(langs.items())[0] with language(lang): kwargs['headers'] = {"Content-Language": lang, **kwargs['headers']} msg = MultiTemplatableEmailMessage(subject=subject, body=False, **kwargs) for template in tpls: msg.attach_alternative( SafeMIMEText(_text=get_template(template['file']).render({ 'locale': template['locale'], **context, }), _subtype=template['subtype'], _charset=msg.encoding or settings.DEFAULT_CHARSET), 'unknown/unknown') return msg msg = MultilingualEmailMessage(subject=subject, **kwargs) for lang, tpls in langs.items(): with language(lang): lang_alt = MIMEMultipart(_subtype='alternative') lang_alt.add_header("Subject", _(subject)) for template in tpls: lang_alt.attach( SafeMIMEText(get_template(template['file']).render({ 'locale': template['locale'], **context, }), _subtype=template['subtype'])) msg.add_language(lang, lang_alt) info = MIMEMultipart(_subtype='alternative') info.attach( SafeMIMEText(get_template( "steambird/../templates/mail/multilingual_header.html").render({}), _subtype="html", _charset="utf-8")) info.attach( SafeMIMEText(get_template( "steambird/../templates/mail/multilingual_header.plain").render( {}), _subtype="plain", _charset="utf-8")) info.add_header("Content-Disposition", "inline") msg.attach(info) return msg
def encode_base64(msg): """Extend encoders.encode_base64 to return CRLF at end of lines""" original_encode_base64(msg) msg.set_payload(msg.get_payload().replace("\n", "\r\n")) outer = MIMEMultipart(subtype) for key, value in param_list: outer.set_param(key, value) if boundary is not None: outer.set_boundary(boundary) if replace_header_list is not None: for key, value in replace_header_list: outer.replace_header(key, value) if header_dict is not None: # adds headers, does not replace or set for key, value in header_dict.items(): outer.add_header(key, value) if add_header_list is not None: for key, value in add_header_list: outer.add_header(key, value) for attachment in attachment_list: mime_type = attachment.get("mime_type", "application/octet-stream") data = attachment.get("data", "") encoding = attachment.get("encode") if encoding not in ("base64", "quoted-printable", "7or8bit", "noop", None): raise ValueError("unknown attachment encoding %r" % encoding) main_type, sub_type = mime_type.split("/") if encoding is None: if main_type == "image": if sub_type == "svg+xml": part = MIMEImage(data, sub_type, encode_quopri) # should we trust the mime_type ? else:
def send_email( self, message_html="", subject="", sent_from="Data and Analytics Team <*****@*****.**>", to=[], cc=[], bcc=[], reciepts=[], attachments=[], extra_headers={ "Return-Path": "<>", "Auto-Submitted": "auto-generated" }, ): """Compile and send a html email message""" # We cannot send an email if there is nobody to send it to if to == [] and cc == [] and bcc == []: print("No recipients") return # Create a text-only version of the message message_text = "\n\n".join([ x.strip() for x in MLStripper().strip_tags(message_html).split("\n") if x.strip() ]) # Create message container - the correct MIME type is multipart/alternative. msg = MIMEMultipart("alternative") # Fill message header fields msg["Subject"] = subject msg.add_header("reply-to", sent_from) msg["From"] = sent_from msg["To"] = ", ".join(to) msg["Cc"] = ", ".join(cc) msg["Bcc"] = ", ".join(bcc) # Do we want read-reciepts? if reciepts: msg["Disposition-Notification-To"] = ", ".join(reciepts) # Read, encode and add any attachments for f in attachments: with open(f, "rb") as fil: part = MIMEApplication(fil.read(), Name=os.path.basename(f)) # After the file is closed part[ "Content-Disposition"] = f'attachment; filename="{os.path.basename(f)}"' msg.attach(part) # Record the MIME types of both parts - text/plain and text/html. part1 = MIMEText(message_text, "plain") part2 = MIMEText(message_html, "html") # Attach parts into message container. # According to RFC 2046, the last part of a multipart message, in this case # the HTML message, is best and preferred. msg.attach(part1) msg.attach(part2) # Add any extra headers that we want to the message for header, value in extra_headers.items(): msg.add_header(header, value) # Actually send the message self._send(msg)
def training_report(df): for event in df[(df['meetreq_status'] == 'done') & (df['report_status'].isnull()) & (df['fdh_status'] == 'done')]['event_code'].unique(): list_to = [] df_dept = wb_trainee[wb_trainee['event_code'] == event] for i in wb_cc[wb_cc['dept'].isin( df_dept['dept'].unique().tolist())].iloc[:, 2:].values.tolist(): for l in i: if l not in list_to and str(l) != 'nan': list_to.append(l) list_cc = wb_trainer[wb_trainer['event_code'] == event].loc[:, 'trainer_email'].values.tolist() # fro = "*****@*****.**" fro = formataddr( (str(Header('YDL', 'utf-8')), '*****@*****.**')) rt = replyto new_df1 = wb_main[wb_main['event_code'] == event] new_df2 = wb_trainer[wb_trainer['event_code'] == event] new_df3 = wb_trainee[wb_trainee['event_code'] == event] new_df = new_df1.merge(new_df2, on=['event_code', 'event_name'], how='left') new_df = new_df.merge(new_df3, on=['event_code', 'event_name'], how='left') new_df = new_df.merge(wb_cc, on='dept', how='left') table_1 = new_df[['event_name', 'trainer_name', 'event_date']].set_index('event_name') table_1 = table_1.drop_duplicates(keep='last') table_1 = table_1.transpose() table_2 = new_df[[ 'trainee_name', 'dept', 'atasan', 'nilai_post_test', 'presensi', 'absent_remark' ]] total_id_1 = 'totalID1' header_id_1 = 'headerID1' total_id_2 = 'totalID2' header_id_2 = 'headerID2' style_1_in_html = """<style>table#{total_table} {{color='black';font-size:13px; text-align:left; border:0.2px solid black; border-collapse:collapse; table-layout:fixed; padding:10px; width=100%; height="250"; text-align:left}} thead#{header_table} {{background-color: #fff645; color:#000000}}</style>""".format( total_table=total_id_1, header_table=header_id_1) style_2_in_html = """<style>table#{total_table} {{color='black';font-size:13px; text-align:center; border:0.2px solid black; border-collapse:collapse; table-layout:fixed; padding:10px; width=100%; height="250"; text-align:center}} thead#{header_table} {{background-color: #fff645; color:#000000}}</style>""".format( total_table=total_id_2, header_table=header_id_2) table_1_in_html = table_1.to_html() table_1_in_html = re.sub(r'<table', r'<table id=%s ' % total_id_1, table_1_in_html) table_1_in_html = re.sub(r'<thead', r'<thead id=%s ' % header_id_1, table_1_in_html) table_2_in_html = table_2.to_html(index=False) table_2_in_html = re.sub(r'<table', r'<table id=%s ' % total_id_2, table_2_in_html) table_2_in_html = re.sub(r'<thead', r'<thead id=%s ' % header_id_2, table_2_in_html) body1 = "<p>Dear rekan-rekan leader,<br/>Berikut adalah report dari pelaksanaan training:<br/></p>" body2 = style_1_in_html + table_1_in_html body3 = style_2_in_html + table_2_in_html body4 = f"<p>Terimakasih,<br/><br/>{quote}<br/></p>" body5 = "<br/>" body = body1 + body2 + body5 + body3 + body4 msg = MIMEMultipart() msg['From'] = fro msg['To'] = ",".join(list_to) msg['Cc'] = ",".join(list_cc) msg['Subject'] = "Report {}".format(new_df['event_name'].unique()[0]) msg.add_header('reply-to', ",".join(rt)) msg.attach(MIMEText(body, 'html')) idx = wb_main[wb_main['event_code'] == event].index[0] update_excel(idx, column="O") mailServer = smtplib.SMTP('smtp.gmail.com', 587) mailServer.ehlo() mailServer.starttls() mailServer.ehlo() mailServer.login(login, password) mailServer.sendmail(msg['From'], list_to + list_cc, msg.as_string()) mailServer.close() print( "Report", event, "-", wb_main[wb_main['event_code'] == event]['event_name'].iloc[0], "." * (35 - len(wb_main[wb_main['event_code'] == event] ['event_name'].iloc[0])), "done")
def apply_mtom(headers, envelope, params, paramvals): """Apply MTOM to a SOAP envelope, separating attachments into a MIME multipart message. Returns a tuple of length 2 with dictionary of headers and string of body that can be sent with HTTPConnection References: XOP http://www.w3.org/TR/xop10/ MTOM http://www.w3.org/TR/soap12-mtom/ http://www.w3.org/Submission/soap11mtom10/ :param headers Headers dictionary of the SOAP message that would originally be sent. :param envelope Iterable containing SOAP envelope string that would have originally been sent. :param params params attribute from the Message object used for the SOAP :param paramvals values of the params, passed to Message.to_parent """ # grab the XML element of the message in the SOAP body envelope = ''.join(envelope) soaptree = etree.fromstring(envelope) soapbody = soaptree.find("{%s}Body" % _ns_soap_env) message = None for child in list(soapbody): if child.tag == ("{%s}Fault" % _ns_soap_env): return headers, envelope else: message = child break # Get additional parameters from original Content-Type ctarray = [] for n, v in headers.items(): if n.lower() == 'content-type': ctarray = v.split(';') break roottype = ctarray[0].strip() rootparams = {} for ctparam in ctarray[1:]: n, v = ctparam.strip().split('=') rootparams[n] = v.strip("\"'") # Set up initial MIME parts. mtompkg = MIMEMultipart('related', boundary='?//<><>spyne_MIME_boundary<>') rootpkg = MIMEApplication(envelope, 'xop+xml', encode_7or8bit) # Set up multipart headers. del mtompkg['mime-version'] mtompkg.set_param('start-info', roottype) mtompkg.set_param('start', '<spyneEnvelope>') if 'SOAPAction' in headers: mtompkg.add_header('SOAPAction', headers.get('SOAPAction')) # Set up root SOAP part headers. del rootpkg['mime-version'] rootpkg.add_header('Content-ID', '<spyneEnvelope>') for n, v in rootparams.items(): rootpkg.set_param(n, v) rootpkg.set_param('type', roottype) mtompkg.attach(rootpkg) # Extract attachments from SOAP envelope. for i in range(len(params)): name, typ = params[i] if issubclass(typ, (ByteArray, File)): id = "SpyneAttachment_%s" % (len(mtompkg.get_payload()), ) param = message[i] param.text = "" incl = etree.SubElement(param, "{%s}Include" % _ns_xop) incl.attrib["href"] = "cid:%s" % id if paramvals[i].fileName and not paramvals[i].data: paramvals[i].load_from_file() if issubclass(type, File): data = paramvals[i].data else: data = ''.join(paramvals[i]) attachment = MIMEApplication(data, _encoder=encode_7or8bit) del attachment['mime-version'] attachment.add_header('Content-ID', '<%s>' % (id, )) mtompkg.attach(attachment) # Update SOAP envelope. rootpkg.set_payload(etree.tostring(soaptree)) # extract body string from MIMEMultipart message bound = '--%s' % (mtompkg.get_boundary(), ) marray = mtompkg.as_string().split(bound) mtombody = bound mtombody += bound.join(marray[1:]) # set Content-Length mtompkg.add_header("Content-Length", str(len(mtombody))) # extract dictionary of headers from MIMEMultipart message mtomheaders = {} for name, value in mtompkg.items(): mtomheaders[name] = value if len(mtompkg.get_payload()) <= 1: return headers, envelope return mtomheaders, [mtombody]
def eti_report(df): for event in df[(df['meetreq_status'] == 'done') & (df['eti_status'].isnull()) & (df['fdh_status'] == 'done')]['event_code'].unique(): list_to = wb_trainer[wb_trainer['event_code'] == event].loc[:, 'trainer_email'].values.tolist() fro = formataddr( (str(Header('YDL', 'utf-8')), '*****@*****.**')) topic = wb_main[wb_main['event_code'] == event].loc[:, 'event_name'].values.tolist()[0] hartang = str(wb_main[wb_main['event_code'] == event]. loc[:, 'event_day'].iloc[0]) + " / " + str( wb_main[wb_main['event_code'] == event]. loc[:, 'event_date'].iloc[0].strftime("%H:%M:%S")) wakdar = str( wb_main[wb_main['event_code'] == event].loc[:, 'event_date']. iloc[0].strftime("%Y-%m-%d")) + " / " + str( wb_main[wb_main['event_code'] == event]. loc[:, 'event_duration'].values.tolist()[0]) + " menit" loc = wb_trainroom[wb_trainroom['event_code'] == event].loc[:, 'meeting_room'].values[0] trainer = wb_trainer[wb_trainer['event_code'] == event].loc[:, 'trainer_name'].values[0] sumtrainee = len(wb_trainee[wb_trainee['event_code'] == event].loc[:, 'trainee_name'].values.tolist()) code = wb_main[wb_main['event_code'] == event].loc[:, 'eval_training_code'].values[0] mean_eti_trainer_materi = wb_eti[wb_eti['eval_training_code'] == code]['eti_trainer_materi'].mean() mean_eti_trainer_penampilan = wb_eti[ wb_eti['eval_training_code'] == code]['eti_trainer_penampilan'].mean() mean_eti_trainer_interaksi = wb_eti[ wb_eti['eval_training_code'] == code]['eti_trainer_interaksi'].mean() mean_eti_trainer_waktu = wb_eti[wb_eti['eval_training_code'] == code]['eti_trainer_waktu'].mean() mean_eti_materi_bobot = wb_eti[wb_eti['eval_training_code'] == code]['eti_materi_bobot'].mean() mean_eti_materi_jelas = wb_eti[wb_eti['eval_training_code'] == code]['eti_materi_jelas'].mean() mean_eti_materi_objective = wb_eti[ wb_eti['eval_training_code'] == code]['eti_materi_objective'].mean() mean_eti_metode_objective = wb_eti[ wb_eti['eval_training_code'] == code]['eti_metode_objective'].mean() mean_eti_organizer = wb_eti[wb_eti['eval_training_code'] == code]['eti_organizer'].mean() mean_eti_trainee_relevan = wb_eti[wb_eti['eval_training_code'] == code]['eti_trainee_relevan'].mean() mean_eti_trainee_manfaat = wb_eti[wb_eti['eval_training_code'] == code]['eti_trainee_manfaat'].mean() all_eti_essay_1 = "<br>".join( wb_eti[wb_eti['eval_training_code'] == code]['eti_essay_1']) all_eti_essay_2 = "<br>".join( wb_eti[wb_eti['eval_training_code'] == code]['eti_essay_2']) all_eti_essay_3 = "<br>".join( wb_eti[wb_eti['eval_training_code'] == code]['eti_essay_3']) df_trainee_postest = wb_trainee[wb_trainee['event_code'] == event] df_trainee_postest = df_trainee_postest.loc[:, [ 'trainee_name', 'NIK', 'dept', 'nilai_post_test' ]] body1 = f"""Dear {trainer},<br> Terimakasih sudah membawakan materi training. Berikut adalah Evaluasi Training Internal dari peserta training.<br><br> Topik\t\t: {topic} <br> Hari/tanggal\t\t: {hartang} <br> Waktu/durasi\t\t: {wakdar} <br> Tempat\t\t: {loc} <br> Jumlah peserta\t\t: {sumtrainee} <br><br>""" body2 = f"""<table border="1"> <tr> <th>Aspek Trainer</th> <th>Skala Nilai</th> </tr> <tr> <td>Penguasaan materi</td> <td>{mean_eti_trainer_materi:.2f}</td> </tr> <tr> <td>Penampilan & body language</td> <td>{mean_eti_trainer_penampilan:.2f}</td> </tr> <tr> <td>Kemampuan interaksi</td> <td>{mean_eti_trainer_interaksi:.2f}</td> </tr> <tr> <td>Alokasi waktu training</td> <td>{mean_eti_trainer_waktu:.2f}</td> </tr> </table><br><br>""" body3 = f"""<table border="1"> <tr> <th>Aspek Materi</th> <th>Skala Nilai</th> </tr> <tr> <td>Bobot</td> <td>{mean_eti_materi_bobot:.2f}</td> </tr> <tr> <td>Kejelasan</td> <td>{mean_eti_materi_jelas:.2f}</td> </tr> <tr> <td>Kesesuaian materi dgn objective training</td> <td>{mean_eti_materi_objective:.2f}</td> </tr> </table><br><br>""" body4 = f"""<table border="1"> <tr> <th>Aspek Metode</th> <th>Skala Nilai</th> </tr> <tr> <td>Kesesuaian metode dgn objective training</td> <td>{mean_eti_metode_objective:.2f}</td> </tr> </table><br><br>""" body5 = f"""<table border="1"> <tr> <th>Aspek Organizer</th> <th>Skala Nilai</th> </tr> <tr> <td>Layout, suhu & kebersihan ruangan</td> <td>{mean_eti_organizer:.2f}</td> </tr> </table><br><br>""" body6 = f"""<table border="1"> <tr> <th>Aspek Trainee</th> <th>Skala Nilai</th> </tr> <tr> <td>Relevansi ke pekerjaan</td> <td>{mean_eti_trainee_relevan:.2f}</td> </tr> <tr> <td>Manfaat ke pekerjaan</td> <td>{mean_eti_trainee_manfaat:.2f}</td> </tr> <tr> <td>Poin-poin penting yg bermanfaat bagi pekerjaan</td> <td>{all_eti_essay_1}</td> </tr> <tr> <td>Poin-poin yg akan diimplementasikan dalam pekerjaan</td> <td>{all_eti_essay_2}</td> </tr> </table><br><br>""" body7 = f"""<table border="1"> <tr> <th>Usulan Perbaikan</th> </tr> <tr> <td>{all_eti_essay_3}</td> </tr> </table><br><br>""" body8 = f"""<table border="1"> <tr> <th>Nama Peserta</th> <th>NIK</th> <th>Dept</th> <th>Nilai post-test</th> </tr>""" for i in df_trainee_postest.index: body8 += f"""<tr> <td>{df_trainee_postest.trainee_name[i]}</td> <td>{df_trainee_postest.NIK[i]}</td> <td>{df_trainee_postest.dept[i]}</td> <td>{df_trainee_postest.nilai_post_test[i]}</td> </tr>""" body8 += """</table><br><br>""" body9 = "Terimakasih,<br>Salam,<br>YDL<br>" body10 = f"{quote}" body = body1 + body2 + body3 + body4 + body5 + body6 + body7 + body8 + body9 + body10 msg = MIMEMultipart() msg['From'] = fro msg['To'] = ",".join(list_to) # msg['Cc'] = ",".join(['*****@*****.**']) msg['Subject'] = f"Report ETI {topic}" msg.add_header('reply-to', ",".join([fro, '*****@*****.**'])) msg.attach(MIMEText(body, 'html')) idx = wb_main[wb_main['event_code'] == event].index[0] update_excel(idx, column="M") mailServer = smtplib.SMTP('smtp.gmail.com', 587) mailServer.ehlo() mailServer.starttls() mailServer.ehlo() mailServer.login(login, password) mailServer.sendmail(fro, list_to, msg.as_string()) mailServer.close() print( "Report ETI", event, "-", wb_main[wb_main['event_code'] == event]['event_name'].iloc[0], "." * (35 - len(wb_main[wb_main['event_code'] == event] ['event_name'].iloc[0])), 'done')
def main(): module = AnsibleModule( argument_spec=dict( username=dict(type='str'), password=dict(type='str', no_log=True), host=dict(type='str', default='localhost'), port=dict(type='int', default=25), sender=dict(type='str', default='root', aliases=['from']), to=dict(type='list', default=['root'], aliases=['recipients']), cc=dict(type='list', default=[]), bcc=dict(type='list', default=[]), subject=dict(type='str', required=True, aliases=['msg']), body=dict(type='str'), attach=dict(type='list', default=[]), headers=dict(type='list', default=[]), charset=dict(type='str', default='utf-8'), subtype=dict(type='str', default='plain', choices=['html', 'plain']), secure=dict(type='str', default='try', choices=['always', 'never', 'starttls', 'try']), timeout=dict(type='int', default=20), ), required_together=[['password', 'username']], ) username = module.params.get('username') password = module.params.get('password') host = module.params.get('host') port = module.params.get('port') sender = module.params.get('sender') recipients = module.params.get('to') copies = module.params.get('cc') blindcopies = module.params.get('bcc') subject = module.params.get('subject') body = module.params.get('body') attach_files = module.params.get('attach') headers = module.params.get('headers') charset = module.params.get('charset') subtype = module.params.get('subtype') secure = module.params.get('secure') timeout = module.params.get('timeout') code = 0 secure_state = False sender_phrase, sender_addr = parseaddr(sender) if not body: body = subject try: if secure != 'never': try: smtp = smtplib.SMTP_SSL(timeout=timeout) code, smtpmessage = smtp.connect(host, port=port) secure_state = True except ssl.SSLError as e: if secure == 'always': module.fail_json(rc=1, msg='Unable to start an encrypted session to %s:%s: %s' % (host, port, to_native(e)), exception=traceback.format_exc()) if not secure_state: smtp = smtplib.SMTP(timeout=timeout) code, smtpmessage = smtp.connect(host, port=port) except smtplib.SMTPException as e: module.fail_json(rc=1, msg='Unable to Connect %s:%s: %s' % (host, port, to_native(e)), exception=traceback.format_exc()) try: smtp.ehlo() except smtplib.SMTPException as e: module.fail_json(rc=1, msg='Helo failed for host %s:%s: %s' % (host, port, to_native(e)), exception=traceback.format_exc()) if int(code) > 0: if not secure_state and secure in ('starttls', 'try'): if smtp.has_extn('STARTTLS'): try: smtp.starttls() secure_state = True except smtplib.SMTPException as e: module.fail_json(rc=1, msg='Unable to start an encrypted session to %s:%s: %s' % (host, port, to_native(e)), exception=traceback.format_exc()) try: smtp.ehlo() except smtplib.SMTPException as e: module.fail_json(rc=1, msg='Helo failed for host %s:%s: %s' % (host, port, to_native(e)), exception=traceback.format_exc()) else: if secure == 'starttls': module.fail_json(rc=1, msg='StartTLS is not offered on server %s:%s' % (host, port)) if username and password: if smtp.has_extn('AUTH'): try: smtp.login(username, password) except smtplib.SMTPAuthenticationError: module.fail_json(rc=1, msg='Authentication to %s:%s failed, please check your username and/or password' % (host, port)) except smtplib.SMTPException: module.fail_json(rc=1, msg='No Suitable authentication method was found on %s:%s' % (host, port)) else: module.fail_json(rc=1, msg="No Authentication on the server at %s:%s" % (host, port)) if not secure_state and (username and password): module.warn('Username and Password was sent without encryption') msg = MIMEMultipart(_charset=charset) msg['From'] = formataddr((sender_phrase, sender_addr)) msg['Subject'] = Header(subject, charset) msg.preamble = "Multipart message" for header in headers: # NOTE: Backward compatible with old syntax using '|' as delimiter for hdr in [x.strip() for x in header.split('|')]: try: h_key, h_val = hdr.split('=') h_val = to_native(Header(h_val, charset)) msg.add_header(h_key, h_val) except Exception: module.warn("Skipping header '%s', unable to parse" % hdr) if 'X-Mailer' not in msg: msg.add_header('X-Mailer', 'Ansible mail module') addr_list = [] for addr in [x.strip() for x in blindcopies]: addr_list.append(parseaddr(addr)[1]) # address only, w/o phrase to_list = [] for addr in [x.strip() for x in recipients]: to_list.append(formataddr(parseaddr(addr))) addr_list.append(parseaddr(addr)[1]) # address only, w/o phrase msg['To'] = ", ".join(to_list) cc_list = [] for addr in [x.strip() for x in copies]: cc_list.append(formataddr(parseaddr(addr))) addr_list.append(parseaddr(addr)[1]) # address only, w/o phrase msg['Cc'] = ", ".join(cc_list) part = MIMEText(body + "\n\n", _subtype=subtype, _charset=charset) msg.attach(part) # NOTE: Backware compatibility with old syntax using space as delimiter is not retained # This breaks files with spaces in it :-( for filename in attach_files: try: part = MIMEBase('application', 'octet-stream') with open(filename, 'rb') as fp: part.set_payload(fp.read()) encoders.encode_base64(part) part.add_header('Content-disposition', 'attachment', filename=os.path.basename(filename)) msg.attach(part) except Exception as e: module.fail_json(rc=1, msg="Failed to send mail: can't attach file %s: %s" % (filename, to_native(e)), exception=traceback.format_exc()) composed = msg.as_string() try: result = smtp.sendmail(sender_addr, set(addr_list), composed) except Exception as e: module.fail_json(rc=1, msg="Failed to send mail to '%s': %s" % (", ".join(set(addr_list)), to_native(e)), exception=traceback.format_exc()) smtp.quit() if result: for key in result: module.warn("Failed to send mail to '%s': %s %s" % (key, result[key][0], result[key][1])) module.exit_json(msg='Failed to send mail to at least one recipient', result=result) module.exit_json(msg='Mail sent successfully', result=result)
# Create message container. The correct MIME type is multipart/alternative. msg = MIMEMultipart('alternative') # Add sender and recipient addresses to the message msg['From'] = SENDER msg['To'] = RECIPIENT msg['Cc'] = CCRECIPIENT msg['Bcc'] = BCCRECIPIENT # Add the subject line, text body, and HTML body to the message. msg['Subject'] = SUBJECT msg.attach(textPart) msg.attach(htmlPart) # Add headers for configuration set and message tags to the message. msg.add_header('X-SES-CONFIGURATION-SET', CONFIGURATION_SET) msg.add_header('X-SES-MESSAGE-TAGS', TAG0) msg.add_header('X-SES-MESSAGE-TAGS', TAG1) # Open a new connection to the SMTP server and begin the SMTP conversation. try: with smtplib.SMTP(HOST, PORT) as server: server.ehlo() server.starttls() #stmplib docs recommend calling ehlo() before and after starttls() server.ehlo() server.login(USERNAME_SMTP, PASSWORD_SMTP) #Uncomment the next line to send SMTP server responses to stdout #server.set_debuglevel(1) server.sendmail(SENDER, RECIPIENT, msg.as_string()) except Exception as e:
def send(body, subject, attachments=None): """Read a configuration file. Args: body: Text for email body subject: Subject for email attachments: List of filepaths to attach Returns: success: True if succesful """ # Initialize key variables success = False config = Config() # Create SMTP TLS session client = smtplib.SMTP('smtp.gmail.com', 587) try: client.ehlo() except: _exception = sys.exc_info() log_message = 'Gmail Communication Failure' log.log2exception(1013, _exception, message=log_message) client.starttls() # Authentication try: client.login(config.smtp_user, config.smtp_pass) except: _exception = sys.exc_info() log_message = 'Gmail Authentication Failure' log.log2exception(1014, _exception, message=log_message) return success # Format message message = MIMEMultipart() message['Subject'] = subject message['From'] = config.email_from message['To'] = ', '.join(config.email_to) message.add_header('reply-to', config.email_from) html = ''' <html> <head></head> <body><font face="courier"> {} </font></body> </html> '''.format('<br>'.join(' '.join(body.split(' ')).split('\n'))) message.attach(MIMEText(html, 'html', 'UTF-8')) # Add attachment if required if bool(attachments) is True: if isinstance(attachments, list) is True: for attachment in attachments: part = MIMEApplication(open(attachment, 'rb').read()) part.add_header('Content-Disposition', 'attachment', filename=('{}'.format(attachment))) message.attach(part) # Send try: client.sendmail(config.email_from, config.email_to, message.as_string()) success = True except: _exception = sys.exc_info() log_message = 'Gmail Send Failure' log.log2exception(1015, _exception, message=log_message) return success finally: client.quit() return success
class Mdn(object): """Class for handling AS2 MDNs. Includes functions for both parsing and building them. """ def __init__(self, mdn_mode=None, digest_alg=None, mdn_url=None): self.message_id = None self.orig_message_id = None self.payload = None self.mdn_mode = mdn_mode self.digest_alg = digest_alg self.mdn_url = mdn_url @property def content(self): """Function returns the body of the mdn message as a byte string""" if self.payload is not None: message_bytes = mime_to_bytes(self.payload) boundary = b"--" + self.payload.get_boundary().encode("utf-8") temp = message_bytes.split(boundary) temp.pop(0) return boundary + boundary.join(temp) else: return "" @property def headers(self): if self.payload: return dict(self.payload.items()) else: return {} @property def headers_str(self): message_header = "" if self.payload: for k, v in self.headers.items(): message_header += f"{k}: {v}\r\n" return message_header.encode("utf-8") def build( self, message, status, detailed_status=None, confirmation_text=MDN_CONFIRM_TEXT, failed_text=MDN_FAILED_TEXT, ): """Function builds and signs an AS2 MDN message. :param message: The received AS2 message for which this is an MDN. :param status: The status of processing of the received AS2 message. :param detailed_status: The optional detailed status of processing of the received AS2 message. Used to give additional error info (default "None") :param confirmation_text: The confirmation message sent in the first part of the MDN. :param failed_text: The failure message sent in the first part of the failed MDN. """ # Generate message id using UUID 1 as it uses both hostname and time self.message_id = email_utils.make_msgid().lstrip("<").rstrip(">") self.orig_message_id = message.message_id # Set up the message headers mdn_headers = { "AS2-Version": AS2_VERSION, "ediint-features": EDIINT_FEATURES, "Message-ID": f"<{self.message_id}>", "AS2-From": quote_as2name(message.headers.get("as2-to")), "AS2-To": quote_as2name(message.headers.get("as2-from")), "Date": email_utils.formatdate(localtime=True), "user-agent": "pyAS2 Open Source AS2 Software", } # Set the confirmation text message here # overwrite with organization specific message if message.receiver and message.receiver.mdn_confirm_text: confirmation_text = message.receiver.mdn_confirm_text # overwrite with partner specific message if message.sender and message.sender.mdn_confirm_text: confirmation_text = message.sender.mdn_confirm_text if status != "processed": confirmation_text = failed_text self.payload = MIMEMultipart("report", report_type="disposition-notification") # Create and attach the MDN Text Message mdn_text = email_message.Message() mdn_text.set_payload(f"{confirmation_text}\r\n") mdn_text.set_type("text/plain") del mdn_text["MIME-Version"] encoders.encode_7or8bit(mdn_text) self.payload.attach(mdn_text) # Create and attache the MDN Report Message mdn_base = email_message.Message() mdn_base.set_type("message/disposition-notification") mdn_report = "Reporting-UA: pyAS2 Open Source AS2 Software\r\n" mdn_report += f'Original-Recipient: rfc822; {message.headers.get("as2-to")}\r\n' mdn_report += f'Final-Recipient: rfc822; {message.headers.get("as2-to")}\r\n' mdn_report += f"Original-Message-ID: <{message.message_id}>\r\n" mdn_report += f"Disposition: automatic-action/MDN-sent-automatically; {status}" if detailed_status: mdn_report += f": {detailed_status}" mdn_report += "\r\n" if message.mic: mdn_report += f"Received-content-MIC: {message.mic.decode()}, {message.digest_alg}\r\n" mdn_base.set_payload(mdn_report) del mdn_base["MIME-Version"] encoders.encode_7or8bit(mdn_base) self.payload.attach(mdn_base) logger.debug( f"MDN report for message {message.message_id} created:\n{mime_to_bytes(mdn_base)}" ) # Sign the MDN if it is requested by the sender if ( message.headers.get("disposition-notification-options") and message.receiver and message.receiver.sign_key ): self.digest_alg = ( message.headers["disposition-notification-options"] .split(";")[-1] .split(",")[-1] .strip() .replace("-", "") ) signed_mdn = MIMEMultipart("signed", protocol="application/pkcs7-signature") del signed_mdn["MIME-Version"] signed_mdn.attach(self.payload) # Create the signature mime message signature = email_message.Message() signature.set_type("application/pkcs7-signature") signature.set_param("name", "smime.p7s") signature.set_param("smime-type", "signed-data") signature.add_header( "Content-Disposition", "attachment", filename="smime.p7s" ) del signature["MIME-Version"] signed_data = sign_message( canonicalize(self.payload), self.digest_alg, message.receiver.sign_key ) signature.set_payload(signed_data) encoders.encode_base64(signature) signed_mdn.set_param("micalg", self.digest_alg) signed_mdn.attach(signature) self.payload = signed_mdn logger.debug(f"Signing the MDN for message {message.message_id}") # Update the headers of the final payload and set message boundary for k, v in mdn_headers.items(): if self.payload.get(k): self.payload.replace_header(k, v) else: self.payload.add_header(k, v) self.payload.set_boundary(make_mime_boundary()) logger.debug( f"MDN generated for message {message.message_id} with " f"content:\n {mime_to_bytes(self.payload)}" ) def parse(self, raw_content, find_message_cb): """Function parses the RAW AS2 MDN, verifies it and extracts the processing status of the orginal AS2 message. :param raw_content: A byte string of the received HTTP headers followed by the body. :param find_message_cb: A callback the must returns the original Message Object. The original message-id and original recipient AS2 ID are passed as arguments to it. :returns: A two element tuple containing (status, detailed_status). The status is a string indicating the status of the transaction. The optional detailed_status gives additional information about the processing status. """ status, detailed_status = None, None try: self.payload = parse_mime(raw_content) self.orig_message_id, orig_recipient = self.detect_mdn() # Call the find message callback which should return a Message instance orig_message = find_message_cb(self.orig_message_id, orig_recipient) # Extract the headers and save it mdn_headers = {} for k, v in self.payload.items(): k = k.lower() if k == "message-id": self.message_id = v.lstrip("<").rstrip(">") mdn_headers[k] = v if ( orig_message.receiver.mdn_digest_alg and self.payload.get_content_type() != "multipart/signed" ): status = "failed/Failure" detailed_status = "Expected signed MDN but unsigned MDN returned" return status, detailed_status if self.payload.get_content_type() == "multipart/signed": logger.debug(f"Verifying signed MDN: \n{mime_to_bytes(self.payload)}") message_boundary = ("--" + self.payload.get_boundary()).encode("utf-8") # Extract the signature and the signed payload signature = None signature_types = [ "application/pkcs7-signature", "application/x-pkcs7-signature", ] for part in self.payload.walk(): if part.get_content_type() in signature_types: signature = part.get_payload(decode=True) elif part.get_content_type() == "multipart/report": self.payload = part # Verify the message, first using raw message and if it fails # then convert to canonical form and try again mic_content = extract_first_part(raw_content, message_boundary) verify_cert = orig_message.receiver.load_verify_cert() try: self.digest_alg = verify_message( mic_content, signature, verify_cert ) except IntegrityError: mic_content = canonicalize(self.payload) self.digest_alg = verify_message( mic_content, signature, verify_cert ) for part in self.payload.walk(): if part.get_content_type() == "message/disposition-notification": logger.debug( f"MDN report for message {orig_message.message_id}:\n{part.as_string()}" ) mdn = part.get_payload()[-1] mdn_status = mdn["Disposition"].split(";").pop().strip().split(":") status = mdn_status[0] if status == "processed": # Compare the original mic with the received mic mdn_mic = mdn.get("Received-Content-MIC", "").split(",")[0] if ( mdn_mic and orig_message.mic and mdn_mic != orig_message.mic.decode() ): status = "processed/warning" detailed_status = "Message Integrity check failed." else: detailed_status = " ".join(mdn_status[1:]).strip() except MDNNotFound: status = "failed/Failure" detailed_status = "mdn-not-found" except Exception as e: status = "failed/Failure" detailed_status = f"Failed to parse received MDN. {e}" logger.error(f"Failed to parse AS2 MDN\n: {traceback.format_exc()}") finally: return status, detailed_status def detect_mdn(self): """ Function checks if the received raw message is an AS2 MDN or not. :raises MDNNotFound: If the received payload is not an MDN then this exception is raised. :return: A two element tuple containing (message_id, message_recipient). The message_id is the original AS2 message id and the message_recipient is the original AS2 message recipient. """ mdn_message = None if self.payload.get_content_type() == "multipart/report": mdn_message = self.payload elif self.payload.get_content_type() == "multipart/signed": for part in self.payload.walk(): if part.get_content_type() == "multipart/report": mdn_message = self.payload if not mdn_message: raise MDNNotFound("No MDN found in the received message") message_id, message_recipient = None, None for part in mdn_message.walk(): if part.get_content_type() == "message/disposition-notification": mdn = part.get_payload()[0] message_id = mdn.get("Original-Message-ID").strip("<>") message_recipient = mdn.get("Original-Recipient").split(";")[1].strip() return message_id, message_recipient
# ======= START OF EMAIL SETUP CONTENT ====== # if send_email in ['true', '1', 't', 'y', 'yes']: server = smtplib.SMTP('smtp.gmail.com:587') msg = MIMEMultipart() msg['Subject'] = 'MyProject Automation Status' sender = '*****@*****.**' recipients = ['*****@*****.**', '*****@*****.**'] ccrecipients = ['*****@*****.**', '*****@*****.**'] msg['From'] = sender msg['To'] = ", ".join(recipients) msg['Cc'] = ", ".join(ccrecipients) password = "******" msg.add_header('Content-Type', 'text/html') # ======= END OF EMAIL SETUP CONTENT ====== # head_content = """ <!doctype html> <html lang="en"> <head> <link rel="shortcut icon" href="https://png.icons8.com/windows/50/000000/bot.png" type="image/x-icon" /> <title>RF Metrics Report</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet"/>
def sendmessage(self, message, options={}): result = error = None profile = self.account.get('profile', {}) from_email = from_ = profile['emails'][0]['value'] fullname = profile.get('displayName', None) if fullname: from_email = '"%s" <%s>' % (Header(fullname, 'utf-8').encode(), Header(from_, 'utf-8').encode(),) url = "https://mail.google.com/mail/b/%s/smtp/" % from_ to_ = options.get('to', None) if not to_ or not '@' in to_: return None, { "provider": self.host, "message": "recipient address is invalid", "status": 0 } to_ = parseaddr(to_) if to_[0]: to_ = '"%s" <%s>' % (Header(to_[0], 'utf-8').encode(), Header(to_[1], 'utf-8').encode()) else: to_ = Header(to_[1], 'utf-8').encode() server = SMTP(self.host, self.port) # in the app:main set debug = true to enable if asbool(config.get('debug', False)): server.set_debuglevel(True) subject = options.get('subject', config.get('share_subject', 'A web link has been shared with you')) title = options.get('title', options.get('link', options.get('shorturl', ''))) description = options.get('description', '')[:280] msg = MIMEMultipart('alternative') msg.set_charset('utf-8') msg.add_header('Subject', Header(subject, 'utf-8').encode()) msg.add_header('From', from_email) msg.add_header('To', to_) c.safeHTML = safeHTML c.options = options # insert the url if it is not already in the message c.longurl = options.get('link') c.shorturl = options.get('shorturl') # reset to unwrapped for html email, they will be escaped c.from_name = fullname c.subject = subject c.from_header = from_ c.to_header = to_ c.title = title c.description = description c.message = message c.thumbnail = (options.get('picture_base64', "") != "") if c.thumbnail: part2 = MIMEMultipart('related') html = MIMEText(render('/html_email.mako').encode('utf-8'), 'html') html.set_charset('utf-8') # FIXME: we decode the base64 data just so MIMEImage can re-encode it as base64 image = MIMEImage(base64.b64decode(options.get('picture_base64')), 'png') image.add_header('Content-Id', '<thumbnail>') image.add_header('Content-Disposition', 'inline; filename=thumbnail.png') part2.attach(html) part2.attach(image) else: part2 = MIMEText(render('/html_email.mako').encode('utf-8'), 'html') part2.set_charset('utf-8') # get the title, or the long url or the short url or nothing # wrap these in literal for text email c.from_name = literal(fullname) c.subject = literal(subject) c.from_header = literal(from_) c.to_header = literal(to_) c.title = literal(title) c.description = literal(description) c.message = literal(message) part1 = MIMEText(render('/text_email.mako').encode('utf-8'), 'plain') part1.set_charset('utf-8') msg.attach(part1) msg.attach(part2) try: try: try: server.starttls() except smtplib.SMTPException: logger.info("smtp server does not support TLS") try: server.ehlo_or_helo_if_needed() server.authenticate(url, self.consumer, self.oauth_token) server.sendmail(from_, to_, msg.as_string()) except smtplib.SMTPRecipientsRefused, exc: for to_, err in exc.recipients.items(): error = {"provider": self.host, "message": err[1], "status": err[0] } break except smtplib.SMTPException, exc: error = {"provider": self.host, "message": "%s: %s" % (exc.smtp_code, exc.smtp_error), "status": exc.smtp_code } except UnicodeEncodeError, exc: raise
class EmailFormatter(object): def __init__(self, msg_object): self.msg_obj = msg_object self.message = MIMEMultipart() self.message.set_charset("utf-8") def build_email(self): # Setting Message ID self.message.set_param("Message-ID", self.msg_obj.message_id) # Encoding for unicode subject self.message["Subject"] = Header(self.msg_obj.subject, charset="UTF-8") # Setting Date Time # Returns a date string as specified by RFC 2822, e.g.: Fri, 09 Nov 2001 01:08:47 -0000 self.message["Date"] = str(self.msg_obj.sent_date) # At least one recipient is required # Required fromAddress from_address = flatten_list(self.msg_obj.sender) if from_address: self.message["From"] = from_address to_address = flatten_list(self.msg_obj.header_dict.get("To")) if to_address: self.message["To"] = to_address cc_address = flatten_list(self.msg_obj.header_dict.get("CC")) if cc_address: self.message["CC"] = cc_address bcc_address = flatten_list(self.msg_obj.header_dict.get("BCC")) if bcc_address: self.message["BCC"] = bcc_address # Add reply-to reply_to = flatten_list(self.msg_obj.reply_to) if reply_to: self.message.add_header("reply-to", reply_to) else: self.message.add_header("reply-to", from_address) # Required Email body content body_content = self.msg_obj.body if body_content: if "<html>" in body_content: body_type = "html" else: body_type = "plain" body = MIMEText(_text=body_content, _subtype=body_type, _charset="UTF-8") self.message.attach(body) else: raise KeyError("Missing email body") # Add message preamble self.message.preamble = "You will not see this in a MIME-aware mail reader.\n" # Optional attachments attachments = self.msg_obj.attachments if len(attachments) > 0: # Some issues here, where data is None or is bytes-like object. self._process_attachments(self.msg_obj.attachments) # composed email composed = self.message.as_string() return composed def save_file(self, file_path, file_name=None): eml_content = self.build_email() file_name = file_name if file_name is not None else str( self.message["Subject"]) + ".eml" eml_file_path = os.path.join(file_path, file_name) with codecs.open(eml_file_path, mode="wb+", encoding="utf-8") as eml_file: eml_file.write(eml_content) return eml_file_path def _process_attachments(self, attachments): for attachment in attachments: ctype = attachment.AttachMimeTag data = attachment.data filename = attachment.Filename maintype, subtype = ctype.split("/", 1) if data is None: continue if maintype == "text" or "message" in maintype: if isinstance(data, bytes): data = data.decode("utf-8", "ignore") attach = MIMEText(data, _subtype=subtype) elif maintype == "image": attach = MIMEImage(data, _subtype=subtype) elif maintype == "audio": attach = MIMEAudio(data, _subtype=subtype) else: attach = MIMEBase(maintype, subtype) attach.set_payload(data) # Encode the payload using Base64 encoders.encode_base64(attach) # Set the filename parameter base_filename = os.path.basename(filename) attach.add_header("Content-ID", "<{}>".format(base_filename)) attach.add_header("Content-Disposition", "attachment", filename=base_filename) self.message.attach(attach)
from smtplib import SMTP_SSL, SMTP_SSL_PORT from email.mime.multipart import MIMEMultipart, MIMEBase from email.mime.text import MIMEText from email.encoders import encode_base64 from_email = 'John Leon <*****@*****.**>' # or simply the email address to_emails = ['*****@*****.**', '*****@*****.**'] # Create multipart MIME email email_message = MIMEMultipart() email_message.add_header('To', ', '.join(to_emails)) email_message.add_header('From', from_email) email_message.add_header('Subject', 'Hello!') email_message.add_header('X-Priority', '2') # Urgent/High priority # Create text and HTML bodies for email text_part = MIMEText('Hello world plain text!', 'plain') html_part = MIMEText('<html><body><h1>HTML!</h1></body></html>', 'html') # Create file attachment attachment = MIMEBase("application", "octet-stream") attachment.set_payload(b'\xDE\xAD\xBE\xEF') # Raw attachment data encode_base64(attachment) attachment.add_header("Content-Disposition", "attachment; filename=myfile.dat") # Attach all the parts to the Multipart MIME email email_message.attach(text_part) email_message.attach(html_part) email_message.attach(attachment) # Connect, authenticate, and send mail
def handle( alert, type='smtp', sender_email=None, recipient_email=None, text=None, html=None, subject=None, reply_to=None, cc=None, bcc=None, ): if not os.environ.get('SMTP_SERVER'): log.info("No SMTP_SERVER in env, skipping handler.") return None smtp_server = os.environ['SMTP_SERVER'] if 'SMTP_PORT' in os.environ: smtp_port = os.environ['SMTP_PORT'] else: smtp_port = 587 if 'SMTP_USE_SSL' in os.environ: smtp_use_ssl = os.environ['SMTP_USE_SSL'] else: smtp_use_ssl = True if 'SMTP_USE_TLS' in os.environ: smtp_use_tls = os.environ['SMTP_USE_TLS'] else: smtp_use_tls = True smtp_user = vault.decrypt_if_encrypted(os.environ['SMTP_USER']) smtp_password = vault.decrypt_if_encrypted(os.environ['SMTP_PASSWORD']) if recipient_email is None: log.error(f"Cannot identify recipient email") return None if text is None: log.error(f"SES Message is empty") return None # Create the base MIME message. if html is None: message = MIMEMultipart() else: message = MIMEMultipart('alternative') # Add HTML/plain-text parts to MIMEMultipart message # The email client will try to render the last part first # Turn these into plain/html MIMEText objects textPart = MIMEText(text, 'plain') message.attach(textPart) if html is not None: htmlPart = MIMEText(html, 'html') message.attach(htmlPart) message['Subject'] = subject message['From'] = sender_email message['To'] = recipient_email recipients = recipient_email.split(',') if cc is not None: message['Cc'] = cc recipients = recipients + cc.split(',') if bcc is not None: recipients = recipients + bcc.split(',') if reply_to is not None: message.add_header('reply-to', reply_to) if smtp_use_ssl is True: context = ssl.create_default_context() if smtp_use_tls is True: smtpserver = smtplib.SMTP(smtp_server, smtp_port) smtpserver.starttls(context=context) else: smtpserver = smtplib.SMTP_SSL(smtp_server, smtp_port, context=context) else: smtpserver = smtplib.SMTP(smtp_server, smtp_port) smtpserver.login(smtp_user, smtp_password) smtpserver.sendmail(sender_email, recipients, message.as_string()) smtpserver.close()
def send_simple_mail(sender, receiver, subject, msgtxt, attachments=None, usergenerated=False, cc=None, replyto=None, sendername=None, receivername=None, messageid=None, suppress_auto_replies=True, is_auto_reply=False, htmlbody=None, headers={}, staggertype=None, stagger=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() if suppress_auto_replies: # Do our best to set some headers to indicate that auto-replies like out of office # messages should not be sent to this email. msg['X-Auto-Response-Suppress'] = 'All' # Is this email auto-generated or auto-replied? if is_auto_reply: msg['Auto-Submitted'] = 'auto-replied' elif not usergenerated: msg['Auto-Submitted'] = 'auto-generated' for h, v in headers.items(): if h in msg: # Replace the existing header -- the one specified is supposedly overriding it msg.replace_header(h, v) else: msg.add_header(h, v) if htmlbody: mpart = MIMEMultipart("alternative") mpart.attach(MIMEText(msgtxt, _charset=_utf8_charset)) mpart.attach(MIMEText(htmlbody, 'html', _charset=_utf8_charset)) msg.attach(mpart) else: # Just a plaintext body, so append it directly msg.attach(MIMEText(msgtxt, _charset='utf-8')) if attachments: for a in attachments: main, sub = a['contenttype'].split('/') part = MIMENonMultipart(main, sub) part.set_payload(a['content']) part.add_header('Content-Disposition', a.get('disposition', 'attachment; filename="%s"' % a['filename'])) if 'id' in a: part.add_header('Content-ID', a['id']) encoders.encode_base64(part) msg.attach(part) with transaction.atomic(): if staggertype and stagger: # Don't send a second one too close after another one of this class. ls, created = LastSent.objects.get_or_create(type=staggertype, defaults={'lastsent': datetime.now()}) sendat = ls.lastsent = ls.lastsent + stagger ls.save(update_fields=['lastsent']) else: sendat = datetime.now() # Just write it to the queue, so it will be transactionally rolled back QueuedMail(sender=sender, receiver=receiver, fullmsg=msg.as_string(), usergenerated=usergenerated, sendat=sendat).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, sendat=sendat).save()
def get_mail_text(self, fields, request, context): """Get header and body of e-mail as text (string) """ headerinfo = self.get_header_info(fields, request, context) body = self.get_mail_body(fields, request, context) if six.PY2 and isinstance(body, six.text_type): body = body.encode("utf-8") email_charset = "utf-8" # always use text/plain for encrypted bodies subtype = ( getattr(self, "gpg_keyid", False) and "plain" or self.body_type or "html" ) mime_text = MIMEText( safe_unicode(body).encode(email_charset, "replace"), _subtype=subtype, _charset=email_charset, ) attachments = self.get_attachments(fields, request) if attachments: outer = MIMEMultipart() outer.attach(mime_text) else: outer = mime_text # write header for key, value in headerinfo.items(): outer[key] = value # write additional header additional_headers = self.additional_headers or [] for a in additional_headers: key, value = a.split(":", 1) outer.add_header(key, value.strip()) for attachment in attachments: filename = attachment[0] ctype = attachment[1] # encoding = attachment[2] content = attachment[3] if ctype is None: ctype = "application/octet-stream" maintype, subtype = ctype.split("/", 1) if maintype == "text": if not six.PY2 and isinstance(content, six.binary_type): content = content.decode("utf-8") msg = MIMEText(content, _subtype=subtype) elif maintype == "image": msg = MIMEImage(content, _subtype=subtype) elif maintype == "audio": msg = MIMEAudio(content, _subtype=subtype) else: msg = MIMEBase(maintype, subtype) msg.set_payload(content) # Encode the payload using Base64 encoders.encode_base64(msg) # Set the filename parameter if six.PY2 and isinstance(filename, six.text_type): filename = filename.encode("utf-8") msg.add_header( "Content-Disposition", "attachment", filename=("utf-8", "", filename) ) outer.attach(msg) return outer.as_string()
class Email: """ Costumized email class based on python's 'email' libary. Initiated instances of this class will allow to send e-mails from John's gmail account. The accound username and password are stored in a separate file that is not synchronised ... TO DO: - write method that can detach already attached mail attachments. """ def __init__(self, sender, recipients, cc=[], bcc=[], replyto=[], subject='', text='', attachments=[], connection='ssl'): """ Prepares mail container and puts in header, text and attachments, however, it does not send mail yet (see 'send()' method). """ self.sender = sender self.recipients = recipients self.cc = cc self.bcc = bcc self.replyto = replyto self.subject = subject self.text = text self.attachments = attachments self.connection = connection self.is_sent = False # mail container self.__msgBasis = MIMEMultipart('mixed') # mail header self._prepare_headerMail() # mail attachments self._attachmentsMail( self.attachments ) def send(self): username, password = secrets_personal.gmail_auth() server = self._connectSMPT(self.connection, username, password) #server.verify(sender) server.sendmail(self.sender, self.recipients + self.cc + self.bcc, self.__msgBasis.as_string()) server.quit() self.is_sent = True def attach(self, file): self._attachmentsMail( file, single_add=True ) def detach(self, file): # to bon programmed .. pass def show(self): pprint.pprint(self.__dict__) def _validMail(self, mail): """ Check if passed variable 'mail' is string. If not, make it string. Then, check if 'mail' matches e-mail pattern, if yes, return mail with preceding and succeeding white blancs stripped. If pattern isn't matched, return False (without doing lstrip() / rstrip()) :return: mail / False """ if not isinstance(mail, str) or not re.search(r"\w.@\w+\.\w+", mail): sys.exit(u'ERROR: Given SENDER adress is no valid e-mail string. Exit.') return mail.lstrip().rstrip() def _valid_listMail(self, list_adresses): """ Check if passed list is a list, if yes, check if entries are valid mail adresses. Strips preceding and succeeding white blancs. Return a list only with valid adresses, if there is no valid adress at all, return empty list. :return list_adress """ adresses = [] if isinstance(list_adresses, list): pass elif isinstance(list_adresses, tuple): list_adresses = list(list_adresses) elif isinstance(list_adresses, str): list_adresses = [list_adresses] else: sys.exit(u'ERROR: Given ADDRESSES are no valid list or tuple format. Exit.') for adress in list_adresses: if self._validMail(adress): adresses.append(adress) return adresses def _prepare_headerMail(self): """ Fill header informatione. """ # preamble self.__msgBasis.preamble = "PREAMBLE: How to learn sending e-mails with Python's SMTP!" # date self.__msgBasis['Date'] = formatdate(localtime=True) # dt.datetime.now().strftime('%Y-%m-%d, %H:%M Uhr') #print(msgBasis['Date']) # sender self.__msgBasis['From'] = self._validMail(self.sender) # recipients self.recipients = self._valid_listMail(self.recipients) self.__msgBasis['To'] = ', '.join(self.recipients) # carbon copies self.cc = self._valid_listMail(self.cc) self.__msgBasis['Cc'] = ', '.join(self.cc) # blind carbon copies self.bcc = self._valid_listMail(self.bcc) self.__msgBasis['Bcc'] = ', '.join(self.bcc) # reply-to self.replyto = self._valid_listMail(self.replyto) self.__msgBasis.add_header('reply-to', ', '.join(self.replyto)) # subject try: self.__msgBasis['Subject'] = str(self.subject) except: self.__msgBasis['Subject'] = '' def _attachmentsMail(self, attachments, single_add=False): """ Attach files past as list 'attachments' to e-mail message 'msgBasis' instance. If given attachment cannot be found, it is not attached. """ if isinstance(attachments, (numpy.ndarray, numpy.generic)): pass elif isinstance(attachments, list): attachments = numpy.array( attachments ) elif isinstance(attachments, tuple): attachments = numpy.array( list(attachments) ) elif isinstance(attachments, str): attachments = numpy.array( [attachments] ) else: sys.exit(u'ERROR: Given ATTACHMENTS are no valid list or tuple format of strings. Exit.') ### attach files, if can not be found, state warning and delete from attachment list del_ind = [] for i in range(len(attachments)): if attachments[i] in self.attachments: continue part = MIMEBase('application', "octet-stream") try: part.set_payload(open(attachments[i], "rb").read()) encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(attachments[i])) self.__msgBasis.attach(part) except Exception: del_ind.append(i) print(u"WARNING: Attachment '%s' not found and thus not attached." % attachments[i]) continue # delete faulty attachments from list clean_attachments = list( numpy.delete(attachments,del_ind) ) if single_add == True: self.attachments += clean_attachments elif single_add == False: self.attachments = clean_attachments def _connectSMPT(self, client, username, password): """ Connect to SMTP mail server. :return: smtplib server """ try: if client.lower() == 'tls': try: server = smtplib.SMTP('smtp.gmail.com', 587) server.ehlo() #server.esmtp_features['starttls'] server.starttls() server.ehlo() server.login(username,password) return server except Exception as err: print(u"WARNING: Couldn't establish '%s' connection to server. Proceed with 'ssh', port '465'. Error message:\n%s" % (client, err)) server.quit() client = 'ssl' if client.lower() == 'ssl': server = smtplib.SMTP_SSL('smtp.gmail.com', 465) server.ehlo() server.login(username,password) return server if client.lower() == 'localhost': command = 'python3 -m smtpd -n localhost:25' server = smtplib.SMTP('localhost', 25) server.set_debuglevel(1) return server sys.exit(u"ERROR: You want to connect to a SMTP server which is not known of the time being (choose 'localhost' or 'gmail'). Exit.") except smtplib.SMTPHeloError as err: sys.exit(u"ERROR: Sever didn't reply properly to HELO GREETING! Exit.") except smtplib.SMTPAuthenticationError as err: sys.exit(u"ERROR: Username and/or password not accepted to connect to SMTP server! Exit.") except smtplib.socket.error as err: if client.lower() == 'localhost': print(u'Did you started a local SMTP server? If not, try:%s' % command) sys.exit(u"ERROR: Couldn't connect to '%s' server. Error message:\n%s." % (client, err)) except smtplib.SMTPServerDisconnected as err: sys.exit(u'ERROR: Just try again! Error message:\n%s.' % err) except Exception as err: sys.exit(u'ERROR: Error message:\n%s' % err)
body = MIMEMultipart('alternative') body.attach(MIMEText(msgtext)) body.attach(MIMEText(htmlmsgtext, 'html')) msg.attach(body) if 'attachmentname' in globals(): f = attachmentname part = MIMEBase('application', "octet-stream") part.set_payload(open(f, "rb").read()) Encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f)) msg.attach(part) msg.add_header('From', fromaddr) msg.add_header('To', toaddr) msg.add_header('Subject', msgsubject) msg.add_header('Reply-To', replyto) # The actual email sendy bits server = smtplib.SMTP('smtp.gmail.com:587') server.set_debuglevel( True ) #commenting this out, changing to False will make the script give NO output at all upon successful completion server.starttls() server.login(username, password) server.sendmail(msg['From'], [msg['To']], msg.as_string()) server.quit() except:
def send_alert_mail(self, sender_parm, receivers_parm, mail_subject, lock_dlist): print_hdr = "[" + self.class_name + ": send_alert_mail] - " sender = sender_parm receivers = receivers_parm.split(',') # sendmail method expects receiver parameter as list print (print_hdr + 'lock_dlist count: ' + str(len(lock_dlist))) message = MIMEMultipart("alternative") message['Subject'] = mail_subject message['From'] = sender_parm message['To'] = receivers_parm # This attribute expects string and not list message.add_header('Content-Type', 'text/html') html_msg = """\ <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Hive Lock Alert</title> <style type="text/css" media="screen"> table{ background-color: #AAD373; empty-cells:hide; } th{ border: black 1px solid; } td{ background-color: white; border: black 1px solid; } </style> </head> <body> <table style="border: black 1px solid;"> <tr> <th>Table Name</th> <th>Lock Type</th> <th>Lock User</th> <th>Lock Datetime</th> <th>Current Lock Duration</th> <th>Lock Mode</th> <th>Lock Query Id</th> <th>Lock Query</th> <th>Waiting Job</th> <th>Waiting Job Start Datetime</th> </tr> """ for lock_dict in lock_dlist: html_msg = html_msg + """\ <tr> <td>""" + lock_dict['table_name'] + """</td> <td>""" + lock_dict['lock_type'] + """</td> <td>""" + lock_dict['lock_query_user'] + """</td> <td>""" + lock_dict['lock_datetime'] + """</td> <td>""" + lock_dict['current_lock_duration'] + """ mins</td> <td>""" + lock_dict['lock_mode'] + """</td> <td>""" + lock_dict['lock_query_id'] + """</td> <td>""" + lock_dict['lock_query_string'] + """</td> <td>""" + lock_dict['waiting_job'] + """</td> <td>""" + lock_dict['waiting_job_start_time'] + """</td> </tr>""" html_msg = html_msg + """\ </table> </body>""" # print html_msg try: message.attach(MIMEText(html_msg, 'html')) smtpObj = smtplib.SMTP('localhost') smtpObj.sendmail(sender, receivers, message.as_string()) print (logdt.now().strftime('[%Y-%m-%d %H:%M:%S] ') + print_hdr + "Successfully sent email") except SMTPException: print (logdt.now().strftime('[%Y-%m-%d %H:%M:%S] ') + print_hdr + "Error: unable to send email") except Exception as e: print (logdt.now().strftime('[%Y-%m-%d %H:%M:%S] ') + print_hdr + "ERROR details: " + traceback.format_exc()) finally: try: del message smtpObj.quit() except Exception as e: print (logdt.now().strftime('[%Y-%m-%d %H:%M:%S] ') + print_hdr + "ERROR details: " + traceback.format_exc())
def SendEmail(self, to_addresses, from_address, subject, message, attachments=None, is_html=True, cc_addresses=None, message_id=None, headers=None): """This method sends an email notification. Args: to_addresses: [email protected] string, list of addresses as csv string, or rdf_standard.DomainEmailAddress from_address: [email protected] string subject: email subject string message: message contents string, as HTML or plain text attachments: iterable of filename string and file data tuples, e.g. {"/file/name/string": filedata} is_html: true if message is in HTML format cc_addresses: [email protected] string, or list of addresses as csv string message_id: smtp message_id. Used to enable conversation threading headers: dict of str-> str, headers to set Raises: RuntimeError: for problems connecting to smtp server. """ headers = headers or {} msg = MIMEMultipart("alternative") if is_html: text = self.RemoveHtmlTags(message) part1 = MIMEText(text, "plain") msg.attach(part1) part2 = MIMEText(message, "html") msg.attach(part2) else: part1 = MIMEText(message, "plain") msg.attach(part1) if attachments: for file_name, file_data in iteritems(attachments): part = MIMEBase("application", "octet-stream") part.set_payload(file_data) encoders.encode_base64(part) part.add_header("Content-Disposition", "attachment; filename=\"%s\"" % file_name) msg.attach(part) msg["Subject"] = subject from_address = self.AddEmailDomain(from_address) to_addresses = self.SplitEmailsAndAppendEmailDomain(to_addresses) cc_addresses = self.SplitEmailsAndAppendEmailDomain(cc_addresses or "") msg["From"] = from_address msg["To"] = ",".join(to_addresses) if cc_addresses: msg["CC"] = ",".join(cc_addresses) if message_id: msg.add_header("Message-ID", message_id) for header, value in iteritems(headers): msg.add_header(header, value) try: s = smtplib.SMTP(config.CONFIG["Worker.smtp_server"], int(config.CONFIG["Worker.smtp_port"])) s.ehlo() if config.CONFIG["Worker.smtp_starttls"]: s.starttls() s.ehlo() if (config.CONFIG["Worker.smtp_user"] and config.CONFIG["Worker.smtp_password"]): s.login(config.CONFIG["Worker.smtp_user"], config.CONFIG["Worker.smtp_password"]) s.sendmail(from_address, to_addresses + cc_addresses, msg.as_string()) s.quit() except (socket.error, smtplib.SMTPException) as e: raise RuntimeError("Could not connect to SMTP server to send email. " "Please check config option Worker.smtp_server. " "Currently set to %s. Error: %s" % (config.CONFIG["Worker.smtp_server"], e))
style0 = xlwt.easyxf('font: bold on') ws.write(0, 0, "KMS LOGS(FQDN)", style0) ws.write(0, 1, "AUTHORIZATION REQUESTS", style0) for ind in range(0, len(res)): ws.write(ind + 1, 0, res[ind]) for ind in range(0, len(addresses)): ws.write(ind + 1, 1, addresses[ind]) wb.save('report.xls') f = open('report.xls', 'rb') att = MIMEBase("application", "vnd.ms-excel") att.set_payload(f.read()) encoders.encode_base64(att) me = "KMS Server" you = ["example.com"] msg = MIMEMultipart() msg['Subject'] = "KMS Logs" msg['To'] = "*****@*****.**" msg.add_header('Content-Disposition', 'attachment; filename="report.xls"') msg.attach(att) s = smtplib.SMTP('localhost') s.sendmail(me, you, msg.as_string()) s.quit()
def send_notify_email(body, start_time, title, attendees, event_uid, patching_duartion_in_min): """Function for send Outlook-notifications and save notification to disk""" subject = 'Linux Monthly Patching {month} | RFC {rfc_number} | {project}'.format( month=datetime.datetime.now().strftime("%B %Y"), rfc_number=rfc_number, project=title) start_time_utc=return_utc(start_time) # create calendar cal = icalendar.Calendar() cal.add('prodid', '-//My calendar application//example.com//') cal.add('version', '2.0') cal.add('method', 'REQUEST') # create event event = icalendar.Event() event.add('summary', subject) event.add('dtstart', datetime.datetime.strptime(start_time_utc, "%d-%m-%Y %H:%M")) event.add('dtend', datetime.datetime.strptime(start_time_utc, "%d-%m-%Y %H:%M")+datetime.timedelta(minutes=patching_duartion_in_min)) event.add('dtstamp', datetime.datetime.now().utcnow()) event['uid'] = event_uid event.add('TZOFFSETFROM', datetime.timedelta(hours=3)) event.add('TZOFFSETTO', datetime.timedelta(hours=3)) event.add('TZID', 'Russian Standard Time') event.add('priority', 5) event.add('organizer', settings['organizer']) event.add('status', "confirmed") event.add('category', "Event") event.add('sequence', 1) event.add('X-MICROSOFT-DISALLOW-COUNTER', "TRUE") event.add('X-MICROSOFT-CDO-BUSYSTATUS', 'FREE') for current_attendee in attendees.split(","): event.add('attendee', current_attendee) # create alarm alarm = icalendar.Alarm() alarm.add("action", "DISPLAY") alarm.add('description', "Reminder") alarm.add("TRIGGER;RELATED=START", "-PT15M") alarm.add('X-MICROSOFT-CDO-BUSYSTATUS', 'FREE') event.add_component(alarm) cal.add_component(event) filename = "invite.ics" msg = MIMEMultipart("mixed") msg["Subject"] = subject msg["From"] = settings['e_mail_from'] msg["To"] = attendees msg_for_cancel = copy.deepcopy(msg) cursor_hashes_db.execute('INSERT INTO "HASHES" (HASH,EMAILS) VALUES (?,?)', (str(event_uid), attendees)) connect_hashes_db.commit() msg_a = MIMEMultipart('alternative') msg.attach(msg_a) part_calendar = MIMEMultipart('text', "calendar", method="REQUEST", name=filename) part_calendar.set_type('text/calendar; charset=UTF-8; method=REQUEST; component = VEVENT') part_calendar.add_header('Content-Type', 'text/calendar') part_calendar.add_header('charset', 'UTF-8') part_calendar.add_header('component', 'VEVENT') part_calendar.add_header('method', 'REQUEST') part_calendar.add_header('Content-Description', filename) part_calendar.add_header('Content-ID', 'calendar_message') part_calendar.add_header("Content-class", "urn:content-classes:appointment") part_calendar.add_header("Filename", filename) part_calendar.add_header("Path", filename) part_calendar_before_encode=copy.deepcopy(part_calendar) part_calendar.set_payload(cal.to_ical()) encode_base64(part_calendar) msg_a.attach(MIMEText(body, 'html')) msg_a.attach(part_calendar) recept_list=attendees.split(",") try: s = smtplib.SMTP(settings['smtp_server']) s.sendmail(msg["From"], recept_list, msg.as_string()) s.quit() print("e-mail with '{title}' title has been sent successfully!".format(title=title)) except Exception as e: termcolor.cprint("Error during sending an-email, second try...", color="white", on_color="on_red") try: s = smtplib.SMTP(settings['smtp_server']) print(recept_list) s.sendmail(msg["From"], recept_list, msg.as_string()) s.quit() print("e-mail with '{title}' title has been sent successfully!".format(title=title)) except Exception as e: termcolor.cprint("Can not send outlook-notofocation for this {prj} project to {start_date}".format(start_date=start_time, prj=title), color="white", on_color="on_red") print("Exception: {e}".format(e=str(e))) cal.update({'method' : 'CANCEL'}) event.update({'summary' : "[CANCELLED] " + subject}) event.update({'status': "cancelled"}) msg_for_cancel.replace_header('Subject', "[CANCELLED] " + subject) msg_a_for_cancel = MIMEMultipart('alternative') msg_for_cancel.attach(msg_a_for_cancel) msg_a_for_cancel.attach(MIMEText(body.replace("please, perform this patching", "<font size=12 color='red'>DO NOT DO IT</font>"), 'html')) part_calendar_before_encode.replace_header('Content-Type', 'text/calendar; charset="UTF-8"; method="CANCEL"; component = "VEVENT"; name="invite.ics"; boundary="calendar"') part_calendar_before_encode.replace_header('method', 'CANCEL') part_calendar_before_encode.set_payload(cal.to_ical()) encode_base64(part_calendar_before_encode) msg_a_for_cancel.attach(part_calendar_before_encode) save_notification_to_disk=open("./archive/" + event_uid + ".msg", 'wb') save_notification_to_disk.write(msg_for_cancel.as_bytes()) save_notification_to_disk.close() input("Enter any symbol to proceed...")