How do I reply to an email using the Python imaplib and include the original message? How do I reply to an email using the Python imaplib and include the original message? django django

How do I reply to an email using the Python imaplib and include the original message?


The original MIME tree structure of the incoming message is as follows (using email.iterators._structure(msg)):

multipart/mixed    text/html                (message)    application/octet-stream (attachment 1)    application/octet-stream (attachment 2)

Replying via GMail results in the following structure:

multipart/alternative    text/plain    text/html

I.e. they aren't being as smart as I thought, just discarding the attachments (good) and providing text and HTML versions that explicitly restructure the "quoted content."

I'm beginning to think that's all I should do too, just reply with a simple message as after discarding the attachments there's not much point in keeping the original message.

Still, might as well answer my original question since I've figured out how to now anyway.

First, replace all the attachments in the original message with text/plain placeholders:

import emailoriginal = email.message_from_string( ... )for part in original.walk():    if (part.get('Content-Disposition')        and part.get('Content-Disposition').startswith("attachment")):        part.set_type("text/plain")        part.set_payload("Attachment removed: %s (%s, %d bytes)"                         %(part.get_filename(),                            part.get_content_type(),                            len(part.get_payload(decode=True))))        del part["Content-Disposition"]        del part["Content-Transfer-Encoding"]

Then create a reply message:

from email.mime.multipart import MIMEMultipartfrom email.mime.text import MIMETextfrom email.mime.message import MIMEMessagenew = MIMEMultipart("mixed")body = MIMEMultipart("alternative")body.attach( MIMEText("reply body text", "plain") )body.attach( MIMEText("<html>reply body text</html>", "html") )new.attach(body)new["Message-ID"] = email.utils.make_msgid()new["In-Reply-To"] = original["Message-ID"]new["References"] = original["Message-ID"]new["Subject"] = "Re: "+original["Subject"]new["To"] = original["Reply-To"] or original["From"]new["From"] = "me@mysite.com"

Then attach the original MIME message object and send:

new.attach( MIMEMessage(original) )s = smtplib.SMTP()s.sendmail("me@mysite.com", [new["To"]], new.as_string())s.quit()

The resulting structure is:

multipart/mixed    multipart/alternative        text/plain        text/html    message/rfc822        multipart/mixed            text/html            text/plain            text/plain

Or it's a bit simpler using Django:

from django.core.mail import EmailMultiAlternativesfrom email.mime.message import MIMEMessagenew = EmailMultiAlternatives("Re: "+original["Subject"],                             "reply body text",                              "me@mysite.com", # from                             [original["Reply-To"] or original["From"]], # to                             headers = {'Reply-To': "me@mysite.com",                                        "In-Reply-To": original["Message-ID"],                                        "References": original["Message-ID"]})new.attach_alternative("<html>reply body text</html>", "text/html")new.attach( MIMEMessage(original) ) # attach original messagenew.send()

The result ends (in GMail at least) showing the original message as "---- Forwarded message ----" which isn't quite what I was after, but the general idea works and I hope this answer helps someone trying to figure out how to fiddle with MIME messages.