原文网址:http://www.blogwind.com/Wuvist/21079.shtml
感谢hamidsforge, sheda0, unruledboy等牛人的贡献……所以,我们才能够有OpenPOP/OpenSMTP这两个开源.net email组件可以用……以及,由这两个项目合并后成为的Mail.Net。
除了这两个(Mail.Net貌似还没有发布)东西,我实在是不知道还有别的什么.Net POP3 client可以用,.Net内置的smtp功能则实在是太弱了……
最近一直在跟email打交道,用了这两个东西很久……有些经验,不敢独享,所以便发表在这里:
1。OpenPOP在处理基于UTF-8 Q编码的中文信件时会出现乱码,包括标题与信的内容
这应该是内置的MIME Parser的QuotedCoding这个类中的bug,如果不想修改OpenPOP的代码,可以使用类似:
If msg.ContentCharset = "UTF-8" Then
Subject=System.Text.Encoding.UTF8.GetString(System.Text.Encoding.GetEncoding("GB2312").GetBytes(msg.Subject))
End If
的简单代码便可以搞定。
2。OpenPOP的MIME Parser中Message类的Date属性刻意忽略了时区的影响,应该调用DateTimeInfo这个属性获得时区信息,再对Date提供的时间做修正,修正时我使用的是类似下面的代码:
- Public Shared Function fixTimeZone()Function fixTimeZone(ByVal timez As String, ByRef dt As DateTime)
- Dim lt As TimeSpan
- Dim i As Integer
- If timez.IndexOf("+") > -1 Then
- timez = timez.Substring(timez.IndexOf("+") + 1)
- If Char.IsDigit(timez.Chars(2)) Then
- i = 2
- Else
- i = 3
- End If
- lt = TimeSpan.FromHours(Convert.ToDouble(timez.Substring(0, 2)))
- lt = lt.Add(TimeSpan.FromMinutes(Convert.ToDouble(timez.Substring(i, 2))))
- lt = lt.Subtract(System.TimeZone.CurrentTimeZone.GetUtcOffset(New DateTime(1999, 1, 1)))
- dt = dt.Subtract(lt)
- ElseIf timez.IndexOf("-") > -1 Then
- timez = timez.Substring(timez.IndexOf("-") + 1)
- If Char.IsDigit(timez.Chars(2)) Then
- i = 2
- Else
- i = 3
- End If
- lt = TimeSpan.FromHours(Convert.ToDouble(timez.Substring(0, 2)))
- lt = lt.Add(TimeSpan.FromMinutes(Convert.ToDouble(timez.Substring(i, 2))))
- lt = lt.Add(System.TimeZone.CurrentTimeZone.GetUtcOffset(New DateTime(1999, 1, 1)))
- dt = dt.Add(lt)
- ElseIf timez.IndexOf("GMT") > -1 Then
- dt = dt.Add(System.TimeZone.CurrentTimeZone.GetUtcOffset(New DateTime(1999, 1, 1)))
- End If
- End Function
3。OpenSMTP在发送文件名为中文的附件时候,没有设置文件名的编码信息,造成乱码。
因为添加、发送附件的时候,都是OpenSMTP内部完成的,所以必须修改它的代码,重新compile……需要修改的是Attachment.cs中ToMime这个函数,下面是我修改后的函数内容:
- public String ToMime()
- {
- StringBuilder sb=new StringBuilder();
- if (ContentId!=null)
- {
- sb.Append("Content-ID: <" + ContentId + ">\r\n");
- }
- String fname;
- fname="\"=?UTF-8?Q?" + MailEncoder.ConvertToQP(name,"UTF-8") + "?=\"";
- fname=fname.Replace("\r\n","");
- fname=fname.Replace("==","=");
- sb.Append("Content-Type: " + mimeType + ";\r\n");
- sb.Append(" name=" + fname + "\r\n");
- sb.Append("Content-Transfer-Encoding: " + encoding + "\r\n");
- sb.Append("Content-Disposition: p_w_upload;\r\n");
- sb.Append(" filename=" + fname + "\r\n\r\n");
-
- FileStream fin = new FileStream(encodedFilePath, FileMode.Open, FileAccess.Read);
-
- byte[] bin;
-
- while (fin.Position != fin.Length)
- {
- bin = new byte[76];
- int len = fin.Read(bin, 0, 76);
- sb.Append(System.Text.Encoding.UTF8.GetString(bin , 0, len)+"\r\n");
- }
-
- fin.Close();
- return sb.ToString();
- }
OpenPOP跟OpenSMTP分别使用了两个用途一致的Email Parser,不仅是在重复发明轮子,也阻碍了两者的整合,Mail.Net的出现是很应该了……Well……其实,我觉得,Email Parser本身也应该可以做为一个独立的.Net控件,其中对于Email发送时间的时区问题以及各种五花八门的编码,其实都还是有完善的空间的。
而说到完善,即使Mail.Net顺利诞生,它其实也还不足以称为最强……因为它完全没有支持IMAP……大家可以去Google一下IMAP .Net,N多公司在靠这样的组件赚钱,而且还很贵……连php/perl等都有提供对IMAP的支持库,相比之下,.Net的程序员貌似太可怜了……不过,也不是没有人提供开源的.Net IMAP Client,CodeProject上便有一个由Rohit Joshi提供的C# IMAP Client library,虽然这个组件很粗糙,但是,我稍微封装一下便可以使用OpenPOP的Email Parser完成最基本的到不同目录查取新信等功能。
不知道,什么时候,才有一个真正的最强.Net开源邮件组件呢?如果已经有了,请拜托告诉我……