Python:如果原始电子邮件没有“Body”标记或任何东西,那么如何解析原始电子邮件中的正文

2024-04-24 20:17:38 发布

您现在位置:Python中文网/ 问答频道 /正文

似乎很容易得到

From
To
Subject

等通过

import email
b = email.message_from_string(a)
bbb = b['from']
ccc = b['to']

假设"a"是这样的原始电子邮件字符串。

a = """From root@a1.local.tld Thu Jul 25 19:28:59 2013
Received: from a1.local.tld (localhost [127.0.0.1])
    by a1.local.tld (8.14.4/8.14.4) with ESMTP id r6Q2SxeQ003866
    for <ooo@a1.local.tld>; Thu, 25 Jul 2013 19:28:59 -0700
Received: (from root@localhost)
    by a1.local.tld (8.14.4/8.14.4/Submit) id r6Q2Sxbh003865;
    Thu, 25 Jul 2013 19:28:59 -0700
From: root@a1.local.tld
Subject: oooooooooooooooo
To: ooo@a1.local.tld
Cc: 
X-Originating-IP: 192.168.15.127
X-Mailer: Webmin 1.420
Message-Id: <1374805739.3861@a1>
Date: Thu, 25 Jul 2013 19:28:59 -0700 (PDT)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="bound1374805739"

This is a multi-part message in MIME format.

--bound1374805739
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

ooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooo

--bound1374805739--"""

问题

如何通过python获取此电子邮件的Body

到目前为止,这是我唯一知道的代码,但我还没有测试它。

if email.is_multipart():
    for part in email.get_payload():
        print part.get_payload()
else:
    print email.get_payload()

这是正确的方法吗?

或者有更简单的事情,比如。。。

import email
b = email.message_from_string(a)
bbb = b['body']

是吗?


Tags: frommessagegetemaillocala1rootcontent
3条回答

有非常好的package可用于分析电子邮件内容和适当的文档。

import mailparser

mail = mailparser.parse_from_file(f)
mail = mailparser.parse_from_file_obj(fp)
mail = mailparser.parse_from_string(raw_mail)
mail = mailparser.parse_from_bytes(byte_mail)

使用方法:

mail.attachments: list of all attachments
mail.body
mail.to

要非常积极地处理实际的电子邮件正文(但仍有可能您没有解析正确的部分),您必须跳过附件,并将注意力集中在纯文本或html部分(取决于您的需要)以进行进一步处理。

由于前面提到的附件可以而且经常是文本/纯文本或文本/html部分,因此此非防弹示例通过检查内容处理头跳过这些附件:

b = email.message_from_string(a)
body = ""

if b.is_multipart():
    for part in b.walk():
        ctype = part.get_content_type()
        cdispo = str(part.get('Content-Disposition'))

        # skip any text/plain (txt) attachments
        if ctype == 'text/plain' and 'attachment' not in cdispo:
            body = part.get_payload(decode=True)  # decode
            break
# not multipart - i.e. plain text, no attachments, keeping fingers crossed
else:
    body = b.get_payload(decode=True)

顺便说一句,walk()在mime部件上迭代得非常好,而get_payload(decode=True)在解码base64等方面为您做了大量的工作。

一些背景——正如我所暗示的,MIME电子邮件的美妙世界呈现出许多“错误地”找到消息体的陷阱。 在最简单的情况下,它位于唯一的“文本/普通”部分,get_payload()非常诱人,但我们并不生活在一个简单的世界中-它通常被多部分/可选内容、相关内容、混合内容等包围。Wikipedia对它的描述非常严格-MIME,但是考虑到下面所有这些情况都是有效的-而且是常见的-我们必须考虑周围的安全网:

非常常见-在普通编辑器(Gmail、Outlook)中,发送带附件的格式化文本时,您会看到:

multipart/mixed
 |
 +- multipart/related
 |   |
 |   +- multipart/alternative
 |   |   |
 |   |   +- text/plain
 |   |   +- text/html
 |   |      
 |   +- image/png
 |
 +-- application/msexcel

相对简单-只是替代表示:

multipart/alternative
 |
 +- text/plain
 +- text/html

无论好坏,此结构也有效:

multipart/alternative
 |
 +- text/plain
 +- multipart/related
      |
      +- text/html
      +- image/jpeg

希望这有帮助。

另外,我的观点是不要轻率地处理电子邮件-它会在你最不期望的时候被咬:)

使用Message.get_payload

b = email.message_from_string(a)
if b.is_multipart():
    for payload in b.get_payload():
        # if payload.is_multipart(): ...
        print payload.get_payload()
else:
    print b.get_payload()

相关问题 更多 >