Reputation: 139
I am trying to send an excel file via email but somehow the format and text is altered. I am using python3 and MIMEMultipart().
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
message.attach(MIMEText(body, "plain"))
filename = "file_name.xlsx" # In same directory as script
# Open PDF file in binary mode
with open(filename, 'r') as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
encoders.encode_base64(part)
message.attach(part)
text = message.as_string()
# Log in to server using secure context and send email
context = ssl.create_default_context()
with smtplib.SMTP_SSL(smtp_server, 465 , context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, text)
Upvotes: 2
Views: 6053
Reputation: 189628
The comment is wrong; you are not opening the file in binary mode ('rb'
) and so you are basically corrupting it
Following up on my answer to your previous question, here is a refactored version of your code to use the modern, Python 3.6+ EmailMessage
library instead.
from email.message import EmailMessage
...
message = EmailMessage()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
message.set_content(body, 'plain')
# The OS will look in the current working directory, not in the directory where you saved the script
filename = "file_name.xlsx"
# Notice 'rb'
with open(filename, 'rb') as attachment:
message.add_attachment(
attachment.read(),
maintype='application', subtype='octet-stream')
# AGAIN, no need for a context if you are just using the default SSL
with smtplib.SMTP_SSL(smtp_server, 465) as server:
server.login(sender_email, password)
# AGAIN, prefer the modern send_message method
server.send_message(message)
As you notice, there's quite a lot less boilerplate than with the older Email.Message
API from Python 3.5 or earlier.
A common arrangement is to have a multipart/related
message with body text and an attachment, but the body text represented as a multipart/alternative
structure with both a text/plain
and a text/html
rendering of the message. If you want this, the "asparagus" example from the email
module documentation's examples page contains a recipe which demonstrates that (though it also includes an image instead of a binary attachment, and displays it inline in the HTML attachment).
Tangentially, you might be better off choosing a less clunky format than Excel for sharing data. If it's just a table, a CSV text file would be a lot smaller as well as easier to process on the receiving end. (If you do send Excel, probably actually use its designated MIME type rather than the generic application/octet-stream
.)
Upvotes: 4