Question

I'm writing some code that writes a zip file to the file system, and then sends that zip file as an attachment in an email. Code used to create the message and attach the file is:

msg = MIMEMultipart()
..
with open( filepath, 'r') as fin:
    data = fin.read()

    part = MIMEBase( 'application', 'octet-stream' )
    part.set_payload( data )
    Encoders.encode_base64( part )

    part.add_header( 'Content-Disposition', 'attachment; filename="%s"' % filename )
    msg.attach( part )
s = smtplib.SMTP( 'mailhost' )                           
s.sendmail( fromAddress, (toAddress,), msg.as_string() ) 
s.close()                                                

Under Linux, everything works fine and I can open the attachment.

Under Windows, the zip file is written correctly to the file system and I can open, however trying to open the zip attachment in the email fails with a corruption error message.

Attaching a csv file (rather than a zip file) to the email works in both Linux & Windows.

Unzipping the attached file in Linux gives:

Archive:  fielname.zip
error [fielname.zip]:  missing 8 bytes in zipfile
  (attempting to process anyway)
retry - request = 0x18446744073709551608
error [fielname.zip]:  attempt to seek before beginning of zipfile
  (please check that you have transferred or created the zipfile in the
  appropriate BINARY mode and that you have compiled UnZip properly)
  (attempting to re-compensate)
 extracting: filenmae.csv   bad CRC 644faeb2  (should be b19cae37)

Python version on Windows is: 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)]

On linux is: 2.6.5 (r265:79063, Mar 26 2010, 10:45:18) \n[GCC 4.4.3]

I think there's an issue with the encoding, but not sure where to start looking.

Was it helpful?

Solution

On Windows, files can be opened in either text mode or binary mode. In text mode, automatic conversion between different kinds of line separators may be performed (e.g. \r\n to \n or vice versa). This will corrupt binary files, so you can avoid it by opening binary files in binary mode.

This line:

with open( filepath, 'r') as fin:

Needs to be:

with open( filepath, 'rb') as fin:
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top