Sending data frame as table inside email body python? - python

I have a csv file that i need to send as a dataframe inside email body.
However in the output of my email i am unable to see the columns of the csv file and instead it just makes the first row of the csv file as columns.
** Here is my Code:**
import pandas as pd
import csv
from tabulate import tabulate
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
me = 'myemailaddress#gmail.com'
password = 'password'
server = 'smtp.gmail.com:587'
you = 'myemailaddress#gmail.com'
text = """
Hello, Friend.
Here is your data:
{table}
Regards,
Me"""
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>
{table}
<p>Regards,</p>
<p>Me</p>
</body></html>
"""
# with open('input.csv') as input_file:
# reader = csv.reader(input_file)
# data = list(reader)
data = pd.read_csv("MySampleFile.csv")
text = text.format(table=tabulate(data, headers="firstrow", tablefmt="grid"))
html = html.format(table=tabulate(data, headers="firstrow", tablefmt="html"))
message = MIMEMultipart(
"alternative", None, [MIMEText(text), MIMEText(html,'html')])
message['Subject'] = "First Attempt"
message['From'] = me
message['To'] = you
server = smtplib.SMTP(server)
server.ehlo()
server.starttls()
server.login(me, password)
server.sendmail(me, you, message.as_string())
server.quit()

It seems all i had to do was to extract the respective columns inside my csv file into a separate list that could be passed into tabulate method's headers parameter.
Here is the complete solution
import pandas as pd
import csv
from tabulate import tabulate
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
me = 'myemailaddress#gmail.com'
password = 'password'
server = 'smtp.gmail.com:587'
you = 'myemailaddress#gmail.com'
text = """
Hello, Friend.
Here is your data:
{table}
Regards,
Me"""
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>
{table}
<p>Regards,</p>
<p>Me</p>
</body></html>
"""
# with open('input.csv') as input_file:
# reader = csv.reader(input_file)
# data = list(reader)
df = pd.read_csv("MySampleFile.csv")
col_list = list(df.columns.values)
data = df
# above line took every col inside csv as list
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'] = "First Attempt"
message['From'] = me
message['To'] = you
server = smtplib.SMTP(server)
server.ehlo()
server.starttls()
server.login(me, password)
server.sendmail(me, you, message.as_string())
server.quit()

Related

How to send prettytable through email using python

I have created a prettytable in python and I have to send the output of prettytable through email
env = "Dev"
cost = 25.3698
line = [env, "${:,.2f}".format(cost)]
totalcostofenv = PrettyTable(['Environment', 'Cost'])
totalcostofenv.add_row(line)
print(totalcostofenv)
Below attached is the output :
Table Output
Can anyone help me to solve this?
This was my question asked and I found an solution , Below displayed is my code:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import os
from prettytable import PrettyTable
env = "Dev"
cost = 25.3698
line = [env, "${:,.2f}".format(cost)]
totalcostofenv = PrettyTable(['Environment', 'Cost'])
totalcostofenv.add_row(line)
print(totalcostofenv)
print(totalcostofenv.get_html_string())
def trigger_email():
my_message = totalcostofenv.get_html_string()
text = "Hi!"
html = """\
<html>
<head>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 5px;
text-align: left;
}
</style>
</head>
<body>
<p>Cost Usage of Plantd Environemnts<br>
%s
</p>
</body>
</html>
""" % (my_message)
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
msg = MIMEMultipart()
from_addr = "from-address"
mail_password = os.environ.get('gmail-pass')
to_addr = "to-address"
msg.attach(part1)
msg.attach(part2)
try:
smtp = smtplib.SMTP('smtp.gmail.com',587)
smtp.starttls()
smtp.login(from_addr , mail_password)
smtp.sendmail(from_addr , to_addr , msg.as_string())
print('Mail sent')
except:
print('Mail not sent')
trigger_email()
You can use MJML templating like this
<mjml>
<mj-head>
<mj-title>Set the title, usually for accessibility tools</mj-title>
<mj-preview>Set inbox preview text here, otherwise it might be something nonsensical</mj-preview>
<mj-attributes>
<mj-all font-family="Helvetica, Arial, sans-serif"></mj-all>
<mj-text font-weight="400" font-size="16px" color="#4A4A4A" line-height="24px" />
<mj-section padding="0px"></mj-section>
</mj-attributes>
</mj-head>
<mj-body>
{{table}}
</mj-body>
</mjml>
Code:
import pystache
# read in the email template, remember to use the compiled HTML version!
email_template = (Path() / 'email_template.html').read_text()
# Logic
env = "Dev"
cost = 25.3698
line = [env, "${:,.2f}".format(cost)]
totalcostofenv = PrettyTable(['Environment', 'Cost'])
totalcostofenv.add_row(line)
# Pass in values for the template using a dictionary
template_params = {'table': totalcostofenv }
# Attach the message to the Multipart Email
final_email_html = pystache.render(email_template, template_params)
message.attach(MIMEText(final_email_html), 'html')
"""Continue with sending..."""

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")

Sending two Pandas dataframes side-by-side using HTML in email

I'm trying to send some summary on my shares portfolio creation via email. I'm using Python + Pandas for the calculations and email.mime module to send html via email.
I am using Pandas to_html method and email.mime module to include the html in the email:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import numpy as np
import pandas as pd
import pickle
from utils import mail
def send_fancy_mail(subject, text_message, html_message):
msg = MIMEMultipart('alternative')
msg['Subject'] = subject
msg['From'] = 'mymail#domain.com'
msg['To'] = settings.MAIL_RECIPIENTS
# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text_message, 'plain')
part2 = MIMEText(html_message, 'html')
msg.attach(part1)
msg.attach(part2)
# Send the message via our own SMTP server.
s = smtplib.SMTP_SSL(settings.SMTP_HOST)
s.login(settings.SMTP_USER, settings.SMTP_PASSWORD)
s.send_message(msg)
s.quit()
fake_or_load = 'fake'
if fake_or_load == 'fake':
n_signals = 20
symbols = np.round(1000*np.random.rand(n_signals)).astype(int)
direction = ["Buy" for i in range(n_signals//2)]
direction.extend(["Sell" for i in range(n_signals//2)])
quantity = np.round(10000*np.random.rand(n_signals)).astype(int)
portfolio = pd.DataFrame({'symbols': symbols, 'direction': direction, 'quantity': quantity})
elif fake_or_load == 'load':
with open('c:\\\\temp\\signals_list', 'rb') as fp:
signals = pickle.load(fp)
portfolio = pd.DataFrame(signals)
portfolio.rename(index=str, inplace=True, columns={0: "symbol", 1: "direction", 2: "quantity"})
shares_to_buy = portfolio[portfolio['direction'] == 'Buy'].copy()
shares_to_buy.sort_values(by='quantity', inplace=True, ascending=False)
shares_to_sell = portfolio[portfolio['direction'] == 'Sell'].copy()
shares_to_sell.sort_values(by='quantity', inplace=True, ascending=False)
# The basic way to convert portfolio to html:
html_to_buy = shares_to_buy.to_html(index=False, header=True, col_space=20, justify='center')
html_to_sell = shares_to_sell.to_html(index=False, header=True, col_space=20, justify='center')
mail_body = "Test Message"
css = """
.div {
flex-direction: row;
}
"""
html_body = """
<html>
<head>
<style>{}</style>
</head>
<body>
<div>{}</div>
<div>{}</div>
</body>
</html>
""".format(css, html_to_buy, html_to_sell)
mail.send_fancy_mail("Test Mail", mail_body, html_body)
I would like to get two columns side-by-side in the email body, preferably able to regulate the column width as well. Is it possible to make the tables responsive?
If you want to create two columns, replace the two divs with the below table. Div's dont have the same support as tables on all email clients.
<table style="width:100%">
<tr>
<td>column 1</td>
<td>column 2</td>
</tr>
</table>

Removing the nan in python in an email

I have created an auto email using python. Right now,I am trying to remove the nan details in my email as user don't want nan to be in the email. I'm not sure how to do it. Can anyone help me to add or edit the code below
This is my code :
import pandas as pd
import csv
from tabulate import tabulate
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
user= 'mahirah.abd.wahab#ericsson.com'
password = '--------'
server = 'smtp.office365.com:587'
recipient = 'nur.suraya.shazwani.kamaru.zaman#ericsson.com,mahirah.abd.wahab#ericsson.com'
text = """
This is a test for the data to be sent
{table}
Regards,
Me"""
html = """
<html>
<head>
<style>
This is a test auto generated email
table, th, td {{ border: 1px solid black; border-collapse: collapse; }}
th, td {{ padding: 5px; }}
</style>
</head>
<body>
{table}
<p></p>
<p></p>
</body></html>
"""
# with open('input.csv') as input_file:
# reader = csv.reader(input_file)
# data = list(reader)
df = pd.read_csv('testcsv2.csv')
col_list = list(df.columns.values)
to_drop = []
for i in range(len(df)):
if df['HOSS1 REVIEWED DATE'][i] == 'nan':
to_drop.append(i)
df.drop(df.index[to_drop])
df.reset_index(drop=True, inplace=True)
data = df
# above line took every col inside csv as list
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'] = "Rental PR – Pending HOS Approval"
message['From'] = user
message['To'] = recipient
server = smtplib.SMTP(server)
server.ehlo()
server.starttls()
server.login(user, password)
server.sendmail(user, recipient, message.as_string())
server.quit()
I also tried using this one line code , but still doesn't work :
df = pd.dropna(subset=['HOSS1 REVIEWED DATE'])
THis is my output
Appreciate if anyone can help.
try this...
to_drop = []
for i in range(len(df)):
if df['HOSS1 REVIEWED DATE'][i] == 'nan':
to_drop.append(i)
df.drop(df.index[to_drop], inplace=True)
df.reset_index(drop=True, inplace=True)

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.

Categories

Resources