Python:如何解析原始电子邮件中的正文,假设原始电子邮件没有“正文”标签或任何内容

2025-03-19 08:56:00
admin
原创
14
摘要:问题描述:似乎很容易得到From To Subject 等等通过import email b = email.message_from_string(a) bbb = b['from'] ccc = b['to'] 假设这"a"是原始电子邮件字符串,看起来像这样。a = "&qu...

问题描述:

似乎很容易得到

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

问题

Body如何通过 python获取该电子邮件?

到目前为止这是我所知道的唯一代码但我尚未测试它。

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']


解决方案 1:

为了确保您处理的是实际的电子邮件正文(但仍然有可能您没有解析正确的部分),您必须跳过附件,并专注于纯文本或 HTML 部分(取决于您的需要)进行进一步处理。

由于前面提到的附件通常是 text/plain 或 text/html 部分,这个非防弹样本通过检查 content-disposition 标头来跳过这些部分:

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 电子邮件的奇妙世界存在许多“错误”查找邮件正文的陷阱。在最简单的情况下,它位于唯一的“text/plain”部分,并且 get_payload() 非常诱人,但我们并不生活在一个简单的世界中 - 它通常被多部分/替代、相关、混合等内容所包围。维基百科对其进行了严格的描述 - 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

PS 我的观点是不要轻易对待电子邮件——它会在你最意想不到的时候给你带来麻烦:)

解决方案 2:

使用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()

解决方案 3:

有一个非常好的软件包可以用来解析电子邮件内容并附带适当的文档。

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

解决方案 4:

Python 3.6+ 提供了内置的便捷方法来查找和解码纯文本正文,如@Todor Minakov的答案中所示。您可以使用EMailMessage.get_body()get_content()方法:

msg = email.message_from_string(s, policy=email.policy.default)
body = msg.get_body(('plain',))
if body:
    body = body.get_content()
print(body)

None请注意,如果没有(明显的)纯文本正文部分,则会出现这种情况。

如果您正在读取 mbox 文件,则可以为邮箱构造函数提供一个EmailMessage工厂:

mbox = mailbox.mbox(mboxfile, factory=lambda f: email.message_from_binary_file(f, policy=email.policy.default), create=False)
for msg in mbox:
    ...

请注意,您必须email.policy.default按照策略传递,因为它不是默认的......

解决方案 5:

python 中没有b['body']。您必须使用 get_payload。

if isinstance(mailEntity.get_payload(), list):
    for eachPayload in mailEntity.get_payload():
        ...do things you want...
        ...real mail body is in eachPayload.get_payload()...
else:
    ...means there is only text/plain part....
    ...use mailEntity.get_payload() to get the body...

祝你好运。

解决方案 6:

如果 emails 是 pandas 数据框,emails.message 是电子邮件文本的列

## Helper functions
def get_text_from_email(msg):
    '''To get the content from email objects'''
    parts = []
    for part in msg.walk():
        if part.get_content_type() == 'text/plain':
            parts.append( part.get_payload() )
    return ''.join(parts)

def split_email_addresses(line):
    '''To separate multiple email addresses'''
    if line:
        addrs = line.split(',')
        addrs = frozenset(map(lambda x: x.strip(), addrs))
    else:
        addrs = None
    return addrs 

import email
# Parse the emails into a list email objects
messages = list(map(email.message_from_string, emails['message']))
emails.drop('message', axis=1, inplace=True)
# Get fields from parsed email objects
keys = messages[0].keys()
for key in keys:
    emails[key] = [doc[key] for doc in messages]
# Parse content from emails
emails['content'] = list(map(get_text_from_email, messages))
# Split multiple email addresses
emails['From'] = emails['From'].map(split_email_addresses)
emails['To'] = emails['To'].map(split_email_addresses)

# Extract the root of 'file' as 'user'
emails['user'] = emails['file'].map(lambda x:x.split('/')[0])
del messages

emails.head()

解决方案 7:

根据 Doctor J 的回答进行小更新。解析电子邮件消息的纯文本部分(如果有)。也可以尝试获取html,因为只发送 html 邮件的(坏)习惯越来越流行。

from email import message_from_string
from email import policy

raw_string = raw_string.strip() # where raw_string is the email message (DATA)
msg = message_from_string(raw_string, policy=policy.default)
body = msg.get_body(('plain',))
if body:
    body = body.get_content()
    print(body)

当将电子邮件数据作为字符串处理时,必须删除前导/尾随空格,否则会浪费很多时间!

解决方案 8:

以下是每次对我有用的代码(适用于 Outlook 电子邮件):

#to read Subjects and Body of email in a folder (or subfolder)

import win32com.client  
#import package

outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")  
#create object

#get to the desired folder (MyEmail@xyz.com is my root folder)

root_folder = 
outlook.Folders['MyEmail@xyz.com'].Folders['Inbox'].Folders['SubFolderName']

#('Inbox' and 'SubFolderName' are the subfolders)

messages = root_folder.Items

for message in messages:
if message.Unread == True:    # gets only 'Unread' emails
    subject_content = message.subject
# to store subject lines of mails

    body_content = message.body
# to store Body of mails

    print(subject_content)
    print(body_content)

    message.Unread = True         # mark the mail as 'Read'
    message = messages.GetNext()  #iterate over mails
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1730  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1390  
  随着科技的飞速发展,人工智能(AI)与产品生命周期管理(PLM)的结合正逐渐成为智能化项目管理领域的新趋势。这一融合不仅为企业带来了前所未有的机遇,也对传统的项目管理模式提出了挑战。深入探讨AI与PLM结合在智能化项目管理中的应用、优势以及面临的挑战,对于企业把握未来发展方向具有重要意义。AI与PLM结合的基础AI技术...
plm办公软件   16  
  PLM(Product Lifecycle Management)项目管理软件旨在对产品从概念设计到退役的全生命周期进行有效管理,涵盖产品数据管理、流程管理、协同工作等多个方面。然而,在实际的实施过程中,往往会面临诸多难点,这些难点若不妥善解决,将严重影响软件实施的效果与企业的业务发展。深入剖析这些难点并制定切实可行的...
plm系统简介   14  
  引言在数字化转型的浪潮中,研发数据治理成为企业提升创新能力和竞争力的关键环节。传统的数据治理模式在应对复杂多变的研发数据时,往往显得力不从心。知识图谱技术的兴起,为研发数据治理带来了新的思路和方法。而产品生命周期管理(PLM)系统作为研发数据的重要管理平台,与知识图谱的结合,开创了研发数据治理的新范式。这种新范式不仅能...
plm管理系统   14  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用