一個POP3客戶端的C#類 (轉)

amyz發表於2007-11-25
一個POP3客戶端的C#類 (轉)[@more@]

一個POP3客戶端的類:namespace prefix = o ns = "urn:schemas--com::office" />

作者: ?id=28276">Bill Dean

關鍵詞: C#, ,.NET, INTERNET

提交: 2002-02-26

-08-06

 

摘要: 本文描述的是一個實現了標準POP3命令的C#類。

 

· /pop3client/pop3client.zip">源 - 2 Kb

· - 5 Kb

· 

示例程式a執行結果 hspace=0 src="/Develop/ArticleImages/20/20575/CSDN_Dev_Image_2003-8-211342380.jpg" align=baseline border=0>

簡介

讀完Agus Kurniawan關於用C#與POP3通訊的,我決定如果建立一個POP3客戶端的類的話,我將走得更遠。我決定為每一個標準的POP3命令實現方法,每一個方法返回一個包含(相應的)POP3伺服器響應的字串,某些情況命令無效,那麼這些方法檢查這些錯誤並且返回一個錯誤資訊而不是直接傳送命令到伺服器。隨文的原始檔包含類的定義和一個使用該類與POP3伺服器通訊的控制檯演示程式(前面列出)。

類,方法和屬性

隨附的包含一個類: POP3Client

  POP3Client類包含十個公用方法,其中九個代表標準的POP3命令:

·  DELE,

·  LIST,

·  N,

·  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狀態:AUTHORIZATIONTRANSACTIONUPDATE。(完整的POP3定義請參見.cmu.edu//rfc1725.html">RFC 1725)state屬性在建立任何與POP3伺服器的連線之前被設為disc(斷開),建立連線後變為AUTHORIZATION。

I also thought it would be useful to store the user name, pass, 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 From a POP3 Server Using C#"


//  at


private TcpClient Server;


private NetworkStream NetStrm;


private StreamReader  RdStrm;


private string Data;


private byte[] szData;


private string CRLF = "rn"; 


  在做任何其他工作之前,我們需要建立道伺服器的連線以及取得流中的資訊。這個在connect公用方法中進行。

public string connect()


{


  // 初始化連線,這段程式碼是稍作修改“借” 來的



//來自Agus Kurniawan在的文章


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


  // at


 


// 用110埠建立伺服器


  Server = new TcpClient(pop,110); 


 


 try


  {


  // 初始化


  NetSt= 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"命令到伺服器。描述了DELE命令返回一個從伺服器發回的單行響應,我們用方法read_single_line_response來讀取。兩個方法都相當直接明瞭,不管是向建立連結的伺服器寫字元還是從建立連結的伺服器讀取來自於網路流的字元。因為執行完DELE命令後POP會話狀態仍為TRANSACTION狀態,我們沒必要擔心要改變state值。state改變的例子請參見原始碼的PASS方法。

private void issue_command(string command)


{


// 傳送命令到POP伺服器,這段程式碼是稍作修改“借” 來的


// 來自Agus Kurniawan在的文章


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


 //


  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在的文章


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


 //


  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;


  }


}


 


使用示例

  POP3協議的細節有點超出本文章的範圍。所以如果你想多瞭解POP3的話,我建議你去RFC 1725,你可以在找到。讓我們簡單的看一下示例程式,以便了解怎樣使用這個類:

static void Main(string[] args)

{


 


 POP3Client.POP3client  Demo = new POP3Client.POP3client();


  Console.WriteLine ("****connecting to server:");


  Console.WriteLine (Demo.connect ("your_pop3_server"));


  Console.WriteLine ("****Issuing USER");


  Console.WriteLine (Demo.USER ("user_id"));


  Console.WriteLine ("****Issuing PASS");


  Console.WriteLine (Demo.PASS ("password"));


  Console.WriteLine ("****Issuing STAT");


  Console.WriteLine (Demo.STAT () );


  Console.WriteLine ("****Issuing LIST");


  Console.WriteLine (Demo.LIST () );


  Console.WriteLine ("****Issuing RETR 700...this will cause the POP3 server to gack a "


  + "hairball since there is no message 700"); 


Console.WriteLine (Demo.RETR (700) ); 


// 如果沒有700訊息,將會導致POP3丟擲一個錯誤


  Console.WriteLine ("****Issuing RETR 7");


  Console.WriteLine (Demo.RETR (7) );


  Console.WriteLine ("****Issuing QUIT");


  Console.WriteLine (Demo.QUIT ());


 


  Console.ReadLine ();


}


  總之,你建立一個POP3Client類的例項,用你的POP3伺服器呼叫connect方法,就可以開始傳送命令了。你將需要呼叫USERPASS方法以成功登陸伺服器,呼叫其他POP3方法之前必須取得有效的登陸資訊。

  我希望你們部分人發覺這篇文章是有用的。我也希望收到反饋或建議。

  請大家明白該程式碼沒有任何的保證,不管是明示還是暗示。該程式碼嚴格的“無保證”提供,僅僅為教育目的。誰使用誰負責。要使用該程式碼,請允諾使用該程式碼帶來的任何損失與作者和Restek無關。

歷史

  • 2003-08-06 —— Ronny Reinertsen好意地把C#版本轉為VB.NET

參看原文:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-984457/,如需轉載,請註明出處,否則將追究法律責任。

相關文章