Search code examples
pythonpython-2.7mime-typesmimesmtplib

Combining plain text and HTML in a mail sent with email/smtplib


Using the example given here, I've written some code to send a mostly plain-text email with a hyperlink in the footer:

def send_mail(subject, removed_ids, added_ids):
    parser = ConfigParser()
    parser.read('config.ini')
    from_address = parser.get('smtp', 'from')
    to_address  = parser.get('smtp', 'to')
    subject = subject
    host = parser.get('smtp', 'host')
    port = parser.get('smtp', 'port')
    password = parser.get('smtp', 'password')

    msg = MIMEMultipart('alternative')
    msg['From'] = from_address
    msg['To'] = to_address
    msg['Subject'] = subject

    body = 'The following Instruction IDs have been removed:\n'
    for id in removed_ids:
        body = body + id + '\n'
    for id in added_ids:
        body = body + id + '\n'
    body = body + '\n'
    body = body + 'The following Instruction IDs have been added:\n'
    msg.attach(MIMEText(body, 'plain'))
    msg.attach(MIMEText(EMAIL_BODY_FOOTER_HYPERLINK_TO, 'html'))

    server = smtplib.SMTP(host, port)
    server.starttls()
    server.login(from_address, password)
    text = msg.as_string()
    server.sendmail(from_address, to_address, text)
    server.quit()

Before I added the HTML section, the plain-text was appearing fine. Now after adding:

msg = MIMEMultipart('alternative')
msg.attach(MIMEText(body, 'plain'))
msg.attach(MIMEText(EMAIL_BODY_FOOTER_HYPERLINK_TO, 'html'))

The HTML footer is now received, but the email is completely missing the plain text that should have preceded it. Where have I gone wrong?


Solution

  • You misunderstood how multipart messages work.

    Plaintext and HTML parts are not "joined" by the client in any way. Both parts should contain the entire message. HTML-clients will show HTML part. Text clients which are incapable of displaying HTML will show text part and ignore HTML part.

    So you need to include your message into HTML part too, possibly escaped or otherwise HTML-formatted.

    Of course, it would be nice to include your URL into plaintext part as well, just don't wrap it into <a> tag. Most clients are quite good at detecting URL's in plaintext emails and highlighting them, and this way your recipients aren't losing anything just because they're using a text-only email client.