use*_*810 5 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':
Run Code Online (Sandbox Code Playgroud)
当我第一次开始编写这段代码时,我正在测试一封带有 .csv 附件的电子邮件,并且在访问附件和提取数据时没有问题,但现在我正在处理带有 .zip 的电子邮件(包含以前使用的.csv)我被卡住了。添加...
import zipfile
Run Code Online (Sandbox Code Playgroud)
...但似乎我需要实际将附加的 .zip 保存到文件系统才能使用 zipfile。我宁愿不这样做,并认为(希望)我可以简单地使用......
zipfile.ZipFile(the_base64_string_from_message, 'r')
Run Code Online (Sandbox Code Playgroud)
但那失败了。如何在不在文件系统中创建 .zip 存档的情况下访问存档?此外,也许我什至不应该使用电子邮件模块(仅使用它以便我可以轻松找到附件)???
您可能正在寻找的是 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()
Run Code Online (Sandbox Code Playgroud)
如果要为解压缩文件指定与当前目录不同的路径,可以将其指定为 extractall() 的参数:
zf.extractall('/path/for/unzipped/files')
Run Code Online (Sandbox Code Playgroud)
StringIO 是我所缺少的魔法;这是解决方案...
import base64, StringIO, zipfile
# base64 string from the message
attachment = '...'
attachment = base64.b64decode(attachment)
attachment = StringIO.StringIO(attachment)
zipFile = zipfile.ZipFile(attachment, 'r')
Run Code Online (Sandbox Code Playgroud)
生成一个 zipfile.ZipFile 实例。