Send the contents of a CSV as a table in an email? - python

How can I send the contents of a CSV as a table in an email using Python?
Example file:
name,age,dob
xxx,23,16-12-1990
yyy,15,02-11-1997

you can use smtplib:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# just an example, you format it usng html
html = "<html><body><table><tr><td>name</td><td><age></td><td>dob</td<tr></table></body></html>"
msg1 = MIMEText(html,'html')
msg = MIMEMultipart("test")
msg['Subject'] = "Name of subject"
msg['From'] = "your#email.com"
msg['To'] = "reciver#gmail.com"
msg.attach(msg1)
server = smtplib.SMTP("smpt_server",port) # example smtplib.smtp("smtp.gmail.com,587)
server.starttls()
server.login("your#gmail.com","login_password")
server.sendmail("your#email.com","reciver#gmail.com",msg.as_string())
server.quit()
better you can do:
msg1 = MIMEText(f.open("file.csv").read())
msg.attach(msg1)

Check this link.
Just pass your csv as third argument to server.sendmail() method

Related

Is there a way to send email with a dataframe attachment?

I currently have a script that manipulates a .csv file using pandas. I'm trying to send a MIMEMultipart email with the latest .csv version of the file that has been amended but for some reason, the email recipients keep receiving an older unaltered version of the .csv that I trying to send. I'm trying to make sense of it in my head because the old version of the .csv file is written over before it is sent but the original version of the .csv is sent to the recipients.
Maybe I need to specify a path for smtplib to get the file as opposed to just giving the name of the file. Is there a way to do that or is there another way around my problem? I've already tried to change the name to something else in order for smtplib to be able to differentiate between the old .csv and the new one.
This doesn't work though as the file is placed in the directory but my script says that the new file doesn't exist
This is my current code:
email_user = 'Bot#gmail.com'
email_password = 'Business101'
email_send = ('myemail#gmail.com', 'myfriendsemail#gmail.com')
subject = 'TOP 5 CONTRACTS'
msg = MIMEMultipart()
msg['From'] = email_user
msg['To'] = ",".join(email_send)
msg['Subject'] = subject
body = 'These are the latest contracts for this week!'
msg.attach(MIMEText(body,'plain'))
filename='CC.csv'
attachment =open(filename,'rb')
part = MIMEBase('application','octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition',"attachment; filename= "+filename)
msg.attach(part)
text = msg.as_string()
server = smtplib.SMTP('smtp.gmail.com',587)
server.starttls()
server.login(email_user,email_password)
server.sendmail(email_user,email_send,text)
server.quit()
print("Emailed Recipients")
Might be worth mentioning that this process is an automated one so the script is being run from a Unix Executable file on my mac.
If you can assist, I'd really appreciate it!
This has been the best way to do it, thanks
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from smtplib import SMTP
import smtplib
import sys
import pandas as pd
df_test = pd.read_csv('/Users/emmanuelafoke/Documents/Selenium/CC.csv')
email_user = 'myemailaddress#gmail.com'
email_password = 'mypassword'
recipients = ['theiremailaddress#gmail.com']
emaillist = [elem.strip().split(',') for elem in recipients]
msg = MIMEMultipart()
msg['Subject'] = 'SUBJECT'
msg['From'] = 'myemailaddress#gmail.com'
html = """\
<html>
<head></head>
<body>
{0}
</body>
</html>
""".format(df_test.to_html())
part1 = MIMEText(html, 'html')
msg.attach(part1)
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(email_user,email_password)
server.sendmail(msg['From'], emaillist , msg.as_string())
Thanks for all of your help!
You could actually do this by using the following libraries: email.mime.application, MIMEApplication, email.mime.multipart and email.mime.text. Now, I don't know which client you are using and you might have to do some adjustments to this.
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
SEND_FROM = 'myaddress#client.com' ## Your email address
TOSEND = {'dataframe.csv': export_csv, 'dataframe.xlsx': export_my_excel}
def send_dataframe(send_to, subject, body, df):
multipart = MIMEMultipart()
multipart['From'] = SEND_FROM
multipart['To'] = send_to
multipart['Subject'] = subject
for filename in EXPORTERS:
attachment = MIMEApplication(TOSEND[filename](df)) ### Here is where the df is attached
attachment['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
multipart.attach(attachment)
multipart.attach(MIMEText(body, 'html'))
s = smtplib.SMTP('localhost')
s.sendmail(SEND_FROM, send_to, multipart.as_string())
s.quit()
In send_dataframe() you'll have to put the df you want to attach. This is where TOSEND come in. As you see, there is a function called export_my_excel. You can create it as
import io
import pandas as pd
def export_my_excel(df):
with io.BytesIO() as buffer:
writer = pd.ExcelWriter(buffer)
df.to_excel(writer)
writer.save()
return buffer.getvalue()

How do I attach separate PDF's to contact list email addresses using Python?

I have written a script that sends individual emails to all contacts in an Excel table. The table looks like this:
Names Emails PDF
Name1 Email1#email.com PDF1.pdf
Name2 Email2#email.com PDF2.pdf
The code I have so far is as follows:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from string import Template
import pandas as pd
e = pd.read_excel("Contacts.xlsx")
emails = e['Email'].values
PDF = e['PDF'].values
print(emails, PDF)
server = smtplib.SMTP(host='smtp.outlook.com', port=587)
server.starttls()
server.login('sender_email','sender_password')
msg = ("""
Hi there
Test message
Thankyou
""")
subject = "Send emails with attachment"
body = "Subject: {}\n\n{}".format(subject,msg)
for emails in emails:
server.sendmail('sender_email',emails,body)
print("Emails sent successfully")
server.quit()
Question: How can I look up the correct attachment (column 3) for each e-mail address (column 2) and attach it to the email using Python?
I made a little changes , and make you sure the pdf field has the pdf path
Edit:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from string import Template
import pandas as pd
#e = pd.read_csv("Contacts.csv")
e = pd.read_excel("Contacts.xlsx")
server = smtplib.SMTP(host='smtp.outlook.com', port=587)
server.starttls()
server.login('yourmail#mail.com','yourpass')
body = ("""
Hi there
Test message
Thankyou
""")
subject = "Send emails with attachment"
fromaddr='yourmail#mail.com'
#body = "Subject: {}\n\n{}".format(subject,msg)
#Emails,PDF
for index, row in e.iterrows():
print (row["Emails"]+row["PDF"])
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
filename = row["PDF"]
toaddr = row["Emails"]
attachment = open(row["PDF"], "rb")
part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)
msg.attach(part)
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
#server.sendmail('sender_email',emails,body)
print("Emails sent successfully")
server.quit()

python MIME attaching multiple attachments to a multipart message

I am trying to attach multiple attachments to a email.mime.multipart object:
from smtplib import SMTP
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
message = MIMEMultipart('alternative')
message['Subject'] = 'test'
for i in range(10):
title="<h2>{}</h2>".format(i)
message.attach(MIMEText(title,"html",_charset="utf-8"))
Here I can check that the payload contains the 10 elements:
message.get_payload()
I can see the list of 10 elements, which seems correct.
However when I send the email with the following code:
MAIL_HOST = 'smtp.gmail.com:587'
MAIL_USER = 'xxx#gmail.com'
MAIL_PASSWORD = 'xxx'
MAIL_REPICIENTS = ['xxx#gmail.com']
smtp = SMTP(MAIL_HOST)
smtp.ehlo()
smtp.starttls()
smtp.login(MAIL_USER, MAIL_PASSWORD)
smtp.sendmail(MAIL_USER, MAIL_REPICIENTS, message.as_string())
smtp.close()
The email contains only the last element of the list.
Can anyone help me with that?
That’s because you are attaching 10 different messages. Why you want is to attach one message. Change your code to this:
from smtplib import SMTP
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
message = MIMEMultipart('alternative')
message['Subject'] = 'test'
html = ''
for i in range(10):
title="<h2>{}</h2>".format(i)
html += title
message.attach(MIMEText(html,"html",_charset="utf-8"))

Unable to send html file content as email body in python

I have a html file whose contents I want to send in the email body using python. Below is the python script:
import smtplib,email,email.encoders,email.mime.text,email.mime.base
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email import encoders
from email.message import Message
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
import codecs
msg = MIMEMultipart()
# me == my email address
# you == recipient's email address
me = "a#b.com"
you = "b#a.com"
# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('mixed')
msg['Subject'] = "Automation Testing"
msg['From'] = me
msg['To'] = you
# Create the body of the message (a plain-text and an HTML version).
f = codecs.open('/Users/test.htm')
html = f.read()
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)
composed = msg.as_string()
fp = open('msgtest.txt', 'w')
fp.write(composed)
# Credentials (if needed)
# The actual mail send
server = smtplib.SMTP('smtp.a.com', 25)
server.starttls()
server.sendmail(me, you, composed)
server.quit()
fp.close()
But, it is sending only an empty email with no html content in the body. Please tell me how to fix this.

Email module in python 3

So I'm following a tutorial to send email in python, the problem is that it was written for python 2 not python 3(which is what I have). So here's what I'm trying to get an answer what is the module for email in python 3? the specific module I'm trying to get is is:
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMETex
I also have a feelling that when I get down to this module there will be an error (haven't got there yet because of
the module above giving error
import smtp
Here is the script:
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMETex
fromaddr = ("XXXXX#mchsi.com")
toaddr = ("XXXX#mchsi.com")
msg = MIMEMultipart
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = ("test")
body = ("This is a test sending email through python")
msg.attach(MIMEText(body, ('plain')))
import smptlib
server = smptlib.SMPT('mail.mchsi.com, 456')
server.login("XXXXX#mchsi.com", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
text = msg.as_string()
sender.sendmail(fromaddr, toaddr, text)
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
By the way here are some mistakes in your code:
fromaddr = "XXXXX#mchsi.com" # redundant parentheses
toaddr = "XXXX#mchsi.com" # redundant parentheses
msg = MIMEMultipart() # not redundant this time :)
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "test" # redundant parentheses
body = "This is a test sending email through python" # redundant parentheses
msg.attach(MIMEText(body, 'plain')) # redundant parentheses
import smtplib # SMTP! NOT SMPT!!
server = smtplib.SMTP('mail.mchsi.com', 456) # `port` is an integer
server.login("XXXXX#mchsi.com", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX") # on most SMTP servers you should remove domain name(`#mchsi.com`) here
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text) # it's not `sender`

Categories