原文网址: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提供的时间做修正,修正时我使用的是类似下面的代码:
 

 

  1. Public Shared Function fixTimeZone()Function fixTimeZone(ByVal timez As String, ByRef dt As DateTime)   
  2. Dim lt As TimeSpan   
  3. Dim i As Integer   
  4. If timez.IndexOf("+") > -1 Then   
  5. timez = timez.Substring(timez.IndexOf("+") + 1)   
  6. If Char.IsDigit(timez.Chars(2)) Then   
  7. i = 2   
  8. Else   
  9. i = 3   
  10. End If   
  11. lt = TimeSpan.FromHours(Convert.ToDouble(timez.Substring(0, 2)))   
  12. lt = lt.Add(TimeSpan.FromMinutes(Convert.ToDouble(timez.Substring(i, 2))))   
  13. lt = lt.Subtract(System.TimeZone.CurrentTimeZone.GetUtcOffset(New DateTime(1999, 1, 1)))   
  14. dt = dt.Subtract(lt)   
  15. ElseIf timez.IndexOf("-") > -1 Then   
  16. timez = timez.Substring(timez.IndexOf("-") + 1)   
  17. If Char.IsDigit(timez.Chars(2)) Then   
  18. i = 2   
  19. Else   
  20. i = 3   
  21. End If   
  22. lt = TimeSpan.FromHours(Convert.ToDouble(timez.Substring(0, 2)))   
  23. lt = lt.Add(TimeSpan.FromMinutes(Convert.ToDouble(timez.Substring(i, 2))))   
  24. lt = lt.Add(System.TimeZone.CurrentTimeZone.GetUtcOffset(New DateTime(1999, 1, 1)))   
  25. dt = dt.Add(lt)   
  26. ElseIf timez.IndexOf("GMT") > -1 Then   
  27. dt = dt.Add(System.TimeZone.CurrentTimeZone.GetUtcOffset(New DateTime(1999, 1, 1)))   
  28. End If   
  29. End Function  


3。OpenSMTP在发送文件名为中文的附件时候,没有设置文件名的编码信息,造成乱码。
因为添加、发送附件的时候,都是OpenSMTP内部完成的,所以必须修改它的代码,重新compile……需要修改的是Attachment.cs中ToMime这个函数,下面是我修改后的函数内容:
 

 

  1. public String ToMime()   
  2.  {   
  3.  StringBuilder sb=new StringBuilder();   
  4.  if (ContentId!=null)   
  5.  {   
  6.  sb.Append("Content-ID: <" + ContentId + ">\r\n");   
  7.  }   
  8.  String fname;   
  9.  fname="\"=?UTF-8?Q?" + MailEncoder.ConvertToQP(name,"UTF-8") + "?=\"";   
  10.  fname=fname.Replace("\r\n","");   
  11.  fname=fname.Replace("==","=");   
  12.  sb.Append("Content-Type: " + mimeType + ";\r\n");   
  13.  sb.Append(" name=" + fname + "\r\n");   
  14.  sb.Append("Content-Transfer-Encoding: " + encoding + "\r\n");   
  15.  sb.Append("Content-Disposition: attachment;\r\n");   
  16.  sb.Append(" filename=" + fname + "\r\n\r\n");   
  17.    
  18.  FileStream fin = new FileStream(encodedFilePath, FileMode.Open, FileAccess.Read);   
  19.    
  20.  byte[] bin;   
  21.    
  22.  while (fin.Position != fin.Length)   
  23.  {   
  24.  bin = new byte[76];   
  25.  int len = fin.Read(bin, 0, 76);   
  26.  sb.Append(System.Text.Encoding.UTF8.GetString(bin , 0, len)+"\r\n");   
  27.  }   
  28.    
  29.  fin.Close();   
  30.  return sb.ToString();   
  31.  }  

 

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开源邮件组件呢?如果已经有了,请拜托告诉我……