2013年7月11日木曜日

C#のsmtpclientでメール送信すると subjectで文字化けする

C#のsmtpclientでメール送信すると subjectで文字化けする。

どうも.NET4.0から、仕様が変わったそうです。

iso-2022-jpだと、smtpclient側で、自動エンコード を行うのが原因だとか。

http://blogs.technet.com/b/exchangeteamjp/archive/2012/10/05/3524293.aspx

今回は System.Net.Mail を利用してメールを送信する際に .NET Framework 4.5 で一部実装が変更されたことで発生する問題と対処方法についてご紹介いたします。
System.Net.Mail の MailMessage では SubjectEncoding を設定することで Subject で使用される文字コードを指定することができますが、SubjectEncoding に "iso-2022-jp" を設定した場合には Q エンコードが使用されてメールが送信されます。
Q エンコードに対応しているクライアントでは特に問題とはなりませんが、Q エンコードに対応していない一部の携帯端末やメーラーでは Subject が文字化けする問題が多数確認され、.NET Framework 4 までは以下のように SubjectEncoding は指定しないで Subject に B エンコードでエンコードした文字列を設定することで対応することができました。
    using System.Net.Mail
    using System.Text.Encoding
    public static void SendMessage(string server)
    {
        string from    = "userA@contoso.com";
        string to      = "userB@contoso.com";
        string subject = "テスト メッセージ";
        string body    = "メッセージの本文"
        MailMessage msg = new MailMessage(from, to);
        msg.Subject = EncodeMailHeader(subject);
        msg.Body = body;
        // SubjectEncoding は指定しない
        // msg.SubjectEncoding = Encoding.GetEncoding("iso-2022-jp");
        msg.BodyEncoding = Encoding.GetEncoding("iso-2022-jp");
        SmtpClient sc = new SmtpClient(server);
        sc.Send(msg);
    }
    // 「=?iso-2022-jp?B?<エンコード文字列>?=」形式に変換
    public static string EncodeMailHeader(string subject)
    {
        Encoding enc = Encoding.GetEncoding("iso-2022-jp");
        string strBase64 = Convert.ToBase64String(enc.GetBytes(subject));
        return string.Format("=?{0}?B?{1}?=", "iso-2022-jp", strBase64);
    }
.NET Framework 4.5 の System.Net.Mail では Subject にエンコードされた文字列を指定してもクラス内部でデコードした値を内部で保持するように一部実装が変更されているため、上記のコードでも Q エンコードが使用されてメールが送信される結果となります。
なお、.NET Framework 4.5 では以下のように二重にエンコードした文字列を Subject に設定することで以前と同様に日本語の件名を B エンコードを使用してメールを送信することができます。
    using System.Net.Mail
    using System.Text.Encoding
    public static void SendMessage(string server)
    {
        string from    = "userA@contoso.com";
        string to      = "userB@contoso.com";
        string subject = "テスト メッセージ";
        string body    = "メッセージの本文"
        MailMessage msg = new MailMessage(from, to);
        msg.Subject = EncodeMailHeader(EncodeMailHeader(subject));
        msg.Body = body;
        // SubjectEncoding は指定しない
        // msg.SubjectEncoding = Encoding.GetEncoding("iso-2022-jp");
        msg.BodyEncoding = Encoding.GetEncoding("iso-2022-jp");
        SmtpClient sc = new SmtpClient(server);
        sc.Send(msg);
    }
    // 「=?iso-2022-jp?B?<エンコード文字列>?=」形式に変換
    public static string EncodeMailHeader(string subject)
    {
        Encoding enc = Encoding.GetEncoding("iso-2022-jp");
        string strBase64 = Convert.ToBase64String(enc.GetBytes(subject));
        return string.Format("=?{0}?B?{1}?=", "iso-2022-jp", strBase64);
    }

0 件のコメント:

コメントを投稿