使用Python从邮件中下载附件和提取元数据

Posted Sky_Lannister

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Python从邮件中下载附件和提取元数据相关的知识,希望对你有一定的参考价值。

在本篇博客中,我们将解析一段Python代码,该代码可以从电子邮件中下载附件并提取发送人、主题和日期等元数据。

这段代码包含两个函数:download_fileget_email_title。其中,download_file 函数用于将附件保存到指定路径;而 get_email_title 函数则用于提取发件人、主题和日期等信息。

download_file 函数

def download_file(msg):  
    fpath = os.getcwd()
    path_name = qq_email_rx.Subject  

    out_file = fpath + "\\\\" + path_name
    print('文件保存路径是:', out_file)
    doc_function.mkdir(out_file)  

    attachment_files = []
    for part in msg.walk():
        file_name = part.get_filename()  
        contentType = part.get_content_type() 
        mycode = part.get_content_charset() 
        if file_name:
            h = Header(file_name)
            dh = decode_header(h)  
            filename_download = dh[0][0]
            if dh[0][1]:
                filename_download = email_parse.decode_str(str(filename_download, dh[0][1])) 
            attachment_files.append(filename_download)
            data = part.get_payload(decode=True)  
            with open(out_file + "\\\\" + filename_download, 'wb') as f:  
                f.write(data)  

            qq_email_rx.filename = attachment_files
            src = out_file + "\\\\" + filename_download
            if qq_email_rx.filename[0].find(".mp3") != -1:  
                dst = out_file + "\\\\" + "mp3-" + qq_email_rx.Date + filename_download
                time.sleep(2)  
            elif qq_email_rx.filename[0].find(".jpg") != -1 or qq_email_rx.filename[0].find(".bmp") != -1 or \\
                    qq_email_rx.filename[0].find(".png") != -1:  
                pic_name = doc_function.search_file("pic")
                if pic_name == None:
                    pic_num = 0
                else:
                    pic_num = len(pic_name)
                dst = out_file + "\\\\" + "pic" + str(pic_num) + "-" + qq_email_rx.Date + filename_download
                qq_email_tx.main_body = qq_email_tx.main_body + str(pic_num) + "-"
            else:  
                dst = out_file + "\\\\" + qq_email_rx.Date + filename_download

            try:
                os.rename(src, dst)
            except:  
                os.remove(dst)
                os.rename(src, dst)

            print(f'附件 filename_download 已下载及重命名完成')

        elif contentType == 'text/plain': 
            data = part.get_payload(decode=True)
            content = data.decode(mycode)
            qq_email_rx.main_body = content

download_file 函数首先获取当前工作目录,并以电子邮件的主题名称作为文件夹名称创建一个新的文件夹。该函数然后遍历电子邮件中的每一部分,使用 msg.walk() 方法检查是否包含任何附件。如果找到附件,则将其保存到之前创建的文件夹中,并使用 open() 函数重命名文件以包含日期和时间,并相应地更新全局变量 qq_email_rxqq_email_tx。如果电子邮件包含纯文本,则函数从中提取文本,并将其存储在 qq_email_rxmain_body 属性中。

get_email_title 函数

def get_email_title(msg):   
    for header in ['From', 'Subject', 'Date']:  
        value = msg.get(header, '')  
        if value != '':
            if header == 'From':  
                hdr, addr = parseaddr(value)
                name = email_parse.decode_str(hdr)  
                value = '%s <%s>' % (name, addr)
                qq_email_rx.From = name

            elif header == 'Subject':
                value = email_parse.decode_str(value) 
                if value.find("回复") != -1:  
                    qq_email_rx.Subject = value[3:]
                    print(qq_email_rx.Subject)
                else:
                    qq_email_rx.Subject = value

            elif header == 'Date':  
                value = email_parse.decode_str(value) 
                print(value)
                time_format = datetime.datetime.strptime(value, '%a, %d %b %Y %H:%M:%S +%f')
                qq_email_rx.Date = time_format.strftime("%Y-%m-%d %H-%M-%S-")
                print(qq_email_rx.Date)

            print('%s: %s' % (header, value))

get_email_title 函数从电子邮件头中提取发送人、主题和日期等信息。它使用 msg.get() 方法获取每个头字段的值,并使用 email_parse.decode_str() 函数对其进行解码。发送者的名称和电子邮件地址分别使用 parseaddr() 方法提取。检查主题行是否包含“回复”一词,如果包含,则将其后面的字符用作文件夹名称。最后,使用 datetime.datetime.strptime() 方法解析日期,并使用 strftime() 方法将其转换为标准格式,然后将其存储在 qq_email_rxDate 属性中。

这是一个有用的代码片段,可以在需要从电子邮件中提取附件和元数据时使用。

如何使用 Python 从电子邮件内容中获取附加的 eml 文件?

【中文标题】如何使用 Python 从电子邮件内容中获取附加的 eml 文件?【英文标题】:How can I get an attached eml file from email message content using Python? 【发布时间】:2020-03-18 08:40:03 【问题描述】:

我正在使用 python 3.7 和电子邮件、imap 库来阅读电子邮件并提取电子邮件和附件的内容,所有附件(如 excel、csv、pdf)都作为附件下载,但是当我收到任何 .eml 文件时电子邮件,它显示错误,请找到以下代码来读取电子邮件内容和附件,如果收到 eml 文件作为附件,则会显示错误。 它在编写 eml 文件时显示错误。 在写入时 part.get_payload(decode=True) 在 eml 文件的情况下变为空白。

filename = part.get_filename()
if filename is not None:
    dot_position = filename.find('.')
    file_prefix = filename[0:dot_position]
    file_suffix = filename[dot_position:len(filename)]
    # print(dot_position)
    # print(file_prefix)
    # print(file_suffix)
    now = datetime.datetime.now()
    timestamp = str(now.strftime("%Y%m%d%H%M%S%f"))
    newFileName = file_prefix + "_" + timestamp + file_suffix
    sv_path = os.path.join(svdir, newFileName)
    # allfiles = allfiles.append(["oldfilename": filename, "newfilename": newFileName])
    mydict = filename + '$$' + newFileName
    mydict1 = mydict1 + ',' + mydict
    print(mydict1)
    if not os.path.isfile(sv_path):
        print("oldpath:---->" + sv_path)
        # filename = os.rename(filename, filename + '_Rahul')
        # sv_path = os.path.join(svdir, filename)
        # print("Newpath:---->" + sv_path)
        fp = open(sv_path, 'wb')
        # print("Rahul")
        print(part.get_payload(decode=True))
        # try:
        # newFileByteArray = bytearray(fp)
        # if part.get_payload(decode=True) is not None:
        fp.write(part.get_payload(decode=True))
        # except (TypeError, IOError):
        #    pass
        fp.close()

错误是

<class 'TypeError'> ReadEmailUsingIMAP.py 129
a bytes-like object is required, not 'NoneType'

【问题讨论】:

代码中的哪一行生成了该错误消息? fp.write(part.get_payload(decode=True)) ,在写入.eml文件时显示错误 get_payload iscoming None.. 您能否提供所有必要的代码和数据,以便我们运行您的程序?请参阅:minimal reproducible example. @RahulGour 至少,partsvdirmydict1 是什么? 您能否也发布完整的输出(包括打印语句的输出和完整的堆栈跟踪?) 【参考方案1】:

使用 eml_parser https://pypi.org/project/eml-parser/ 导入日期时间 导入json 导入 eml_parser

def json_serial(obj):
    if isinstance(obj, datetime.datetime):
        serial = obj.isoformat()
        return serial


with open('sample.eml', 'rb') as fhdl:
    raw_email = fhdl.read()

parsed_eml = eml_parser.eml_parser.decode_email_b(raw_email)

print(json.dumps(parsed_eml, default=json_serial))

【讨论】:

以上是关于使用Python从邮件中下载附件和提取元数据的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Python 从电子邮件内容中获取附加的 eml 文件?

使用PHP阅读电子邮件附件(csv)

用python从邮件中下载附件

使用GOLANG从电子邮件文件中提取附件

从 PST 文件中提取电子邮件和附件

从 Outlook 电子邮件中提取嵌入的图像