如何使用Python imaplib回复电子邮件并包含原始邮件?

时间:2010-02-02 06:10:03

标签: python django email mime imaplib

我目前正在使用imaplib从服务器获取电子邮件并处理内容和附件。

我想回复带有状态/错误消息的消息,并链接到我的网站上生成的内容,如果可以处理的话。这应该包括原始邮件,但应删除任何附件(这将是很大的),并最好用它们的文件名/大小替换它们。

由于我已经走过了MIME消息部分,我假设我需要做的是构建一个包含原始消息副本的新MIME消息树,并删除/替换附件节点。

在我走这条道路之前,我希望有人可以给我一些提示。有没有任何类型的库函数可以做到这一点?我应该坚持的任何标准行为?

我目前知道/我正在使用imaplibsmtplibemail模块,但可能遗漏了明显的内容。这也在Django中运行,因此可以使用django.core.email中的任何内容,如果这样可以更容易。

1 个答案:

答案 0 :(得分:16)

传入邮件的原始MIME树结构如下(使用email.iterators._structure(msg)):

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

通过GMail回复会产生以下结构:

multipart/alternative
    text/plain
    text/html

即。他们没有我想象的那么聪明,只是放弃附件(好)并提供明确重构“引用内容”的文本和HTML版本。

我开始认为这也是我应该做的,只需回复一条简单的信息,因为在丢弃附件之后,保留原始信息没有多大意义。

不过,不管怎么回答我原来的问题,不管怎么回事。

首先,使用text / plain占位符替换原始邮件中的所有附件:

import email

original = 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"]

然后创建回复消息:

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.message import MIMEMessage

new = 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"

然后附加原始MIME消息对象并发送:

new.attach( MIMEMessage(original) )

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

得到的结构是:

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

或者使用Django有点简单:

from django.core.mail import EmailMultiAlternatives
from email.mime.message import MIMEMessage

new = 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 message
new.send()

结果(至少在GMail中)显示原始消息为“---- Forwarded message ----”,这不是我所追求的,但总体思路有效,我希望这个答案有帮助有人试图找出如何摆弄MIME邮件。