read email response from outlook using email lib python - python

Hello currently I am using IMAPLIB and EMAIL library of python for reading and get then content sends of different emails, but when I received an email response from outlook, I can not get the content from the email am receive a string like this:
'PGh0bWw+DQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0i\r\ndGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyIgc3R5bGU9\r\nImRpc3BsYXk6bm9uZTsiPiBQIHttYXJnaW4tdG.......'
this is the code to get the emails, I am using to authenticate IMAPLIB, the email server was built with this repo: https://github.com/modoboa/modoboa
mail.select("inbox")
result, data = mail.uid('search', None, 'UNSEEN')
inbox_item_list = data[0].split()
list_emails = []
root_dict = {}
campaigns = []
for item in inbox_item_list:
result2, email_data = mail.uid('fetch', item, '(RFC2045)')
raw_email = email_data[0][1].decode('utf-8')
email_message = email.message_from_string(raw_email)
to_= email_message["Delivered-To"]
from_= email_message['From']
subject_= email_message['Subject']
counter = 1
for part in email_message.walk():
if part.get_content_maintype() == "multipart":
continue
filename = part.get_filename()
if not filename:
ext = 'html'
filename = 'msg-part-%08d%s' %(counter, ext)
counter += 1
content_type = part.get_content_type()
if "plain" in content_type:
pass
elif "html" in content_type:
emails = {}
html_ = part.get_payload()
soup_ = BeautifulSoup(html_, "html.parser")
text = soup_.get_text()
text is the variable the saves the content of the email, works with Gmail but currently doesn't works with the email response of outlook.

If you want just work with mailbox/emails (not read RFC and parse data), try:
https://github.com/ikvk/imap_tools:
from imap_tools import MailBox, A
with MailBox('imap.mail.com').login('test#mail.com', 'pwd', 'INBOX') as mailbox:
for msg in mailbox.fetch(A(all=True)):
body = msg.text or msg.html
*Regards, author of imap_tools

So it turns out it was just base64 encoded. Here's the decoded text:
b'<html>\r\n<head>\r\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r\n<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>\r\n</head>\r\n<body dir="ltr">\r\n<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">\r\nCount on me<br>\r\n</div>\r\n<div id="appendonsend"></div>\r\n<hr style="display:inline-block;width:98%" tabindex="-1">\r\n<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>De:</b> Giraluna Gomez <2344#holbertonschool.com><br>\r\n<b>Enviado:</b> lunes, 24 de mayo de 2021 4:13 p. m.<br>\r\n<b>Para:</b> Giraluna Gomez <lunagolo#hotmail.com><br>\r\n<b>Cc:</b> david+2022#zeroclickmail.com <david+2022#zeroclickmail.com><br>\r\n<b>Asunto:</b> Luna golo.Test 2 from email merge</font>\r\n<div> </div>\r\n</div>\r\n<div>\r\n<div dir="ltr">Test 2 to email merge. </div>\r\n<div hspace="streak-pt-mark" style="max-height:1px"><img alt="" style="width:0px; max-height:0px; overflow:hidden" src="https://mailfoogae.appspot.com/t?sender=aMjM0NEBob2xiZXJ0b25zY2hvb2wuY29t&type=zerocontent&guid=9189324e-7d1c-4590-b502-8179902f97de"><font color="#ffffff" size="1">\xe1\x90\xa7</font></div>\r\n</div>\r\n</body>\r\n</html>\r\n'
And here's what I used to decode it:
from base64 import b64decode
print(b64decode("PGh0bWw+DQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyIgc3R5bGU9ImRpc3BsYXk6bm9uZTsiPiBQIHttYXJnaW4tdG9wOjA7bWFyZ2luLWJvdHRvbTowO30gPC9zdHlsZT4NCjwvaGVhZD4NCjxib2R5IGRpcj0ibHRyIj4NCjxkaXYgc3R5bGU9ImZvbnQtZmFtaWx5OiBDYWxpYnJpLCBIZWx2ZXRpY2EsIHNhbnMtc2VyaWY7IGZvbnQtc2l6ZTogMTJwdDsgY29sb3I6IHJnYigwLCAwLCAwKTsiPg0KQ291bnQgb24gbWU8YnI+DQo8L2Rpdj4NCjxkaXYgaWQ9ImFwcGVuZG9uc2VuZCI+PC9kaXY+DQo8aHIgc3R5bGU9ImRpc3BsYXk6aW5saW5lLWJsb2NrO3dpZHRoOjk4JSIgdGFiaW5kZXg9Ii0xIj4NCjxkaXYgaWQ9ImRpdlJwbHlGd2RNc2ciIGRpcj0ibHRyIj48Zm9udCBmYWNlPSJDYWxpYnJpLCBzYW5zLXNlcmlmIiBzdHlsZT0iZm9udC1zaXplOjExcHQiIGNvbG9yPSIjMDAwMDAwIj48Yj5EZTo8L2I+IEdpcmFsdW5hIEdvbWV6ICZsdDsyMzQ0QGhvbGJlcnRvbnNjaG9vbC5jb20mZ3Q7PGJyPg0KPGI+RW52aWFkbzo8L2I+IGx1bmVzLCAyNCBkZSBtYXlvIGRlIDIwMjEgNDoxMyBwLiBtLjxicj4NCjxiPlBhcmE6PC9iPiBHaXJhbHVuYSBHb21leiAmbHQ7bHVuYWdvbG9AaG90bWFpbC5jb20mZ3Q7PGJyPg0KPGI+Q2M6PC9iPiBkYXZpZCsyMDIyQHplcm9jbGlja21haWwuY29tICZsdDtkYXZpZCsyMDIyQHplcm9jbGlja21haWwuY29tJmd0Ozxicj4NCjxiPkFzdW50bzo8L2I+IEx1bmEgZ29sby5UZXN0IDIgZnJvbSBlbWFpbCBtZXJnZTwvZm9udD4NCjxkaXY+Jm5ic3A7PC9kaXY+DQo8L2Rpdj4NCjxkaXY+DQo8ZGl2IGRpcj0ibHRyIj5UZXN0IDIgdG8gZW1haWwgbWVyZ2UuJm5ic3A7PC9kaXY+DQo8ZGl2IGhzcGFjZT0ic3RyZWFrLXB0LW1hcmsiIHN0eWxlPSJtYXgtaGVpZ2h0OjFweCI+PGltZyBhbHQ9IiIgc3R5bGU9IndpZHRoOjBweDsgbWF4LWhlaWdodDowcHg7IG92ZXJmbG93OmhpZGRlbiIgc3JjPSJodHRwczovL21haWxmb29nYWUuYXBwc3BvdC5jb20vdD9zZW5kZXI9YU1qTTBORUJvYjJ4aVpYSjBiMjV6WTJodmIyd3VZMjl0JmFtcDt0eXBlPXplcm9jb250ZW50JmFtcDtndWlkPTkxODkzMjRlLTdkMWMtNDU5MC1iNTAyLTgxNzk5MDJmOTdkZSI+PGZvbnQgY29sb3I9IiNmZmZmZmYiIHNpemU9IjEiPuGQpzwvZm9udD48L2Rpdj4NCjwvZGl2Pg0KPC9ib2R5Pg0KPC9odG1sPg0K"))

Related

Sending a pandas Dataframe using smtplib

I've seen a lot of threads here about this topic, however, none regarding this specific question.
I am sending a email with a pandas dataframe (df) as an html using pandas built in df.to_html() method. The email sends successfully. However, the df is displayed in the email as html, not in the desired table format. Can anyone offer assistance on how to ensure the df is displayed as a table, not in html in the email? The code is below:
import requests
import pandas as pd
import smtplib
MY_LAT =
MY_LNG =
API_KEY = ""
parameters = {
"lat": MY_LAT,
'lon': MY_LNG,
'exclude': "",
"appid": API_KEY
}
df = pd.read_csv("OWM.csv")
response = requests.get("https://api.openweathermap.org/data/2.5/onecall", params=parameters)
response.raise_for_status()
data = response.json()
consolidated_weather_12hour = []
for i in range(0, 12):
consolidated_weather_12hour.append((data['hourly'][i]['weather'][0]['id']))
hour7_forecast = []
for hours in consolidated_weather_12hour:
weather_id = df[df.weather_id == hours]
weather_description = weather_id['description']
for desc in weather_description.iteritems():
hour7_forecast.append(desc[1])
times = ['7AM', '8AM', '9AM', '10AM', '11AM', '12PM', '1PM', '2PM', '3PM', '4PM', '5PM', '6PM']
col_header = ["Description of Expected Weather"]
weather_df = pd.DataFrame(data=hour7_forecast, index=times, columns=col_header)
my_email = ""
password = ""
html_df = weather_df.to_html()
with smtplib.SMTP("smtp.gmail.com", 587) as connection:
connection.starttls() # Makes connection secure
connection.login(user=my_email, password=password)
connection.sendmail(from_addr=my_email, to_addrs="",
msg=f"Subject: 12 Hour Forecast Sterp"
"""\
<html>
<head></head>"
<body>
{0}
<body>
</html>
""".format(html_df))
just use df.to_html() to convert it into an html table that you can include in your html email
then when you send the mail you must set the mimetype to html
smtp = smtplib.SMTP("...")
msg = MIMEMultipart('alternative')
msg['Subject'] = subject_line
msg['From'] = from_addr
msg['To'] = ','.join(to_addrs)
# Create the body of the message (a plain-text and an HTML version).
part1 = MIMEText(plaintext, 'plain')
part2 = MIMEText(html, 'html')
smtp.sendmail(from_addr, to_addrs, msg.as_string())
you can use the library html2text to convert your html to markdown for clients that do not support html content (not many these days) if you do not feel like writing the plaintext on your own
as an aside... using jinja when you are working with html tends to simplify things...

Send Table contents from CSV file in Outlook Mail Body using Python

i programmed a code to send a outlook mail , which should contain the contents of CSV file as it's body , Mail part is working fine . But the table appears to be distorted .
[![MailBody][1]][1]
So here is there anyway to arrange this . and make it pretty .
and here is my code :
def sendMailt():
print("*** SENDING MAIL ****")
email_user = 'ABC#domain.com'
email_send = 'DCF#domain.com'
subject = ''
msg = MIMEMultipart()
msg['From'] = email_user
msg['To'] = email_send
msg['Subject'] = subject
body = 'Hi Team , Please Open This attachment for Folderstat Report,'
msg.attach(MIMEText(body, 'plain'))
text = """
Hello, Friend.
Here is your data:
{table}
Regards,
Me"""
with open(filtered_CSV) as input_file:
reader = csv.reader(input_file)
data = list(reader)
text = text.format(table=tabulate(data, headers=['Unnamed: 0','id','path','name','extension','size','FolderSize in GB','LastAccessTime','LastModifiedTime','LastCreationTime','folder','Total Number of files','Absolute File Count','depth','parent','uid','Oldest File Timestamp','Recent File Timestamp','Folder Modified Timestamp','Status','md5]'] ,tablefmt='orgtbl'))
server = smtplib.SMTP('domain')
sender = 'ABC#domain.com'
reciever = ['DCF#domain.com']
server.sendmail(sender, reciever, text)
server.quit()
print("Mail SEND")
and also when i receive mail , am not able to see subject or receivers ID
[1]: https://i.stack.imgur.com/y5Gxy.png
if you Use html in tablefmt you can get the data in decent format
from tabulate import tabulate
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
text = """
Hello, Friend.
Here is your data:
{table}
Regards,
Me"""
with open(filtered_CSV) as input_file:
reader = csv.reader(input_file)
data = list(reader)
html = text.format(table=tabulate(data, headers="firstrow", tablefmt="html")
# for html design ( you can add whatever style you want)
html = html.replace('<table>', """<table border=1 style="
border-color:grey;
font-family: Helvetica, Arial;
font-size: 15px;
padding: 5px;">""")
server = smtplib.SMTP('domain')
msg = MIMEMultipart("alternative", None, [MIMEText(html, 'html')])
msg['From'] = from address
msg['To'] = to address
msg['Subject'] = "your subject"
server.sendmail(msg['From'], msg['To'], msg.as_string())
server.quit()
print("Mail SEND")

Python-Imap: retrieve MIMEMultipart's mails and get the body with HTML tags

Here my situation: I am currently retrieving all my outlook (2016) mails from my Inbox, and more specificcaly I am retrieving a table:
¦ Product ¦ Currency ¦ Tenor (months) ¦ Code 1 ¦
¦ MyItem ¦ USD ¦ 12 ¦ AAA01 ¦
My goal is to catch the body of each of them to then store them in a MsSQL Server.
I had difficulties to understand the 'Multipart' term, now with couples of (long) hours it's more clear.
So for now my process is:
going through all my mails in the Inbox
Creating a list of mails' Id
For all the Id I have in this list, I am checking if the mail is a Multipart one.
If Yes -> I retrieve the body with body = part.get_payload(decode=True)
If No -> I retrieve the body with body = b.get_payload(decode=True)
So in both case I use the get_payload(decode=True).
When my mail is "Multipart", it appears in my debugger as a simple text:
Product
Currency
Tenor (months)
Code 1
MyItem
USD
12
AAA01
When my mail isn't a Multipart, it appears in my debugger with HTML tags:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>
<body>
<table>
<tr>
<td><b>Product</b></td>
<td><b>Currency</b></td>
<td><b>Tenor (months)</b></td>
<td><b>Code 1</b></td>
</tr>
<tr>
<td>MyItem</td>
<td>USD</td>
<td>12</td>
<td>AAA01</td>
</tr>
</table>
</body>
</html>
How can I retrieve body of Multipart's mails with HTML tag also and not as simple text ?
I need HTML tag to identify each header and its corresponding value to use Beautiful Soup and Insert all those data into my MSSQL Server ?
Thanks for your help to let me understand better MIMEMultipart !
Here my (messy) python code:
#app.route('/ps_rfq_imap', methods=['GET', 'POST'])
def ps_rfq_imap():
#Connection to IMAP/OULTLOOK
url = 'outlook.mycompayny.com'
mailbox = imaplib.IMAP4_SSL(url,993)
user,password = ('mymail#mycompany.com','mypassword')
mailbox.login(user,password)
mailbox.list() # Lists all labels in GMail
mailbox.select('INBOX') # Connected to inbox.
#giving list id, not outlook ones, but uid ones
typ, data = mailbox.search(None,'ALL')
#Get all the uid outlook of all emails
#typ, data = mailbox.uid('search', None,'ALL')
ids = data[0]
id_list = ids.split()
print id_list
#get the most recent email id
latest_email_id = int( id_list[-1] )
for i in range( latest_email_id, latest_email_id-(latest_email_id), -1 ):
print 'EMAIL ID:'
print i
typ, data = mailbox.fetch( i, '(RFC822)')
msg=str(email.message_from_string(data[0][1]))
b = email.message_from_string(msg)
body = ""
if b.is_multipart():
email_from = b['from']
email_subject = b['subject']
print 'FROM:'
print email_from
print 'SUBJECT'
print email_subject
for part in b.walk():
ctype = part.get_content_type()
cdispo = str(part.get('Content-Disposition'))
# skip any text/plain (txt) attachments
if ctype == 'text/plain' and 'attachment' not in cdispo:
body = part.get_payload(decode=True) # decode
print '******************************* MULTIPART body content***********************************'
print body
break
elif ctype == 'text/html':
print 'HTML PART'
continue
# not multipart - i.e. plain text, no attachments, keeping fingers crossed
else:
email_from = b['from']
email_subject = b['subject']
print 'FROM:'
print email_from
print 'SUBJECT'
print email_subject
body = b.get_payload(decode=True)
print '******************************* SIMMMMMMPPPPLLLLEEEE***********************************'
print body
return body
EDIT: here myupdated code to only catch the HTML part of my email, in case it can help somebody:
typ, data = mailbox.fetch( i, '(RFC822)')
msg=str(email.message_from_string(data[0][1]))
b = email.message_from_string(msg)
body = ""
if b.is_multipart():
email_from = b['from']
email_subject = b['subject']
for part in b.walk():
ctype = part.get_content_type()
cdispo = str(part.get('Content-Disposition'))
# skip any text/plain (txt) attachments
if ctype == 'text/plain' and 'attachment' not in cdispo:
continue
elif ctype == 'text/html':
print 'HTML PART'
body = part.get_payload(decode=True) # decode
soup = BeautifulSoup(body)
metaTag = soup.find_all('meta')
if metaTag is not None:
print 'WE HAVE FOUND THE BODY******************** Time to process it with BS for getting the value of the table'
soup = BeautifulSoup(body, "html.parser")
tables = soup.findChildren('table')
continue
# not multipart - i.e. plain text, no attachments, keeping fingers crossed
else:
continue
Best Regards,

Adding colors to individual columns of a dataframe when sending dataframe as table in an email?

Color individual columns while sending data frame over email
I have a data frame that i am emailing as a table with an attachment and the code works nice and dandy, but i now require to color some specific columns with a different color, i tried changing the html part of rendering table and also tried the Style functionality of pandas data frame but to no avail. Here is my code:
from tabulate import tabulate
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
import pandas as pd
from email.mime.base import MIMEBase
from email import encoders
me = 'myemail#gmail'
password = 'mypassword'
server = 'smtp.gmail.com:587'
you = 'myreceipient#gmail.com'
text = """
Hello, Friend.
Here is your data:
{table}
Regards,
Me"""
# here i tried to directly apply a color style into the table via <p> tag
html = """
<html>
<head>
<style>
table, th, td {{ border: 1px solid black; border-collapse: collapse; }}
th, td {{ padding: 5px; }}
</style>
</head>
<body><p>Hello, Friend This data is from a data frame.</p>
<p>Here is your data:</p>
<p style = "color: yellow;" >
{table}
</p>
<p>Regards,</p>
<p>Me</p>
</body></html>
"""
df = pd.read_csv("MyFile.csv")
col_list = list(df.columns.values)
# here again a tried to setstyle directly on the pandas dataframe.
df.style.set_properties(**{'background-color': 'white',
'color': 'yellow',
'border-color': 'black'})
data = df
text = text.format(table=tabulate(data, headers=col_list, tablefmt="grid"))
html = html.format(table=tabulate(data, headers=col_list, tablefmt="html"))
message = MIMEMultipart(
"alternative", None, [MIMEText(text), MIMEText(html,'html')])
message['Subject'] = "sending early morning "
message['From'] = me
message['To'] = you
import glob, os
os.chdir("D://FolderLogFileUploads//")
file_list = []
filename = "File1.csv"
for file in glob.glob("*.csv"):
file_list.append(file)
if filename in file_list:
target_file = filename
attachment = open(target_file, 'rb')
part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= "+filename)
message.attach(part)
server = smtplib.SMTP(server)
server.ehlo()
server.starttls()
server.login(me, password)
server.sendmail(me, you, message.as_string())
print("message with attachment sent successfully")
server.quit()
PS:my col list is ["name", "city", "e_id", "pay_band"] and i want my col: "e_id" and "city" to be of a specific color say yellow.

Include Excel table in the body of an email in Python

Using Python, I am trying to send an email with an Excel table inside the body of an email. I would like to maintain all the conditional formatting from the Excel file. I can send the Excel file as an attachment easy, but I would like to also put the table inside the body of the email. I will convert it to an HTML table if I need to, but I need to know how to include the HTML table into body of the email then. Below attaches the file as an email, but I haven't been able to figure out how to put the table inside of the email. How can I do this?
msg = MIMEMultipart()
msg['Subject'] = 'Subject goes here'
msg.attach(MIMEText('Text goes here'))
part = MIMEBase('application', "octet-stream")
f = 'file_name.xlsx'
part.set_payload(open(f, "rb").read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % f)
msg.attach(part)
Thanks for your help!
The easiest way to do is use pandas. Something like:
import pandas as pd
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def generate_html():
read_file = pd.read_csv("example.csv")
html_file = read_file.to_html()
sendEmail(html_file)
def sendEmail(html_file):
msg = MIMEMultipart('alternative')
msg['Subject'] = "Hello"
msg['From'] = EmailFrom
msg['To'] = EmailTo
part = MIMEText(html_file, 'html')
msg.attach(part)
s = smtplib.SMTP("smtp.gmail.com")
s.sendmail(EmailFrom, EmailTo, msg.as_string())
s.quit()
You might want to look into openpyxl https://openpyxl.readthedocs.io/en/default/
Something like this might solve your problem:
import openpyxl
from openpyxl import load_workbook
workbook = load_workbook(f)
worksheet = workbook.get_active_sheet()
html_data = """
<html>
<head>
<title>
XLSX to HTML demo
<title>
<head>
<body>
<h3>
XLSX to HTML demo
<h3>
<table>
"""
ws_range = worksheet.range('A1:H13')
for row in ws_range:
html_data += "<tr>
for cell in row:
if cell.value is None:
html_data += "<td> + ' ' + "<td>
else:
html_data += "<td> + str(cell.value) + "<td>
html_data += "<tr>
html_data += "</table></body></html>
msg.attach(MIMEText(html_data))
with open(f, "rb") as fil:
part = MIMEApplication(
fil.read(),
Name=basename(f)
)
part['Content-Disposition'] = 'attachment; filename="{0}"'.format(basename(f))
msg.attach(part)
Inspired by https://jugad2.blogspot.ch/2013/11/publish-microsoft-excel-xlsx-data-to.html?m=1

Categories

Resources