Question:
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?
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..
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.
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.