Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python SMTP Emails Showing Both Plain and HTML Versions

Sending an smtp email, and when I receive the email it shows the plain text version and the html version back to back. The point of this is to take incoming email dicts from Sendgrid and then send them to another user. The 'message' object referenced in the code is the dict Sendgrid posts to my endpoint.

Here is what I'm seeing:

    test

Me
Signature

    test

Me
Signature

Here is the string I am sending to the mailServer:

Content-Type: multipart/mixed; boundary="===============5453410005537724489=="
MIME-Version: 1.0
To: [email protected]
From: Me <[email protected]>
Subject: test
reply-to: Original Sender <[email protected]>

--===============5453410005537724489==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

    test

Me
Signature




--===============5453410005537724489==
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><span class="Apple-tab-span" style="white-space:pre">    </span>test<br class=""><div apple-content-edited="true" class="">
<span>Me</span><br><span>Signature</span>
</div>
<br class=""></body></html>
--===============5453410005537724489==--

Lastly, here is the Python I am using to send the email:

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

subject = message.get('subject', 'No Subject')
text = message.get('text', None)
html = message.get('html', None)
to = message.get('to')
cc = message.get('cc', None)
reply_to = message.get('from')

msg = MIMEMultipart()
msg['To'] = '[email protected]'
msg['From'] = '[email protected]'
msg['Subject'] = subject
msg.add_header('reply-to', reply_to)

toaddrs = msg['To']
if cc is not None:
    msg['CC'] = ', '.join(cc)
    toaddrs += ', ' + msg['CC']

if text is not None:
    msg.attach(MIMEText(text[0].encode('ascii', 'ignore'), 'plain'))
else:
    msg.attach(MIMEText('No plain text for this email', 'plain'))

if html is not None:
    msg.attach(MIMEText(html[0].encode('ascii', 'ignore'), 'html'))

mailServer = smtplib.SMTP("smtp.gmail.com", 587)
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(GMAIL_USERNAME, GMAIL_PASSWORD)
mailServer.sendmail(GMAIL_USERNAME, toaddrs, msg.as_string())
mailServer.quit()

What am I missing here?

like image 851
Crowson Avatar asked Dec 25 '22 02:12

Crowson


1 Answers

You've specified multipart/mixed content, which means that the parts are independent messages, and should all be shown, in exactly the order included.

You want multipart/alternative, which means the parts are alternative versions of the same message, and only the last one whose content-type the receiver can understand should be shown.

In other words:

msg = MIMEMultipart('alternative')

Wikipedia has a nice explanation of the different multipart subtypes, but for the official definition, turn to RFC 2046:

5.1.3. Mixed Subtype

The "mixed" subtype of "multipart" is intended for use when the body parts are independent and need to be bundled in a particular order. Any "multipart" subtypes that an implementation does not recognize must be treated as being of subtype "mixed".

5.1.4. Alternative Subtype

The "multipart/alternative" type is syntactically identical to "multipart/mixed", but the semantics are different. In particular, each of the body parts is an "alternative" version of the same information.

Systems should recognize that the content of the various parts are interchangeable. Systems should choose the "best" type based on the local environment and references, in some cases even through user interaction. As with "multipart/mixed", the order of body parts is significant. In this case, the alternatives appear in an order of increasing faithfulness to the original content. In general, the best choice is the LAST part of a type supported by the recipient system's local environment.

"Multipart/alternative" may be used, for example, to send a message in a fancy text format in such a way that it can easily be displayed anywhere…

like image 148
abarnert Avatar answered Dec 27 '22 15:12

abarnert