Archived Forum Post

Index of archived forum posts

Question:

IMAP/Mail Message Attachment Corruption

Oct 10 '12 at 12:27

We have been using your Chilkat .NET components for a while now and we’ve recently uncovered what we feel is a bug in the IMAP/Email piece. When returning attachments we received complaints about corruption of .xlsx files. While researching this we have determined that an extra zero byte is always appended to the end of the byte array rendering the file as corrupted when opening it.

I have screen shots of the files being viewed in a hex editor that show the extra byte.

Here is the code we use to write the data to the file system I’m pretty sure it was lifted from your examples:

For Each att As Attachment In msg.Attachments
     Dim fData As Byte() = New Byte(Convert.ToInt32(att.ContentStream.Length)) {}
     Dim strm As System.IO.Stream = att.ContentStream
     strm.Read(fData, 0, Convert.ToInt32(att.ContentStream.Length))
     strm.Close()
     '------------------------------------------------------------------------
     '------ uncomment this code for file system attachments -----------------
     '------------------------------------------------------------------------
     Dim fs As New FileStream(dirToCreate & "\" & pos & ReturnValidFileName(att.Name), FileMode.OpenOrCreate, FileAccess.ReadWrite)
     fs.Write(fData, 0, fData.Length)
     fs.Close()
     fs = Nothing
     '------------------------------------------------------------------------

     pos += 1

Next

The .xlsx files seem to be the only ones that complain about it. All other programs seem to ignore the extra byte.

Any ideas?


Answer

The code snippet you posted does not appear to be Chilkat code. It appears to be using an email object that is NOT the Chilkat email object..


Answer

Maybe I should explain what we do a little better.

I work with a software package called WebSPOC. It's an ITIL package. We use the Chilkat components to read mail from a box and generate tickets. The service reads from the email box and databases the email. A process then looks for unprocessed records and creates them as tickets in the system. Each ticket can have it's own attachments that we pull out of the Chilkat object and put in the database along side the email data.

When the email is processed, we create a .NET MailMessage from the databased email, we pass that mail message into a processing routine to create a ticket. All attachments in the email are attached to the ticket. These files/attachments are stored on the file system of the web server.

The code above is what writes the data from the database to the file system.

The code that puts the attachments in the database is this:

If eMailID > 0 AndAlso MailMsg.NumAttachments > 0 Then
     For i As Integer = 0 To MailMsg.NumAttachments - 1

          Dim attName As String = MailMsg.GetAttachmentFilename(i)
          attName = ReturnValidFileName(attName)
          Dim attType As String = MailMsg.GetAttachmentContentType(i)
          Dim attSize As String = MailMsg.GetAttachmentSize(i)
          Dim attData As Byte() = MailMsg.GetAttachmentData(i)

          Using con As New SqlConnection(ReturnConString)
               Try
                    con.Open()
               Catch ex As Exception
                    logErrors(imap, "Error opening db connection (attachments). Error description: " & ex.Message & " - " & ex.StackTrace, True)
               End Try

               Dim qry As String = _
                            "INSERT INTO TicketEmailAttachments " & _
                            "(TicketEmailID,FileName,FileType,FileSize,FileData) " & _
                            "VALUES " & _
                            "(@TicketEmailID,@FileName,@FileType,@FileSize,@FileData)"

               Using cmd As New SqlCommand(qry, con)
                    cmd.Parameters.AddWithValue("@TicketEmailID", eMailID)
                    cmd.Parameters.AddWithValue("@FileName", attName.Replace("&", ""))
                    cmd.Parameters.AddWithValue("@FileType", attType)
                    cmd.Parameters.AddWithValue("@FileSize", attSize)
                    cmd.Parameters.AddWithValue("@FileData", attData)
                    Try
                         cmd.ExecuteNonQuery()
                    Catch ex As Exception
                         Dim msgInfo As String = ""
                         msgInfo = "Message received on " & MailMsg.EmailDate & " from '" & sSender & "'. Message ID: " & MailMsg.Uidl

                         'log error
                         logErrors(imap, "Error during inserts of mail attachments. Message info: " & _
                                              msgInfo & ". Error description: " & ex.Message & " - " & ex.StackTrace, True)
                     End Try
                End Using

                If con.State = ConnectionState.Open Then
                     con.Close()
                End If
           End Using
      Next
 End If

The data in the database has been found to have the extra byte. That's why I provided the method by which we write the file to the file system.


Answer

1) Make sure you're using the very latest version (v9.3.2). If you weren't, then re-test using the latest version.

2) After the following line of code:

Dim attData As Byte() = MailMsg.GetAttachmentData(i)
Save the contents of attData to a file by calling System.IO.File.WriteAllBytes. Verify that the extra byte is in the file. If it is NOT, then the error is not w/ Chilkat and the error is introduced somewhere in your application code.

3) If the System.IO.File.WriteAllBytes produces a file w/ the extra byte, then you'll want to see if attachment itself actually contains the extra byte. To check on this, save the MailMsg to a .eml by calling MailMsg.SaveEml, open it in Mozilla Thunderbird, and the save the attachments to files using Thunderbird. Check to see if the extra bytes is present in the attachments saved by Thunderbird. If so, then the "extra byte" is already in the email.