一、故事

首先通过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('"') + ; if (filenameStart > )
{
filename = line.Substring(filenameStart, line.Length -
filenameStart - );
}
else // filename does not have quote
{
filenameStart = line.IndexOf('=') + ;
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('"') + ; if (filenameStart > )
{
filename = line.Substring(filenameStart, line.Length -
filenameStart - );
}
else // filename does not have quote
{
filenameStart = line.IndexOf('=') + ;
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 > )
{
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, , 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 = ; switch (transferEncoding)
{
case TransferEncoding.Base64:
tranferEncodingMarker = "B";
encodingMarker = "UTF-8";
maxChunkLength = ;
break;
case TransferEncoding.QuotedPrintable:
tranferEncodingMarker = "Q";
encodingMarker = "ISO-8859-1";
maxChunkLength = ;
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 * );
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(, length);
stringToSplit = stringToSplit.Substring(length);
} if (stringToSplit.Length > ) yield return stringToSplit;
}
}

这个牛B的类不是我写的!声明下!我可没那么牛×,是哥千辛万苦+输入了英文才找到的!更坚定了我要学好英文的夙愿!!!!

四、后话

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

总结下:

1、要有不放弃不抛弃。

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

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

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

C# MailMessage Attachment 中文名附件发邮件-Firefox中文显示正常,网页打开邮件附件中文名乱码的更多相关文章

  1. C#实现.Net对邮件进行DKIM签名和验证,支持附件,发送邮件签名后直接投递到对方服务器(无需己方邮件服务器)

    项目地址 https://github.com/xiangyuecn/DKIM-Smtp-csharp 主要支持 对邮件进行DKIM签名,支持带附件 对整个邮件内容(.eml文件)的DKIM签名进行验 ...

  2. C#操作EML邮件文件实例(含HTML格式化邮件正文和附件)

    使用QQ邮箱.163邮箱等导出的EML邮件,包含了邮件的发件人.主题.内容.附件等所有信息,该实例就如何解析这些信息,并在编辑后保存做个Demo. 如下图所示,EML文件是编码后的文本文件,可以使用正 ...

  3. openerp 7.0邮件接收中文附件乱码问题解决办法

    openerp 7.0邮件接收中文附件乱码问题解决办法: 修改文件\addons\mail\mail_thread.py #1064 line插入代码: h=email.Header.Header(n ...

  4. centos 邮件服务 腾讯企业邮箱(免费) 使用iRedmail 需要有公网的centos主机 发邮件协议:smtp 端口25 收邮件协议:pop3 端口110 iredmail安装配置 使用邮箱系统 第三十一节课

    centos   邮件服务  腾讯企业邮箱(免费) 使用iRedmail 需要有公网的centos主机 发邮件协议:smtp 端口25  收邮件协议:pop3 端口110  iredmail安装配置 ...

  5. .NET开发邮件发送功能的全面教程(含邮件组件源码)

    今天,给大家分享的是如何在.NET平台中开发“邮件发送”功能.在网上搜的到的各种资料一般都介绍的比较简单,那今天我想比较细的整理介绍下: 1)         邮件基础理论知识 2)         ...

  6. IMAP(Internet Mail Access Protocol,Internet邮件访问协议)以前称作交互邮件访问协议(Interactive Mail Access Protocol)。

    IMAP(Internet Mail Access Protocol,Internet邮件访问协议)以前称作交互邮件访问协议(Interactive Mail Access Protocol).IMA ...

  7. dedecms 5.7文章编辑器附件上传图标不显示

    我最近发现在使用dedecms 5.7文章编辑器附件上传图标不显示了,以前是没有问题的,这个更新系统就出来问题了,下面我来给大家分享此问题解决办法.   问题bug:在dedecms 5.7中发现了一 ...

  8. app在admin中显示成我们想要的中文名

    在django的开发中,很多时候我们希望app在admin中显示成我们想要的中文名,而不是显示默认的app_label名称. 比如我们有一个blog应用,在我们的blog app目录下面,默认会生成一 ...

  9. Centos Firefox中文乱码

    解决CentOS Firefox 中文乱码问题,执行以下命令 Centos 6 # yum -y groupinstall chinese-support 重启电脑即可. Centos 7 yum - ...

随机推荐

  1. ASP.NET MVC学习之过滤器篇(2)

    下面我们继续之前的ASP.NET MVC学习之过滤器篇(1)进行学习. 3.动作过滤器 顾名思义,这个过滤器就是在动作方法调用前与调用后响应的.我们可以在调用前更改实际调用的动作,也可以在动作调用完成 ...

  2. 享受LINQ:判断一组文字是否在字符串中同时出现的最简单方法

    需求是这样的:不允许在一个字符串中同时出现"博", "客", "园", "团", "队"这5个文字. ...

  3. Html5 Canvas transform setTransform

    Html5 Canvas transform就是矩阵变换,一种坐标的变形. 坐标变形的三种方式,平移translate, 缩放scale以及旋转rotate都可以通过transform做到. tran ...

  4. IPv6协议

    IPv4协议仅能提供约2.5亿个IP地址, 即使使用CIDR和NAT等技术进行扩展也无法满足日益增长的需要. IETF于1996年开始研究下一代IP协议IPv6, 并于1998年12月正式公布(RFC ...

  5. VPS CentOS-6 下 LNMP HTTP服务器的搭建

    VPS CentOS-6 下 LNMP HTTP服务器的搭建 前言 恢复更新后的第一篇博文, 前段时间由于各种理由, 把博客更新给宕掉了, 个人独立博客的开发也搁浅了, 现在随着工作的逐步稳定, 决心 ...

  6. Atitit.软件的建模种类and 建模语言选型and UML???

    Atitit.软件的建模种类and  建模语言选型and UML??? 1. 4大的建模种类:ui建模,业务流程建模 , 业务对象建模, 数据库建模 1 2. 文本还是图片化(推荐)的建模 1 3.  ...

  7. atitit.团队建设总结o6o fix

    atitit.团队建设o6o fix #----- 无限放大梦想 2 要有自己的方向...主动添加自己的东东.. 3 有几个tech site,能晓得最新的的知识.. 3 有问题多交流, 3 失败的造 ...

  8. paip.提升性能----硬盘不同转速不同缓存对比转

    paip.提升性能----硬盘不同转速不同缓存对比转 西数 WDC WD2500BEVT-08A23T1 ( 250 GB / 5400 转/分 ) 5400转 8M缓存 单碟250 GB      ...

  9. JNI技术基础(2)——从零开始编写JNI代码

    书接上文: <JNI技术基础(1)——从零开始编写JNI代码> 2.编译源程序HelloWorld.java并生成HelloWorld.class 3.生成头文件HelloWorld.h ...

  10. ASP.NET MVC4+EasyUI+EntityFrameWork5权限管理系统——菜单模块的实现(二)

    ASP.NET MVC4+EasyUI+EntityFrameWork5权限管理系统——数据库的设计(一) 菜单和模块是在同一个表中,采用的是树形结构,模块菜单表结构如下代码: USE [Permis ...