[VBNET] 繞路解決 MailMessage 在 Header 亂編碼的 bug

大概是美國人寫的吧~ MailMessage 這個類別預設在 Header 是用 QP 編碼,長度長也就算了,最慘的是會把空白編碼編進去…
比如說讀信回條以標準的 eMail 寫法:開發者 <qvb3377@ms5.hinet.net>
 
如果用到中文會出現:

標頭值中找到無效的字元。

描述: 在執行目前 Web 要求的過程中發生未處理的例外情形。請檢閱堆疊追蹤以取得錯誤的詳細資訊,以及在程式碼中產生的位置。
例外詳細資訊: System.FormatException: 標頭值中找到無效的字元。


 
如果用到英文暱稱,空白還會被編進去,變成下圖,且因為空白等被編碼,所以根本無法回傳讀信通知:
 
這在國內外論壇是個難解的狀況,預定在 .Net 4.0 中修復。有些文章說到,用 UTF-8 編碼即可解決,不過 UTF-8 算是語言編碼,傳輸編碼仍然還是 QP 碼,並非是 Base64 ,能處理的最多就是附件改用 Base64 編碼。
 
這部分使用可以先幫 .Net 編碼後再送出,就不會自作孽了~
 
這篇以回條為例:
         ‘ 讀信回條
         If bAskReceipt Then .Headers.Add(“Disposition-Notification-To", rfcMime.EncodeInnerString(strFrom, , False))
 
rfcMime.EncodeInnerString 是我自己寫的類別,程式碼片段如下:

VB2008 – RfcMIMEPackage

Friend Function EncodeInnerString(ByVal strSource As String, Optional ByVal strEncoding As String = Nothing, Optional ByVal bAllEncode As Boolean = True) As String

      Try

           If Not IsNothing(strEncoding) AndAlso strEncoding.Length > 0 Then Encoding = System.Text.Encoding.GetEncoding(strEncoding)

           If Encoding.CodePage <> Encoding.Default.CodePage Then

                 Dim encName As String = Encoding.HeaderName

                 Dim fmtEncode As String = “=?{0}?B?{1}?="

                 Dim strHeaderItem As String = strSource

                 Dim encHeader As New System.Text.StringBuilder

                 Dim ascHeader As String = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(strHeaderItem))

                 Dim strBase64 As String

 

                 If bAllEncode Then

                       strBase64 = System.Convert.ToBase64String(Encoding.GetBytes(strHeaderItem))

                       encHeader.AppendFormat(fmtEncode, encName, strBase64)

                 Else

                       Dim ibl, ubl, sbl, ebl As Integer

                       ubl = strHeaderItem.Length – 1

                       ebl = -1

                       ibl = -1

                       Do

                             ibl += 1

                             If strHeaderItem.Substring(ibl, 1) <> ascHeader.Substring(ibl, 1) Then

                                  sbl = ibl

                                  encHeader.Append(strHeaderItem.Substring(ebl + 1, sbl – ebl – 1))

                                  Do

                                        ibl += 1

                                        If strHeaderItem.Substring(ibl, 1) = ascHeader.Substring(ibl, 1) Then

                                              ebl = ibl – 1

                                              strBase64 = System.Convert.ToBase64String(Encoding.GetBytes(strHeaderItem.Substring(sbl, ebl – sbl + 1)))

                                              encHeader.AppendFormat(fmtEncode, encName, strBase64)

                                              Exit Do

                                        ElseIf ibl = ubl Then

                                              ebl = ibl

                                              strBase64 = System.Convert.ToBase64String(Encoding.GetBytes(strHeaderItem.Substring(sbl, ebl – sbl + 1)))

                                              encHeader.AppendFormat(fmtEncode, encName, strBase64)

                                              Exit Do

                                        End If

                                  Loop Until ibl >= ubl

                             End If

                       Loop Until ibl >= ubl

                       encHeader.Append(strHeaderItem.Substring(ebl + 1))

                 End If

                 Return encHeader.ToString

           Else

                 Return strSource

           End If

      Catch ex As Exception

           Throw ex

      End Try

End Function

 
經過編碼後,可以看見回條變成 開發者
 
所以回條就能正確地丟回給開發者的信箱,確保又能顯示中文,又能回傳。
廣告
Categories: 技術分享 | 發表留言

文章分頁導航

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

在WordPress.com寫網誌.

%d 位部落客按了讚: