I try to create a zip archive containing all files from a specific directory(and subdirectories) and send it via mail:
#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()
The script seems to work. I recive the mail including the attached zip archive containing all the files. When the script is executed there are 2 possible situations:
Case 1: there is already a zip archive before executing the script, named report.zip (old one from the last run)
Case 2: there is no zip archive before executing the script.
In case 1 everything works fine. The old one is replaced with the newly generated and will then be sent via email.
In case 2 the report.zip is generated and sent via email, but it is invalid. If I try to open it on Windows with 7zip(or the windows onboard tools) it just say "the archive is invalid". I found out that only the report.zip sent via email is broken. If I send the report.zip generated in Case 2 by hand via email I can unzip it and use the files.
I'm a python newbie and to be honest it was hard enough to get to the point where I am at the moment, but solving this problem headaches me. Can anyone explain me what I'm doing wrong ?
You need to close the zip file after adding the files to ensure the archive is complete.
https://docs.python.org/2/library/zipfile.html#zipfile.ZipFile.close
better yet use a with
statement :
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))
Details As I understand them.
1st run:
2nd run: