none
關於 MailMessage 寄信後部分中文字會出現問號的問題(在Big5編碼下) RRS feed

  • 問題

  •  

    我發現一個存在很久的問題,想問大家是否能解決!

     

    我用 .Net 做發信時,因為客戶要求郵件內容一定要用 Big5 編碼,所以我寄信時會特別指定 Big5 編碼,但是信件寄出去之後「有些中文字」會出現問號,這問題無論是寄到 Gmail 還是 Outlook 都有這個問題存在,我特別寫了個範例程式(如下),你們新增一頁 "0-TEST2.aspx" 並將以下的程式碼複製下來,貼到這一頁 ASP.NET 的 Code Behind 的地方就可以執行了。

     

    記得要改 myToEmail 參數才收的到信喔!如果沒安裝 SMTP Service 的也記得要改 SmtpClient smtp = new SmtpClient("localhost"); 的發信主機位址!


    using System;

    using System.Data;

    using System.Configuration;

    using System.Collections;

    using System.Web;

    using System.Web.Security;

    using System.Web.UI;

    using System.Web.UI.WebControls;

    using System.Web.UI.WebControls.WebParts;

    using System.Web.UI.HtmlControls;

    using System.Net.Mail;

    using System.Text;

     

    public partial class _0_TEST2 : System.Web.UI.Page

    {

        private string myMailEncoding = "BIG5";

        private string myFromEmail = "test@test.com";

        private string myFromName = "多奇-寶貝-寄件者";

     

        private string myToEmail = "test@test.com";

        private string myToName = "多奇-寶貝-收件者";

     

        protected void Page_Load(object sender, EventArgs e)

        {

            MailAddress from = new MailAddress(myFromEmail, myFromName, Encoding.GetEncoding(myMailEncoding));

            MailAddress to = new MailAddress(myToEmail, myToName, Encoding.GetEncoding(myMailEncoding));

     

            MailMessage myMessage = new MailMessage(from, to);

     

            myMessage.Subject = "多奇-寶貝-郵件主旨";

            myMessage.SubjectEncoding = Encoding.GetEncoding(myMailEncoding);

     

            myMessage.Body = "<h1>這是郵件內容</h1>";

            myMessage.BodyEncoding = Encoding.GetEncoding(myMailEncoding);

     

            myMessage.IsBodyHtml = true;

     

            myMessage.Priority = MailPriority.High;

     

            SmtpClient smtp = new SmtpClient("localhost");

     

            try

            {

                smtp.Send(myMessage);

     

                Response.Write(DateTime.Now.ToString() + " 寄信成功");

            }

            catch

            {

                Response.Write(DateTime.Now.ToString() + " 寄信失敗!!!");

            }

        }

    }

     


     

    以下是收到信的結果(有 Outlook 與 Gmail 的畫面)

     

    Outlook: http://home.so-net.net.tw/miniasp/GotMailOutlook.png

     

     

    Gmail: http://home.so-net.net.tw/miniasp/GotMailGmail.png

     

     

     

    就是這個問題困擾著我,奇怪的是我在網路上盡然沒看到有半個人討論這個議題?(可能大家都用Unicode了吧)

     

    麻煩各位了,謝謝!

    2007年4月28日 上午 08:43

解答

  • 我自己用 VBNET ,大部分時間配合 CDO ,有時會自己直接用 TcpClient ,我不用 . Net 包的,目前在 .Net 2.0 之前都還是呼叫 CDO ,所以我自己都直接呼叫 CDO 。

     

    這邊看起來是 5F 沒有正常解碼,也就是 A9_ 跟 C4_ ,有的編碼會編成  =A9=5F 這樣,可能要查 QP 碼編碼規則關於非字母的延伸碼規定有沒有包含符號,我自己寫的 POP3 解 QP 不夠標準,所以可以解,你編輯你的 eml 檔,把 A9_ 改成 A9=5F ,在點兩下那個檔,你就可以發現 OE 可以解。

     

    還有 From / To 後面沒有信箱 test@test.com,不確定是不是你手動刪掉了。

     

    不過我認為這不是你業主要的東西,你業主要求用 big5 碼的前提下,應該是指在信件內使用原始編碼,也就是在信件未指定編碼下,預設採用本機編碼的郵件,因此這種郵件發到其他地區語系的信箱應該會變成亂碼,但反過來可以有效的減少信件流量。

     

    若這屬於你業主要求的內容,內崁編碼、信件本體編碼用 Base64 可讓內容比較小,可以節省流量,不過也比所謂的 big5 大。我在想你業主所謂的 big5 應該是在純 ANSI 下使用,當郵件內無任何編碼資訊可供辨識時,郵件軟體預設會採本機端的地區語系來解碼,也就是控制台、地區及語言選項、進階中非 Unicode 預設的選擇。所以內容應該是:


    ANSI 原始內容
    Delivered-To: xxxxx@gmail.com
    Received'>mailto:xxxxx@gmail.com">xxxxx@gmail.com
    Received: by 10.82.98.14 with SMTP id v14cs28279bub;
            Sat, 28 Apr 2007 01:29:10 -0700 (PDT)
    Received: by 10.35.50.5 with SMTP id c5mr6901624pyk.1177748949304;
            Sat, 28 Apr 2007 01:29:09 -0700 (PDT)
    Return-Path:
    Received: from mail.test.com (mail.test.com [11.22.33.44])
            by mx.google.com with ESMTP id n63si3207565pyh.2007.04.28.01.29.08;
            Sat, 28 Apr 2007 01:29:09 -0700 (PDT)
    Received: from mycomputer ([192.168.0.1]) by mail.test.com with Microsoft SMTPSVC(6.0.3790.1830);
      Sat, 28 Apr 2007 16:29:07 +0800
    mime-version: 1.0
    from: 多奇-寶貝-寄件者
    to: 多奇-寶貝-收件者
    x-priority: 1
    priority: urgent
    importance: high
    date: 28 Apr 2007 16:29:06 +0800
    subject: 多奇-寶貝-郵件主旨
    Return-Path: test@test.com
    Message-ID'>mailto:test@test.com">test@test.com
    Message-ID:
    X-OriginalArrivalTime: 28 Apr 2007 08:29:07.0700 (UTC) FILETIME=[49DDDB40:01C7896F]

    <h1>這是郵件內容</h1>

     

    你可以用筆記本把上面內容存成 xxx.eml 後,直接點兩下,用 OE 看即可。

    一般我們特別要求 big5 是指這種,完全沒有任何編碼或字碼頁的信件。

    2007年4月28日 下午 03:59
    版主

所有回覆

  • 您好:
    由於您的網頁目錄並無 index.html 檔案存在,因此「鎖尼」不允許我們觀看您所貼的圖。
    2007年4月28日 上午 09:00
  • 我不是把路徑都貼上來了嗎?
    2007年4月28日 上午 09:24
  • 你找別台自己連看看,或是把 cookies 清除後試看看,我們都看不到。

     

    我比較期望看到用 OE 收成 eml ,這樣會保留原始信件內容,才比較能除錯,我自己不用 OE 收信,所以我會自己寫 POP3 收成 eml 來看,這樣可以從收到的內容判斷發生什麼問題。

    2007年4月28日 上午 09:33
    版主
  •  

    我把整封郵件的原始碼貼上來了(其實我比較 Prefer 你們 run 一遍發信程式,看你們收到信的結果是不是跟我一樣):

    Delivered-To: xxxxx@gmail.com Received: by 10.82.98.14 with SMTP id v14cs28279bub; Sat, 28 Apr 2007 01:29:10 -0700 (PDT) Received: by 10.35.50.5 with SMTP id c5mr6901624pyk.1177748949304; Sat, 28 Apr 2007 01:29:09 -0700 (PDT) Return-Path: Received: from mail.test.com (mail.test.com [11.22.33.44]) by mx.google.com with ESMTP id n63si3207565pyh.2007.04.28.01.29.08; Sat, 28 Apr 2007 01:29:09 -0700 (PDT) Received: from mycomputer ([192.168.0.1]) by mail.test.com with Microsoft SMTPSVC(6.0.3790.1830); Sat, 28 Apr 2007 16:29:07 +0800 mime-version: 1.0 from: =?big5?Q?=A6h=A9_-=C4_=A8=A9-=B1H=A5=F3=AA=CC?= to: =?big5?Q?=A6h=A9_-=C4_=A8=A9-=A6=AC=A5=F3=AA=CC?= x-priority: 1 priority: urgent importance: high date: 28 Apr 2007 16:29:06 +0800 subject: =?big5?Q?=A6h=A9_-=C4_=A8=A9-=B6l=A5=F3=A5D=A6=AE?= content-type: text/html; charset=big5 content-transfer-encoding: quoted-printable Return-Path: test@test.com Message-ID: X-OriginalArrivalTime: 28 Apr 2007 08:29:07.0700 (UTC) FILETIME=[49DDDB40:01C7896F] <h1>=B3o=ACO=B6l=A5=F3=A4=BA=AEe</h1>
    2007年4月28日 上午 09:41
  • 我可能知道你為什麼看不到圖了!

     

    請你把網址 Copy 下來,貼到另一個 IE 視窗,這樣應該就可以看到了。

     

    so-net 可能又做 HTTP Referer 檢查(Hot-linking).

    2007年4月28日 上午 09:46
  • 我自己用 VBNET ,大部分時間配合 CDO ,有時會自己直接用 TcpClient ,我不用 . Net 包的,目前在 .Net 2.0 之前都還是呼叫 CDO ,所以我自己都直接呼叫 CDO 。

     

    這邊看起來是 5F 沒有正常解碼,也就是 A9_ 跟 C4_ ,有的編碼會編成  =A9=5F 這樣,可能要查 QP 碼編碼規則關於非字母的延伸碼規定有沒有包含符號,我自己寫的 POP3 解 QP 不夠標準,所以可以解,你編輯你的 eml 檔,把 A9_ 改成 A9=5F ,在點兩下那個檔,你就可以發現 OE 可以解。

     

    還有 From / To 後面沒有信箱 test@test.com,不確定是不是你手動刪掉了。

     

    不過我認為這不是你業主要的東西,你業主要求用 big5 碼的前提下,應該是指在信件內使用原始編碼,也就是在信件未指定編碼下,預設採用本機編碼的郵件,因此這種郵件發到其他地區語系的信箱應該會變成亂碼,但反過來可以有效的減少信件流量。

     

    若這屬於你業主要求的內容,內崁編碼、信件本體編碼用 Base64 可讓內容比較小,可以節省流量,不過也比所謂的 big5 大。我在想你業主所謂的 big5 應該是在純 ANSI 下使用,當郵件內無任何編碼資訊可供辨識時,郵件軟體預設會採本機端的地區語系來解碼,也就是控制台、地區及語言選項、進階中非 Unicode 預設的選擇。所以內容應該是:


    ANSI 原始內容
    Delivered-To: xxxxx@gmail.com
    Received'>mailto:xxxxx@gmail.com">xxxxx@gmail.com
    Received: by 10.82.98.14 with SMTP id v14cs28279bub;
            Sat, 28 Apr 2007 01:29:10 -0700 (PDT)
    Received: by 10.35.50.5 with SMTP id c5mr6901624pyk.1177748949304;
            Sat, 28 Apr 2007 01:29:09 -0700 (PDT)
    Return-Path:
    Received: from mail.test.com (mail.test.com [11.22.33.44])
            by mx.google.com with ESMTP id n63si3207565pyh.2007.04.28.01.29.08;
            Sat, 28 Apr 2007 01:29:09 -0700 (PDT)
    Received: from mycomputer ([192.168.0.1]) by mail.test.com with Microsoft SMTPSVC(6.0.3790.1830);
      Sat, 28 Apr 2007 16:29:07 +0800
    mime-version: 1.0
    from: 多奇-寶貝-寄件者
    to: 多奇-寶貝-收件者
    x-priority: 1
    priority: urgent
    importance: high
    date: 28 Apr 2007 16:29:06 +0800
    subject: 多奇-寶貝-郵件主旨
    Return-Path: test@test.com
    Message-ID'>mailto:test@test.com">test@test.com
    Message-ID:
    X-OriginalArrivalTime: 28 Apr 2007 08:29:07.0700 (UTC) FILETIME=[49DDDB40:01C7896F]

    <h1>這是郵件內容</h1>

     

    你可以用筆記本把上面內容存成 xxx.eml 後,直接點兩下,用 OE 看即可。

    一般我們特別要求 big5 是指這種,完全沒有任何編碼或字碼頁的信件。

    2007年4月28日 下午 03:59
    版主
  • 剛剛測了一下,直接叫用 CDO 不指定編碼下,就可以寄出這種 big5 ,有關 CDO 的討論,可以點選上方搜尋找既有討論。

     

    我測的範例如下 (我的 eMail 及相關資訊以手動變更為 xxxx@xxx 、xxx,主要是奇、寶第二碼的問題,所以我沒測太多內容):


    信件原始內容


    Received: from msr34.hinet.net (msr34.hinet.net [168.95.4.134])
     by ms5.hinet.net (8.8.8/8.8.8) with ESMTP id AAA13941
     for <xxxxxxx@xxx.hinet.net>; Sun, 29 Apr 2007 00:04:08 +0800 (CST)
    Received: from xxxxxx (xxx-xxx-xxx-xxx.xxx.hinet.net [xxx.xxx.xxx.xxx])
     by msr34.hinet.net (8.9.3/8.9.3) with SMTP id AAA27240
     for <xxxxxxx@xxx.hinet.net>; Sun, 29 Apr 2007 00:04:07 +0800 (CST)
    Disposition-Notification-To: "奇-寶" <xxxxxxx@xxx.hinet.net>
    thread-index: AceJrtMBLleCUCBySSekwwNHkADvRQ==
    Thread-Topic: Test: 奇-寶
    From: "奇-寶" <xxxxxxx@xxx.hinet.net>
    To: "奇-寶" <xxxxxxx@xxx.hinet.net>
    Subject: Test: 奇-寶
    Date: Sun, 29 Apr 2007 00:03:56 +0800
    Organization: HISDT 風禹科技驗證有限公司,由 user@[::1] 寄信給您。
    Message-ID: <6362C803F8C74D21AB8E983ED38B6FCB@c2e6400>
    X-Mailer: Microsoft CDO for Windows 2000
    Content-Class: urn:content-classes:message
    Importance: normal
    Priority: normal
    X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.3959
    Content-Length: 58
    Status: RO

    <h1>奇-寶</h1>
    --
    風禹科技驗證有限公司 Web Mail Reader

     

    2007年4月28日 下午 04:13
    版主
  • 多謝回覆!

     

    看樣子 System.Net.Mail 是英雄無用武之地了 -_-''

     

    我剛還有用 Reflector 分析 System.Net.Mail  下的好幾個 Class,發現 .Net 只會接受幾種 Unicode 的字集用 Base64,其他全部都用 Quoted-Printable 編碼,而且好像也沒辦法修改,因為那幾個 Class 都是 internal class,沒辦法繼承或 overwrite 的樣子,不知道微軟會不會在下一版或 Patch 開放讓我們選擇要用 Base64 還是 QP。

     

    另外,我不知道 .Net 怎麼呼叫 CDO ,你可以給我一個簡單的範例嗎?

    2007年4月28日 下午 06:59
  • 前面不是有說嗎:

    有關 CDO 的討論,可以點選上方搜尋找既有討論。

    http://forums.microsoft.com/MSDN-CHT/Search/Search.aspx?words=CDO&SiteID=14&searchscope=allforums

    2007年4月29日 上午 12:58
    版主