0

I'm sending an email with a python script. It's a multipart mail composed with plain-text, html, and an attachment.

The mail is correctly sent but on some clients the attachment doesn't appear. I read in this discussion that changing "alternative" by "html" or "mixed" solve the problem message = MIMEMultipart("alternative")

But since then both part plain text and html appear in the body of the mail. How to solve this issue ?

Thanks

# Create a multipart message and set headers
message = MIMEMultipart("mixed")
message["From"] = sender_email
message["To"] = ", ".join(to)
message["Cc"] = ", ".join(cc)
message["Subject"] = subject

filename = 'myfile.zip'  

mimetype, encoding = guess_type(os.path.join(os.path.abspath(savepath),filename))
mimetype = mimetype.split('/', 1)
fp = open(os.path.join(os.path.abspath(savepath),filename), 'rb')
attachment = MIMEBase(mimetype[0], mimetype[1])
attachment.set_payload(fp.read())
# Encode file in ASCII characters to send by email  
encoders.encode_base64(attachment)
# Add header as key/value pair to attachment part
attachment.add_header('Content-Disposition','attachment', filename=filename)

# Create the plain-text and HTML version of your message
text = """\
my plain-text body
"""
html = """\
<html> my html body</html>
"""

# Add attachment to message and convert message to string
message.attach(attachment)

# Turn these into plain/html MIMEText objects
part1 = MIMEText(text, "plain")
part2 = MIMEText(html, "html")

# Add HTML/plain-text parts to MIMEMultipart message
# The email client will try to render the last part first
message.attach(part1)
message.attach(part2)

# convert message to string
text = message.as_string()

with smtplib.SMTP_SSL(host='__MYHOST__', port=587) as server:
    server.login(credentials.user, credentials.paswd)
    server.sendmail(sender_email,  message["To"].split(",") + message["Cc"].split(","), text)   
Eric
  • 95
  • 7
  • More detail here: https://stackoverflow.com/questions/3902455/mail-multipart-alternative-vs-multipart-mixed – Eric Mar 08 '22 at 13:46

1 Answers1

3

It is not directly a Python question but a MIME one.

Your message contains a body and an attachment, and the body is an alternative message (viewable as HTML or text). So the structure of your message should be:

MIXED
| ALTERNATIVE
| | text part
| | html part
| attachment

So instead of attaching part1 and part2 to the main message, you should first build a MIMEMultipart alternative to contain them and attach it to the main message:

...
body = MIMEMultipart("alternative")
body.attach(part1)
body.attach(part2)
message.attach(body)
...
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252