一个POP3客户端的C#类

** 一个POP3客户端的C#类 **

** 作者: ** ** Bill Dean **

** 关键词 ** ** : ** C#, VB.NET,.NET, INTERNET

** 提交: ** ** ** 2002-02-26 ** **

** 更新: ** ** ** 2003-08-06 ** **

** 摘要: ** ** ** 本文描述的是一个实现了标准 POP3 命令的 C# 类。

· 下载源文件 - 2 Kb

· 下载演示程序 - 5 Kb

· 下载 VB.NET 版本源文件 (Ronny Reinertsen)

示例程序执行结果

简介

读完 Agus Kurniawan 关于用 C# 与 POP3 服务器通讯的 文章 ,我决定如果建立一个 POP3 客户端的类的话,我将走得更远。我决定为每一个标准的 POP3 命令实现方法,每一个方法返回一个包含(相应的) POP3 服务器响应的字符串,某些情况命令无效,那么这些方法检查这些错误并且返回一个错误信息而不是直接发送命令到服务器。随文的源文件包含类的定义和一个使用该类与 POP3 邮件服务器通信的控制台演示程序(前面列出)。

类,方法和属性

随附的源代码包含一个类 : POP3Client

POP3Client 类包含十个公用方法,其中九个代表标准的 POP3 命令:

· DELE,

· LIST,

· NOOP,

· PASS,

· QUIT,

· RETR,

· RSET,

· STAT

· and USER

每一个 "POPmethods" 返回一个字符串,内容为(相应的) POP3 服务器响应结果,或者不恰当的命令导致的错误信息。最后一个公用方法: connect 用来初始化连结。没有实现可选的 POP3 命令: APOP, TOP and UIDL 。

开始工作后不久,我认识到所有 POP3 方法应该按以下四个基本步骤实现:

1. 检查该命令载当前的 POP 状态中是否有效。

2. 如果有效,发送命令到服务器。

3. 读取响应结果。

4. (如果需要)改变 POP 状态。

我决定用一个叫 state 的属性来跟踪 POP 会话的当前状态,数据类型声明为 connect_state 的枚举类型。你们可以看到这些声明在类的定义的顶部。

public enum connect_state {disc,AUTHORIZATION,TRANSACTION,UPDATE};


 


...


 


public connect_state state=connect_state.disc ;

有三个 POP 状态: AUTHORIZATIONTRANSACTION UPDATE 。(完整的 POP3 协议定义请参见 RFC 1725 ) state 属性在建立任何与 POP3 服务器的连接之前被设为 disc (断开),建立连接后变为 AUTHORIZATION 。

I also thought it would be useful to store the user name, password, pop server name and error state (i.e.: did an error occur on the last POP3 command), so I add these properties to the class:

我也认为保存用户名、密码、 POP3 服务器名和错误状态是有用的(例如:判断上一个 POP3 命令是否发生错误),所以我在类中加入了这些属性:

public string user;


public string pwd;


public string pop;


public bool error;

连接服务器( TcpClient )、发送( NetworkStream )和接收数据( StreamReader )的机制直接取自 Agus 的代码。我甚至保留了相同的变量名:

 


_// 借用自 Agus Kurniawan的文章:"Retrieve Mail From a POP3 Server Using C#"_


_//  at http://www.codeproject.com/csharp/popapp.asp _


private TcpClient Server;


private NetworkStream NetStrm;


private StreamReader  RdStrm;


private string Data;


private byte[] szData;


private string CRLF = "\r\n";    

在做任何其他工作之前,我们需要建立道服务器的连接以及取得网络流中的信息。这个在 connect 公用方法中进行。

public string connect()


{


    _// 初始化连接,这段代码是稍作修改“借” 来的_


__


_// 来自Agus Kurniawan在www.codeproject.com的文章_


___// "Retrieve Mail From a POP3 Server Using C#"_


    _// at http://www.codeproject.com/csharp/popapp.asp_


 


_// 用110端口创建服务器_


    Server = new TcpClient(pop,110);                                


        


    try


    {


_ // 初始化_


        NetStrm = Server.GetStream();


        RdStrm= new StreamReader(Server.GetStream());


 


_ //POP会话现在被设为AUTHORIZATION状态_


        state=connect_state.AUTHORIZATION ;


        return(RdStrm.ReadLine ());


    }            


    catch(InvalidOperationException err)


    {


        return("Error: "+err.ToString());


    }


 


}

注意:只要连接一初始化,会话就进入了 AUTHORIZATION 状态。

正如前面所提到的,九个 POP3 方法实质上具有相同的结构。 DELE 方法的源代码展示出该结构。

public string DELE(int msg_number)


{


    string temp;


        


    if (state != connect_state.TRANSACTION )


    {


_ // 只有在POP会话处于TRANSACTION状态时 DELE 命令才为有效_


        temp="Connection state not = TRANSACTION";


    }


    else


    {


        issue_command("DELE " + msg_number.ToString ());


        temp=read_single_line_response();            


    }


    return(temp);


}

首先,我们知道 DELE POP3 命令只在 TRANSACTION 状态有效,所以如果该类不在这个状态,查看记录在 state 属性的值,那么返回一个错误信息而不是发送请求到 POP3 服务器。当处于别的状态时发送 DELE 命令也不会损伤 POP3 服务器,只是会产生内部的错误信息而已。如果你宁可让 POP3 服务器产生状态的错误信息,尽可移出 if 结构只留下 issue_command() 调用。一旦确定 POP 会话处于正确的状态,我们就使用私有方法 issue_command 发送 " DELE " 命令到服务器。 RFC 1725 描述了 DELE 命令返回一个从服务器发回的单行响应,我们用方法 read_single_line_response 来读取。两个方法都相当直接明了,不管是向建立连结的服务器写字符还是从建立连结的服务器读取来自于网络流的字符。因为执行完 DELE 命令后 POP 会话状态仍为 TRANSACTION 状态,我们没必要担心要改变 state 值。 state 改变的例子请参见源代码的 PASS 方法。

private void issue_command(string command)


{


   _// 发送命令到POP服务器,这段代码是稍作修改“借” 来的_


_// 来自Agus Kurniawan在www.codeproject.com的文章_


_// "Retrieve Mail From a POP3 Server Using C#"_


   _// http://www.codeproject.com/csharp/popapp.asp_


    Data= command + CRLF;


    szData = System.Text.Encoding.ASCII.GetBytes(Data.ToCharArray());


    NetStrm.Write(szData,0,szData.Length);


 


}


private string read_single_line_response()


{


_// 读取POP服务器的响应结果,这段代码是稍作修改“借” 来的_


   _// 来自Agus Kurniawan在www.codeproject.com的文章_


_// "Retrieve Mail From a POP3 Server Using C#"_


   _// http://www.codeproject.com/csharp/popapp.asp_


    string temp;


    try


    {


        temp = RdStrm.ReadLine();


        was_pop_error(temp);                


        return(temp);


    }


    catch(InvalidOperationException err)


    {


        return("Error in read_single_line_response(): " + err.ToString ()) ;


    }


 


}

注意,在某些情况,有些 POP3 命令返回多行响应。这里也采用一个名叫 read_multi_line_response 的方法来处理。我前面已经提到过,我认为显示地判断最后一个 POP 命令是否正确执行,或者 POP3 服务器是否返回错误,将是有用的。这里用 was_pop_error 私有方法来检查。

private void was_pop_error(string response)


{


    _// 检查POP服务器发出了响应并认为发生了错误_


  


    if(response.StartsWith ("-"))


    {


        _// 如果第一个字符是"-"_


        _// 那么pop服务器在执行客户端发过去的最后一个命令时发生错误_


        error=true;


    }


    else


    {


        _// 成功_


        error=false;


    }


}


 

使用示例

&

Published At
Categories with Web编程
Tagged with
comments powered by Disqus