简体   繁体   中英

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!

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

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM