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

时间:2013-10-21 21:22:09

标签: python email zip email-attachments

我需要检索.zip档案,检索.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 个答案:

答案 0 :(得分:4)

你可能正在寻找的是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')

答案 1 :(得分:3)

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实例。