I am trying to send an email using Python smtplib
.
My objective is to include the below info in email
Attachment file
#works fine
Paste the contents of a table in message body
#works fine
Write a few lines about the table (as text) in message body
# not works. instead stores as an attachment
So, I tried the below code
message = MIMEMultipart() message['Subject'] = 'For your review - files' message['From'] = 'user2@org.com' message['To'] = 'user1@org.com' # code to paste table contents in outlook message window - works fine body_content = output # this has the pretty table - html table message.attach(MIMEText(body_content, "html")) # code to paste the written text in outlook message window - not works. instead of writing the text in outlook body,it stores as an attachment written_text = """ Hi, How are you?""" message.attach(MIMEText(written_text, "plain")) # code to attach an csv file to a outlook email - works fine with open(filename, "rb") as attachment: part = MIMEBase("application", "octet-stream") part.set_payload(attachment.read()) encoders.encode_base64(part) part.add_header( "Content-Disposition", f"attachment; filename= {filename}", ) message.attach(part) msg_body = message.as_string() server = SMTP('internal.org.com', 2089) server.sendmail(message['From'], message['To'], msg_body) print("mail sent successfully") server.quit()
The problem in my code is that it creates a text file (containing the message “Hi, How are you”) and sends as an attachment?
But I want “Hi, How are you” as a text message in the main Outlook message window.
Advertisement
Answer
The immediate problem is that many email clients assume that text body parts after the first are attachments. You can experiment with adding an explicit Content-Disposition: inline
to the part(s) you want rendered as part of the main message, but is there a reason these need to be separate body parts in the first place? Combining the text fragments into a single body part would perhaps make more sense here.
More fundamentally, your email
code was written for an older Python version. The email
module in the standard library was overhauled in Python 3.6 to be more logical, versatile, and succinct; new code should target the (no longer very) new EmailMessage
API. Probably throw away this code and start over with modern code from the Python email
examples documentation.
from email.message import EmailMessage message = EmailMessage() message['Subject'] = 'For your review - files' message['From'] = 'user2@org.com' message['To'] = 'user1@org.com' message.set_content(output, subtype="html") written_text = """ Hi, How are you?""" message.add_attachment( written_text, subtype="plain", disposition="inline") with open(filename, "rb") as attachment: message.add_attachment( attachment.read(), maintype="application", subtype="octet-stream", filename=filename) with SMTP('internal.org.com', 2089) as server: server.send_message(message) print("mail sent successfully") server.quit()
If the final attachment is really a CSV file, specifying it as application/octet-stream
is a bit misleading; the proper MIME type would be text/csv
(see also What MIME type should I use for CSV?)