• C# MailMessage Attachment 中文名附件发邮件-Firefox中文显示正常,网页打开邮件附件中文名乱码


    一、故事

          首先通过CDO.Message来获取邮件EML相关数据:邮件标题、邮件内容、邮件附件、发件人、收件人、CC主要就这么几个,其次通过MailMessage来组织邮件通过Python来发送邮件!

      

         就这么简简单单的需求!!问题出现了,中文附件名!Web打开始终是乱码!使用邮件客户端FireFox是OK的,查看了FireFox源码发现是乱码,这点说明FireFox的强大,非常强大!

        

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

      见图见图

     

    ……

    二、折腾中

         出了问题想办法,一定要抱着始终相信一定可以解决的尤其是搞IT的一定有方法!大事化小,小事化无。先找卧底!第一个想到的便是CDO.Message那就从他下手。最后发现他是平民!

         先说说走的路,干货的路,其他摸索的方法想了下数数应该有4,5种了:

        读取EML转换成流,再获取附件再解码,发现中文名OK

         先看结果

        

        再看看代码

        

    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不是卧底!是个良民!!!他只是一个善良的二道贩子!

    三、看到曙光

        好了,总共就两人,一个平民了,那么另一个一定是卧底咯-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的类不是我写的!声明下!我可没那么牛×,是哥千辛万苦+输入了英文才找到的!更坚定了我要学好英文的夙愿!!!!

    四、后话

        好了,可以安心改改代码,发布一个Demo了。

        总结下:

         1、要有不放弃不抛弃。

         2、要敢自我调侃的娱乐精神。

         3、关键时刻别忘了Google,国外的月亮有时候真的比国内圆!

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

  • 相关阅读:
    cross apply / outer apply
    查看锁表
    常用的一些占位符
    如何将法向量转换到世界空间
    Essential Mathematics for Games and Interactive Applications
    下一本要看的书
    第五章第五节 四元数
    向量坐标转换、旋转矩阵以及视图转换
    怪诞行为学摘录
    unity3d发布apk资源打包和访问方式
  • 原文地址:https://www.cnblogs.com/PEPE/p/4632540.html
Copyright © 2020-2023  润新知