浙林龙哥

   :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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(ByVal timez As StringByRef 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(02)))
            lt 
= lt.Add(TimeSpan.FromMinutes(Convert.ToDouble(timez.Substring(i, 2))))
            lt 
= lt.Subtract(System.TimeZone.CurrentTimeZone.GetUtcOffset(New DateTime(199911)))
            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(02)))
            lt 
= lt.Add(TimeSpan.FromMinutes(Convert.ToDouble(timez.Substring(i, 2))))
            lt 
= lt.Add(System.TimeZone.CurrentTimeZone.GetUtcOffset(New DateTime(199911)))
            dt 
= dt.Add(lt)
        
ElseIf timez.IndexOf("GMT"> -1 Then
            dt 
= dt.Add(System.TimeZone.CurrentTimeZone.GetUtcOffset(New DateTime(199911)))
        
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: attachment;\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, 076);
                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开源邮件组件呢?如果已经有了,请拜托告诉我……

posted on 2008-01-22 09:30  浙林龙哥  阅读(1386)  评论(3编辑  收藏  举报