【问题标题】:Spaces replaced by =20 after extracting text from email从电子邮件中提取文本后,空格替换为 =20
【发布时间】:2020-05-31 01:31:23
【问题描述】:

我尝试使用 python 中的 email 和 imaplib 模块获取收到的 gmail 的文本。用utf-8解码后,得到消息的payload后,所有的空格还是换成=20。我可以使用另一个解码步骤来解决这个问题吗?

代码如下:(我从 youtube 教程中得到它 - https://youtu.be/Jt8LizzxkPU

``

import email
import imaplib



username = "abc"
password = "123"

mail = imaplib.IMAP4_SSL("imap.gmail.com")
mail.login(username,password)

mail.select("inbox")

result, data = mail.uid("search", None,"ALL")

inbox_item_list = data[0].split()

for item in inbox_item_list:
    #most_recent = inbox_item_list[-1]
    #oldest = inbox_item_list[0]

    result2, email_data = mail.uid('fetch',item,'(RFC822)') 

    raw_email = email_data[0][1].decode("utf-8")

    email_message = email.message_from_string(raw_email)

    to_ = email_message['To']
    from_ = email_message['From']
    subject_ = email_message['Subject']

    counter = 1
    for part in email_message.walk():
        if part.get_content_maintype() == "multipart":
            continue
        filename = part.get_filename()
        if not filename:
            ext = ".html"
            filename = "msg-part-%08d%s" %(counter, ext)
        counter += 1   

    #save file
    content_type = part.get_content_type()
    print(subject_)
    print (content_type)
    if "plain" in content_type:
        print(part.get_payload())
    elif "html" in content_type:
        print("do some beautiful soup")
    else:
        print(content_type)

``

【问题讨论】:

  • 发布您的代码/脚本的相关部分。看起来不像是反向引用可打印编码。在责备别人之前排除代码中的“问题”。
  • 困难的方法:手动解码各种电子邮件部分,例如,=20 暗示quopri.decodestring(b'=20')。或者您可以改为传递整个电子邮件:email.message_from_string(email_text),它可以使用适当的解码方法解码不同的部分
  • 我想,我已经用email.message_from_string(email_text) 完成了这一步。所以我不认为问题与这个特定步骤有关。 @AnFi 感谢您的回答,但我不怪任何人。我只是在寻找一种方法来排除我的代码中的问题。 ^^
  • 如果空格是唯一的问题,为什么不用' '替换所有'=20'
  • 是的,这可行。但是,如果有一个文本,实际上是故意包含 =20s 呢?我的意思是我可以做到,但它不是那么干净,对吧?

标签: python python-3.x email imap imaplib


【解决方案1】:

这是一个完整的代码示例,说明如何解码简单电子邮件(包含文字 =20 以及应由空格替换的 =20 序列):

#!/usr/bin/env python3
import email.policy

email_text = """Subject: =?UTF-8?B?dGVzdCDwn5OnID0yMA==?=
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo=
oooooooooooooooooooooooooooooong=20word
=3D20
^ line starts with =3D20
emoji: <=F0=9F=93=A7>"""
msg = email.message_from_string(
    email_text, policy=email.policy.default
)
print("Subject: <{subject}>".format_map(msg))
assert not msg.is_multipart()
print(msg.get_content())

输出

Subject: <test ? =20>
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong word
=20
^ line starts with =20
emoji: <?>

msg.walk(), part.get_payload(decode=True) 可用于遍历更复杂的EmailMessage 对象。见email Examples

【讨论】:

  • 感谢编码示例,但我认为,我上面的代码已经包含了 email.message_from_strings 步骤。 =20s 无论如何都会出现。
  • @Chris761:查看上面的完整代码示例 ^ 你在email_text 中的word 之前看到=20 吗?你看到它被msg.get_content() 中的空格替换了吗? message_from_string() 返回一个对象 (EmailMessage)。您必须调用它的方法,例如 get_content() 来获取您需要的特定部分。
【解决方案2】:

尝试import quopri,然后当您获得电子邮件正文的内容(或任何包含=20s 的文本)时,您可以使用quopri.decodestring()

我是这样做的

quopri.decodestring(part.get_payload())

但请记住,如果您特别想从quoted-printable 解码。通常我会说@jfs 的答案更整洁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    • 2018-03-13
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 2014-03-23
    相关资源
    最近更新 更多