通过电子邮件发送的 Zip 在第一次尝试时无效

Posted

技术标签:

【中文标题】通过电子邮件发送的 Zip 在第一次尝试时无效【英文标题】:Zip sent via email is invalid on first attempt 【发布时间】:2015-09-09 11:07:24 【问题描述】:

我尝试创建一个包含来自特定目录(和子目录)的所有文件的 zip 存档并通过邮件发送:

#Create archive containing all files from directory "reports/"
zipf = zipfile.ZipFile('reports.zip', 'w')
for root, dirs, files in os.walk('reports/'):
for file in files:
    zipf.write(os.path.join(root, file))

#Create email
msg = MIMEMultipart()
msg["From"] = emailfrom
msg["To"] = emailto
msg["Subject"] = "Monatliche Reports - Verrechnung an Kunden"

#Attach report.zip to email
fp = open(fileToSend, "rb")
attachment = MIMEBase('application', 'zip')
attachment.set_payload(fp.read())
fp.close()
encoders.encode_base64(attachment)
attachment.add_header("Content-Disposition", "attachment",
filename=fileToSend)
msg.attach(attachment)

#Send email via localhost smtp-server
server = smtplib.SMTP("localhost")
server.sendmail(emailfrom, emailto, msg.as_string())
server.quit()

脚本似乎有效。我收到了包含所有文件的附加 zip 存档的邮件。脚本执行时有两种可能的情况:

案例 1:在执行脚本之前已经有一个 zip 存档,名为 report.zip(上次运行的旧文件)

案例2:执行脚本前没有zip压缩包。

如果情况 1 一切正常。旧的替换为新生成的,然后将通过电子邮件发送。

在案例 2 中,report.zip 生成并通过电子邮件发送,但它是无效的。如果我尝试使用 7zip(或 Windows 板载工具)在 Windows 上打开它,它只会说“存档无效”。我发现只有通过电子邮件发送的 report.zip 被破坏了。如果我通过电子邮件手动发送案例 2 中生成的 report.zip,我可以将其解压缩并使用这些文件。

我是一个 python 新手,老实说,要达到我现在的位置已经够难了,但是解决这个问题让我很头疼。谁能解释一下我做错了什么?

【问题讨论】:

【参考方案1】:

您需要在添加文件后关闭 zip 文件以确保存档完整。

https://docs.python.org/2/library/zipfile.html#zipfile.ZipFile.close

最好使用with 声明:

with zipfile.ZipFile('reports.zip', 'w') as zipf: 
   for root, dirs, files in os.walk('reports/'):
      for file in files:
         zipf.write(os.path.join(root, file))    

详情 据我了解。

第一次运行

zipfile 创建文件描述符(在内存占位符中)和包清单(要添加的文件) zipfile.write() 将文件压缩到文件描述符中,并将文件添加到清单中 msg.attach() 文件尚未刷新,因此内存中的位置没有任何内容。 --结束脚本文件描述符清理将文件描述符刷新到磁盘。 (reports.zip 存在但不完整/无效)

第二次运行

zipfile 创建一个 fd 和 manifest zipfile.write() 将文件压缩到 fd 并将文件添加到清单中 msg.attach() 文件上次刷新但仍不完整附加无效文件

【讨论】:

Thx 这确实解决了问题,但我仍然对它在我的代码的第二次尝试中起作用感到困惑。为什么存档在第 2 次运行时要关闭,而在第一次尝试时保持打开状态? 因为当脚本完成时解释器会关闭文件。在第二次尝试时,它将获得(部分)文件。 zip 文件在第一遍结束时仍处于打开状态并准备好接收更多文件,这将是一个不完整的包。 所以第一次尝试它是一个不完整的包,因为当脚本完成执行时文件仍然打开?我看不出尝试 2 的区别。发生的情况完全相同,文件在脚本完成时也是打开的。非常感谢您的解释。【参考方案2】:

试试这个:

import yagmail
me = 'me@gmail.com'
yag = yagmail.SMTP(emailfrom, 'mypassword') 
yag.send(emailto,  "Monatliche Reports - Verrechnung an Kunden", 'reports.zip')

您可能必须使用 pip install yagmail 安装 yagmail

免责声明:我是 yagmail 的开发者,该软件包试图让发送电子邮件(带或不带附件)变得容易。

【讨论】:

看起来很有趣,我会试一试。谢谢你的提示

以上是关于通过电子邮件发送的 Zip 在第一次尝试时无效的主要内容,如果未能解决你的问题,请参考以下文章

将 zip 文件添加到电子邮件中

联系表格发送时电子邮件无效

在磁盘或 RAM 不足时发送电子邮件警报

无法通过 nodemailer 发送电子邮件 |发件人“电子邮件 id@gmail.com>”无效

MIME 消息无效 AWS SES 由于 MIME 消息无效而拒绝它

让 nodemailer 使用不同的 gmail 帐户发送电子邮件