Python 2.7 - 从电子邮件消息文件中提取Zip

5

我需要提取.zip档案中的文件并提取其数据。.zip档案附加在电子邮件消息文件中;我不使用邮件协议来访问邮箱。我能够解析这些邮件消息...

...
from email.parser import Parser
...
for fileName in os.listdir(mailDir):
    ...
    message = Parser().parse(open(mailDir + '/' + fileName, 'r'))
    ...
    for part in message.walk():
        if part.get_content_type() == 'application/octet-stream':

当我开始编写这段代码时,我测试的是带有 .csv 附件的电子邮件,并没有问题访问附件并提取数据,但现在我正在处理带有 .zip(包含之前使用的 .csv)的电子邮件,我卡住了。 添加...

import zipfile

...但是似乎我需要将附加的.zip实际保存到文件系统中才能使用zipfile。我不想这样做,认为(希望)我可以简单地使用...

zipfile.ZipFile(the_base64_string_from_message, 'r')

但是那样做失败了。我如何在不在文件系统中创建.zip档案的情况下访问存档?另外,也许我甚至不应该使用电子邮件模块(仅使用它来轻松查找附件)?
2个回答

5
你可能需要的是StringIO模块,它将字符串封装成文件接口。此外,你需要对电子邮件附件的负载进行base64解码,以便处理正确的字节。以下是一个示例,它将附件解压缩到当前工作目录:
import email
import zipfile
from cStringIO import StringIO
import base64

with open('some_email_with_zip.eml', 'r') as f:
    m = email.message_from_file(f)

for part in m.walk():
    # You might also check to see if the content-type for your zip files is
    # application/zip instead of application/octet-stream
    if part.get_content_type() == 'application/zip':
        zip_bytes = base64.b64decode(part.get_payload())
        file_wrapper = StringIO(zip_bytes)
        if zipfile.is_zipfile(file_wrapper):
            with zipfile.ZipFile(file_wrapper, 'r') as zf:
                zf.extractall()

如果您想指定解压后的文件路径与当前目录不同,可以将路径作为参数传递给extractall()方法:
zf.extractall('/path/for/unzipped/files')

4

我缺少的魔法是StringIO; 这里是解决方案...

import base64, StringIO, zipfile

# base64 string from the message
attachment = '...'
attachment = base64.b64decode(attachment)
attachment = StringIO.StringIO(attachment)

zipFile = zipfile.ZipFile(attachment, 'r')

返回结果:

返回一个zipfile.ZipFile实例。


你显然比我快一分钟。嗯,你可以接受我的! :-) - Christian Abbott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接