Python Sending Emails with Attachments
The post shares the knowledge on how to build a python script to send email with attachment. Keywords: SMTP, DataFrame, StringIO
In my previous post, I shared the knowledge of how to configure a Gmail account and use Python’s SMTP module to build an email server class. This technique comes in handy when you need to constantly monitor the health of your application while you don’t necessarily want to build a full-fledge dashboard. This post takes it further to illustrate how to send email with an attachment. The approach is not as trivial as I originally thought. I had to do some research on how to attach the data (i.e. Pandas DataFrame) without needing to save it to the working directory. This trick is useful when you are working in the cloud environment where you don’t necessarily have the save option.
- Configure the email service
You can refer to my previous post Python Gmail Setup Guide and Code Example for accessing email with less secure app.
2. Save a dataframe to csv and attach to the email
To accomplish this task, you need the following modules
from email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.mime.application import MIMEApplicationfrom io import StringIO
To attach a dataframe as a csv, you need to use the StringIO module. Initalize a textString instance and save a dataframe with the csv format to it. Basically, the testString instance is acting like a memory buffer, which allows you to save the data to the memroy instead of the hard dish.
textStream = StringIO()
df.to_csv(textStream,index=False)
Then you need to extract the value from the memory and attach to the message object.
msg = MIMEMultipart()
msg.attach(MIMEApplication(textStream.getvalue(), Name=filename))
Along with the email subject and body text, the entire workflow looks like this
msg = MIMEMultipart()msg['Subject'] = subjectmsg['From'] = smtp_usermsg['To'] = recipientmsg.add_header('Content-Type','text/html')msg.attach(MIMEText(message, 'html'))textStream = StringIO()df.to_csv(textStream,index=False)msg.attach(MIMEApplication(textStream.getvalue(), Name=filename))
Feel free to check out my Github repo on the full version of codes. Thanks for reading!