C# MailMessage Attachment 中文名附件發郵件-Firefox中文顯示正常,網頁打開郵件附件中文名亂碼

1、故事app

 

      首先經過CDO.Message來獲取郵件EML相關數據:郵件標題、郵件內容、郵件附件、發件人、收件人、CC主要就這麼幾個,其次經過MailMessage來組織郵件經過Python來發送郵件!網站

  

     就這麼簡簡單單的需求!!問題出現了,中文附件名!Web打開始終是亂碼!使用郵件客戶端FireFox是OK的,查看了FireFox源碼發現是亂碼,這點說明FireFox的強大,很是強大!ui

    

Content-Type: application/octet-stream; name=鎶ラ攢鍗昪s.xlsx
Content-Transfer-Encoding: base64
Content-Disposition: attachment

  見圖見圖this

 

 

……編碼

2、折騰中spa

 

     出了問題想辦法,必定要抱着始終相信必定能夠解決的尤爲是搞IT的必定有方法!大事化小,小事化無。先找臥底!第一個想到的即是CDO.Message那就從他下手。最後發現他是平民!3d

 

     先說說走的路,乾貨的路,其餘摸索的方法想了下數數應該有4,5種了:excel

    讀取EML轉換成流,再獲取附件再解碼,發現中文名OKcode

     先看結果orm

    

    再看看代碼

    

public class AttachmentExtractor
    {
        private static int imageCount;

        public static void Method(string path)
        {
            StreamReader reader = null;
            try
            {
                reader = new StreamReader(path);
                string line;
                StringBuilder sb = new StringBuilder();
                while ((line = reader.ReadLine()) != null)
                {
                    sb.Append(line.ToLower());
                    if (line.ToLower().StartsWith("content-disposition:attachment;") || line.ToLower().StartsWith("content-disposition: attachment;")) // found attachment 
                    { 
                        string fileName = GetAttachment(reader, line);
                        fileName = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(fileName.Replace("=?utf-8?B?", "").Replace("?=", ""))); 
                    }
                    if (line.ToLower().StartsWith("content-type:image/")) // found embedded image
                    {
                        ExtractContent(reader, GetImage(reader, line));
                    }
                }
            }
            catch (IOException)
            {
                Console.WriteLine("找不到文件!");
            }
            finally
            {
                if (reader != null) reader.Close();
            }

        }

        private static string GetAttachment(TextReader reader, string line)
        {
            if (!line.Contains("filename"))
            {
                line = reader.ReadLine(); // Thunderbird: filename start at
                //second line
            }
            return GetFilenameNew(reader, line);
        }

        private static string GetImage(TextReader reader, string line)
        {
            if (!line.Contains("name"))
            {
                line = reader.ReadLine(); // Thunderbird: filename start at
                //second line
            }
            if (!line.Contains("name")) // embedded image does not have name
            {
                AdvanceToEmptyLine(reader);

                return "image" + imageCount++ + ".jpg"; // default to jpeg
            }

            return GetFilename(reader, line);
        }

        private static string GetFilename(TextReader reader, string line)
        {
            string filename;
            int filenameStart = line.IndexOf('"') + 1;

            if (filenameStart > 0)
            {
                filename = line.Substring(filenameStart, line.Length -
                filenameStart - 1);
            }
            else // filename does not have quote
            {
                filenameStart = line.IndexOf('=') + 1;
                filename = line.Substring(filenameStart, line.Length -
                filenameStart);
            }

            AdvanceToEmptyLine(reader);

            return filename;
        }

        private static string GetFilenameNew(TextReader reader, string line)
        {
            string filename;
            int filenameStart = line.IndexOf('"') + 1;

            if (filenameStart > 0)
            {
                filename = line.Substring(filenameStart, line.Length -
                filenameStart - 1);
            }
            else // filename does not have quote
            {
                filenameStart = line.IndexOf('=') + 1;
                filename = line.Substring(filenameStart, line.Length -
                filenameStart);
            } 

            return filename;
        }

        private static void AdvanceToEmptyLine(TextReader reader)
        {
            string line;

            while ((line = reader.ReadLine()) != null)
            {
                if (String.IsNullOrEmpty(line)) break;
            }
        }

        private static void ExtractContent(TextReader reader, string filename)
        {
            string line;
            var content = new StringBuilder();

            while ((line = reader.ReadLine()) != null)
            {
                if (String.IsNullOrEmpty(line)) break;

                content.Append(line);
            }

            if (content.Length > 0)
            {
                byte[] buffer = Convert.FromBase64String(content.ToString());
                #region 7.7
                if (!File.Exists(filename))
                {
                    return;
                } 
                #endregion
                using (Stream writer = new FileStream(filename,
                FileMode.Create))
                {
                    writer.Write(buffer, 0, buffer.Length);
                }
            }
        }
    }
public RedEmail()
        {
            InitializeComponent();
            this.txtEmailPath.Text = "C:\\Users\\Administrator\\Desktop\\4a3266e6-23bd-11e5-9703-0050569a7cc2.eml";

            AttachmentExtractor.Method(txtEmailPath.Text);
        }

 

   仔細看完代碼會發現獲取的附件名是編碼過的,須要截取。這個要注意!發現常常不寫寫,不說說都不知道如何表達我那被困的感覺!!!不過!有結果就是勝利!以下:

   可喜的是,我找到了緣由:CDO.Message不是臥底!是個良民!!!他只是一個善良的二道販子!

 

3、看到曙光

    好了,總共就兩人,一個平民了,那麼另外一個必定是臥底咯-MailMessage

    先看勝利的結果,這個喜悅之情那!!

    

   一個是EML裏面的附件-亂碼,一個是經過改良後代碼上傳上去的-OK……(ps 寫博客都不忘給我老婆店鋪作廣告,主要是由於咱們博客園老牛B了,常常會被其餘網站轉載,又不寫轉載信息!

   搞IT的代碼最直接看看代碼,以下:   

                //MemoryStream ms =
                //    new MemoryStream(File.ReadAllBytes(@"C:\\Users\\Administrator\\Desktop\\RDP_需求規格說明書.docx"));
                ////message.Attachments.Add(new System.Net.Mail.Attachment(ms, "RDP_需求規格說明書.docx"));

                //System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
                //System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(ms, ct);
                //attach.ContentDisposition.FileName = "產品經理2.docx";
                 
                //attach.NameEncoding = Encoding.GetEncoding("utf-8"); 
                //      `message.Attachments.Add(attach);

                System.Net.Mail.Attachment attachment = AttachmentHelper.CreateAttachment(@"C:\\Users\\Administrator\\Desktop\\產品經理2.jpg", "產品經理2.jpg", TransferEncoding.Base64);

                message.Attachments.Add(attachment);
                //var attachment = new Attachment(new MemoryStream(File.ReadAllBytes(@"C:\\Users\\Administrator\\Desktop\\產品經理2.jpg")), new System.Net.Mime.ContentType("application/vnd.ms-excel"));
                ////bool flag = File.Exists(@"C:\\Users\\Administrator\\Desktop\\產品經理2.jpg");
                //FileStream fs = new FileStream(@"C:\\Users\\Administrator\\Desktop\\產品經理2.jpg", FileMode.Open, FileAccess.Read);
                //System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
                //System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(fs, ct);
                //attach.ContentDisposition.FileName =  "產品經理2.jpg";
                //fs.Close();
                //message.Attachments.Add(attach);   

看到了麼!註釋的就是實驗的!我說我是折騰了半天解決的!

  好了,揭開神祕的面紗AttachmentHelper  

 public class AttachmentHelper
    {
        public static System.Net.Mail.Attachment CreateAttachment(string attachmentFile, string displayName, TransferEncoding transferEncoding)
        {
            System.Net.Mail.Attachment attachment = new System.Net.Mail.Attachment(attachmentFile);
            attachment.TransferEncoding = transferEncoding;

            string tranferEncodingMarker = String.Empty;
            string encodingMarker = String.Empty;
            int maxChunkLength = 0;

            switch (transferEncoding)
            {
                case TransferEncoding.Base64:
                    tranferEncodingMarker = "B";
                    encodingMarker = "UTF-8";
                    maxChunkLength = 30;
                    break;
                case TransferEncoding.QuotedPrintable:
                    tranferEncodingMarker = "Q";
                    encodingMarker = "ISO-8859-1";
                    maxChunkLength = 76;
                    break;
                default:
                    throw (new ArgumentException(String.Format("The specified TransferEncoding is not supported: {0}", transferEncoding, "transferEncoding")));
            }

            attachment.NameEncoding = Encoding.GetEncoding(encodingMarker);

            string encodingtoken = String.Format("=?{0}?{1}?", encodingMarker, tranferEncodingMarker);
            string softbreak = "?=";
            string encodedAttachmentName = encodingtoken;

            if (attachment.TransferEncoding == TransferEncoding.QuotedPrintable)
                encodedAttachmentName = HttpUtility.UrlEncode(displayName, Encoding.Default).Replace("+", " ").Replace("%", "=");
            else
                encodedAttachmentName = System.Convert.ToBase64String(Encoding.UTF8.GetBytes(displayName));

            encodedAttachmentName = SplitEncodedAttachmentName(encodingtoken, softbreak, maxChunkLength, encodedAttachmentName);
            attachment.Name = encodedAttachmentName;

            return attachment;
        }

        private static string SplitEncodedAttachmentName(string encodingtoken, string softbreak, int maxChunkLength, string encoded)
        {
            int splitLength = maxChunkLength - encodingtoken.Length - (softbreak.Length * 2);
            var parts = SplitByLength(encoded, splitLength);

            string encodedAttachmentName = encodingtoken;

            foreach (var part in parts)
                encodedAttachmentName += part + softbreak + encodingtoken;

            encodedAttachmentName = encodedAttachmentName.Remove(encodedAttachmentName.Length - encodingtoken.Length, encodingtoken.Length);
            return encodedAttachmentName;
        }

        private static IEnumerable<string> SplitByLength(string stringToSplit, int length)
        {
            while (stringToSplit.Length > length)
            {
                yield return stringToSplit.Substring(0, length);
                stringToSplit = stringToSplit.Substring(length);
            }

            if (stringToSplit.Length > 0) yield return stringToSplit;
        }
    }

這個牛B的類不是我寫的!聲明下!我可沒那麼牛×,是哥千辛萬苦+輸入了英文才找到的!更堅決了我要學好英文的夙願!!!!

 

 

4、後話

    好了,能夠安心改改代碼,發佈一個Demo了。

 

    總結下:

     一、要有不放棄不拋棄。

     二、要敢自我調侃的娛樂精神。

     三、關鍵時刻別忘了Google,國外的月亮有時候真的比國內圓!

 

一口氣,好了,我去WC 憋死我了………………

相關文章
相關標籤/搜索