Богатые символы электронных писем неправильно переводятся при чтении из базы данных с использованием MimeKit - PullRequest
1 голос
/ 24 апреля 2019

У меня есть служба Windows, написанная на VB.Net, которая загружает электронные письма в объекты MimeMessage, удаляет их вложения, а затем записывает остатки электронной почты в базу данных SQL Server.Отдельное приложение ASP.Net (использующее VB.Net) считывает электронную почту обратно в объект MimeMessage и возвращает ее пользователю по запросу.

Во время этого процесса происходит что-то, что приводит к появлению странных символов в выходных данных.

Этот вопрос ( Кодировка содержимого с использованием MimeKit / MailKit ) показался многообещающим, но изменение кодировки символов с ASCII на UTF8 и т. Д. Не решило его.

Вот код, который сохраняет электронное письмо в базе данных:

Sub ImportEmail(exConnectionString As String)
    Dim oClient As New Pop3Client()
    ' … email connection code removed …
    Dim message = oClient.GetMessage(0)
    Dim strippedMessage As MimeMessage = message
    ' … code to remove attachments removed …
    Dim mem As New MemoryStream
    strippedMessage.WriteTo(mem)
    Dim bytes = mem.ToArray
    Dim con As New SqlConnection(exConnectionString)
    con.Open()
    Dim com As New SqlCommand("INSERT INTO Emails (Body) VALUES (@RawDocument)", con)
    com.CommandType = CommandType.Text
    com.Parameters.AddWithValue("@RawDocument", bytes)
    com.ExecuteNonQuery()
    con.Close()
End Sub

А вот код ASP.Net, чтобы прочитать его обратно пользователю:


Private Sub OutputEmail(exConnectionString As String)
    Dim BlobString As String = ""
    Dim Sql As String = "SELECT Body FROM Emails WHERE Id = @id"    
    Dim com As New SqlClient.SqlCommand(Sql)
    com.CommandType = CommandType.Text
    com.Parameters.AddWithValue("@id", ViewState("email_id")) 

    Dim con As New SqlConnection(exConnectionString)
    con.Open()
    com.Connection = con
    Dim da As New SqlClient.SqlDataAdapter(com)
    Dim dt As New DataTable()
    da.Fill(dt)
    con.Close()

    If dt.Rows.Count > 0 Then
        Dim Row = dt.Rows(0)
        BlobString = Row(0).ToString()

        Dim MemStream As MemoryStream = GetMemoryStreamFromASCIIEncodedString(BlobString)
        Dim message As MimeMessage = MimeMessage.Load(MemStream)

        BodyBuilder.HtmlBody = message.HtmlBody
        BodyBuilder.TextBody = message.TextBody
        message.Body = BodyBuilder.ToMessageBody()

        Response.ContentType = "message/rfc822"
        Response.AddHeader("Content-Disposition", "attachment;filename=""" & Left(message.Subject, 35) & ".eml""")
        Response.Write(message)
        Response.End()
    End If
End Sub

Private Function GetMemoryStreamFromASCIIEncodedString(ByVal BlobString As String) As MemoryStream
    Dim BlobStream As Byte() = Encoding.ASCII.GetBytes(BlobString) ' **
    Dim MemStream As MemoryStream = New MemoryStream()
    MemStream.Write(BlobStream, 0, BlobStream.Length)
    MemStream.Position = 0
    Return MemStream
End Function

Например, предположим, что приведенный ниже текст отображается в исходном электронном письме:

“So long and thanks for all the fish” (fancy quotes)

При обратном чтении он выглядит следующим образом:

†So long and thanks for all the fishâ€

Другие замены символов следующие:

- (длинная черта) становится 10 -

• (пули) становятся  •

1 Ответ

1 голос
/ 26 апреля 2019

Проблема со следующим фрагментом:

If dt.Rows.Count > 0 Then
    Dim Row = dt.Rows(0)
    BlobString = Row(0).ToString() ' <-- the ToString() is the problem

    Dim MemStream As MemoryStream = GetMemoryStreamFromASCIIEncodedString(BlobString)
    Dim message As MimeMessage = MimeMessage.Load(MemStream)

Чтобы исправить повреждение данных, вам нужно сделать следующее:

If dt.Rows.Count > 0 Then
    Dim Row = dt.Rows(0)
    Dim BlobString as Byte() = Row(0)

    Dim MemStream As MemoryStream = new MemoryStream (BlobString, False)
    Dim message As MimeMessage = MimeMessage.Load(MemStream)

Вы также можете избавиться от функции GetMemoryStreamFromASCIIEncodedString.

(Примечание: я не знаю VB.NET, так что я просто догадываюсь о синтаксисе, но он должен быть очень близок к правильному)

...