首页 > 解决方案 > AttributeError:“NoneType”对象没有属性“解码”

问题描述

我正在尝试在 Python3 中从我的 gmail 收件箱中读取一封电子邮件。所以我跟着这个教程:https ://www.thepythoncode.com/article/reading-emails-in-python

我的代码如下:

 username = "*****@gmail.com"
password = "******"
# create an IMAP4 class with SSL 
imap = imaplib.IMAP4_SSL("imap.gmail.com")
# authenticate
imap.login(username, password)
status, messages = imap.select("INBOX")
# total number of emails
messages = int(messages[0])
    

for i in range(messages, 0, -1):
    # fetch the email message by ID
    res, msg = imap.fetch(str(i), "(RFC822)")
    for response in msg:
        if isinstance(response, tuple):
            # parse a bytes email into a message object
            msg = email.message_from_bytes(response[1])
            # decode the email subject
            subject = decode_header(msg["Subject"])[0][0]
            if isinstance(subject, bytes):
                # if it's a bytes, decode to str
                subject = subject.decode()
            # email sender
            from_ = msg.get("From")
            # if the email message is multipart
            if msg.is_multipart():
                # iterate over email parts
                for part in msg.walk():
                    # extract content type of email
                    content_type = part.get_content_type()
                    content_disposition = str(part.get("Content-Disposition"))

                    # get the email body
                    body = part.get_payload(decode=True).decode()
                    print(str(body))

    imap.close()
    imap.logout()
    print('DONE READING EMAIL')

我正在使用的库是:

import imaplib
import email
from email.header import decode_header

但是,当我执行它时,我收到以下错误消息,我不明白,因为我的收件箱中从来没有空电子邮件...

Traceback (most recent call last):

  File "<ipython-input-19-69bcfd2188c6>", line 38, in <module>
    body = part.get_payload(decode=True).decode()

AttributeError: 'NoneType' object has no attribute 'decode'

任何人都知道我的问题可能是什么?

标签: pythonpython-3.xemailimapimaplib

解决方案


文档中:

可选的 decode 是一个标志,指示是否应该根据 Content-Transfer-Encoding 标头对有效负载进行解码。当 True 并且消息不是多部分时,如果此标头的值是quoted-printable 或 base64,则有效负载将被解码。如果使用了其他编码,或者缺少 Content-Transfer-Encoding 标头,或者如果有效负载具有虚假的 base64 数据,则有效负载按原样返回(未解码)。如果消息是多部分且解码标志为 True,则返回 None。解码的默认值为 False。

(注意:此链接适用于 python2 - 无论出于何种原因,python3 的相应页面似乎都没有提及get_payload。)

所以这听起来像是某些消息的一部分:

  • 缺少内容传输编码(email.message没有说明它是如何被解码的),或者
  • 使用 QP 或 base64 以外的编码(email.message不支持解码),或
  • 声称是 base-64 编码,但包含无法解码的错误编码字符串

最好的办法可能就是跳过它。

代替:

                    body = part.get_payload(decode=True).decode()

和:

                    payload = part.get_payload(decode=True)
                    if payload is None:
                        continue
                    body = payload.decode()

尽管我不确定decode()您调用的方法是否在payload使用. 你可能应该对此进行测试,如果你发现这个调用没有做任何事情(即如果和相等),那么你可能会完全省略这一步:get_payloaddecode=Truedecodebodypayload

                    body = part.get_payload(decode=True)
                    if body is None:
                        continue

如果您添加一些关于from_and的打印语句subject,您应该能够识别受影响的消息,然后转到 gmail 中的“显示原始”进行比较,看看到底发生了什么。


推荐阅读