www.pudn.com > MailAccess.rar > POPClient.cs
using System;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
namespace OpenPOP.POP3
{
public class POPClient
{
public event EventHandler CommunicationBegan;
public event EventHandler CommunicationOccured;
public event EventHandler CommunicationLost;
public event EventHandler AuthenticationBegan;
public event EventHandler AuthenticationFinished;
public event EventHandler MessageTransferBegan;
public event EventHandler MessageTransferFinished;
internal void OnCommunicationBegan(EventArgs e)
{
if (CommunicationBegan != null)
CommunicationBegan(this, e);
}
internal void OnCommunicationOccured(EventArgs e)
{
if (CommunicationOccured != null)
CommunicationOccured(this, e);
}
internal void OnCommunicationLost(EventArgs e)
{
if (CommunicationLost != null)
CommunicationLost(this, e);
}
internal void OnAuthenticationBegan(EventArgs e)
{
if (AuthenticationBegan != null)
AuthenticationBegan(this, e);
}
internal void OnAuthenticationFinished(EventArgs e)
{
if (AuthenticationFinished != null)
AuthenticationFinished(this, e);
}
internal void OnMessageTransferBegan(EventArgs e)
{
if (MessageTransferBegan != null)
MessageTransferBegan(this, e);
}
internal void OnMessageTransferFinished(EventArgs e)
{
if (MessageTransferFinished != null)
MessageTransferFinished(this, e);
}
private const string RESPONSE_OK="+OK";
//private const string RESPONSE_ERR="-ERR";
private TcpClient clientSocket=null;
private StreamReader reader;
private StreamWriter writer;
private string _Error = "";
private int _receiveTimeOut=60000;
private int _sendTimeOut=60000;
private int _receiveBufferSize=4090;
private int _sendBufferSize=4090;
private string _basePath=null;
private bool _receiveFinish=false;
private bool _autoDecodeMSTNEF=true;
private int _waitForResponseInterval=200;
private int _receiveContentSleepInterval=100;
private string _aPOPTimestamp;
private string _lastCommandResponse;
private bool _connected=true;
public bool Connected
{
get{return _connected;}
}
public string APOPTimestamp
{
get{return _aPOPTimestamp;}
}
public int ReceiveContentSleepInterval
{
get{return _receiveContentSleepInterval;}
set{_receiveContentSleepInterval=value;}
}
public int WaitForResponseInterval
{
get{return _waitForResponseInterval;}
set{_waitForResponseInterval=value;}
}
public bool AutoDecodeMSTNEF
{
get{return _autoDecodeMSTNEF;}
set{_autoDecodeMSTNEF=value;}
}
public string BasePath
{
get{return _basePath;}
set
{
try
{
if(value.EndsWith("\\"))
_basePath=value;
else
_basePath=value+"\\";
}
catch
{
}
}
}
public int ReceiveTimeOut
{
get{return _receiveTimeOut;}
set{_receiveTimeOut=value;}
}
public int SendTimeOut
{
get{return _sendTimeOut;}
set{_sendTimeOut=value;}
}
public int ReceiveBufferSize
{
get{return _receiveBufferSize;}
set{_receiveBufferSize=value;}
}
public int SendBufferSize
{
get{return _sendBufferSize;}
set{_sendBufferSize=value;}
}
private void WaitForResponse(bool blnCondiction, int intInterval)
{
if(intInterval==0)
intInterval=WaitForResponseInterval;
while(!blnCondiction==true)
{
Thread.Sleep(intInterval);
}
}
private void WaitForResponse(ref StreamReader rdReader, int intInterval)
{
if(intInterval==0)
intInterval=WaitForResponseInterval;
while(!rdReader.BaseStream.CanRead)
{
Thread.Sleep(intInterval);
}
}
private void WaitForResponse(ref StreamReader rdReader)
{
DateTime dtStart=DateTime.Now;
TimeSpan tsSpan;
while(!rdReader.BaseStream.CanRead)
{
tsSpan=DateTime.Now.Subtract(dtStart);
if(tsSpan.Milliseconds>_receiveTimeOut)
break;
Thread.Sleep(_waitForResponseInterval);
}
}
private void WaitForResponse(ref StreamWriter wrWriter, int intInterval)
{
if(intInterval==0)
intInterval=WaitForResponseInterval;
while(!wrWriter.BaseStream.CanWrite)
{
Thread.Sleep(intInterval);
}
}
private void ExtractApopTimestamp(string strResponse)
{
Match match = Regex.Match(strResponse, "<.+>");
if (match.Success)
{
_aPOPTimestamp = match.Value;
}
}
private bool IsOkResponse(string strResponse)
{
return (strResponse.Substring(0, 3) == RESPONSE_OK);
}
private string GetResponseContent()
{
return _lastCommandResponse.Substring(3);
}
private bool SendCommand(string strCommand, bool blnSilent)
{
_lastCommandResponse = "";
try
{
if(writer.BaseStream.CanWrite)
{
writer.WriteLine(strCommand);
writer.Flush();
WaitForResponse(ref reader);
_lastCommandResponse = reader.ReadLine();
return IsOkResponse(_lastCommandResponse);
}
else
return false;
}
catch(Exception e)
{
if(!blnSilent)
{
_Error = strCommand + ":" +e.Message;
Utility.LogError(_Error);
}
return false;
}
}
private bool SendCommand(string strCommand)
{
return SendCommand(strCommand,false);
}
private int SendCommandIntResponse(string strCommand)
{
int retVal = 0;
if(SendCommand(strCommand))
{
try
{
retVal = int.Parse(_lastCommandResponse.Split(' ')[1]);
}
catch(Exception e)
{
Utility.LogError(strCommand + ":" + e.Message);
}
}
return retVal;
}
public POPClient()
{
Utility.Log=false;
}
public POPClient(string strHost,int intPort,string strlogin,string strPassword,AuthenticationMethod authenticationMethod)
{
Connect(strHost, intPort);
Authenticate(strlogin,strPassword,authenticationMethod);
}
public void Connect(string strHost,int intPort)
{
OnCommunicationBegan(EventArgs.Empty);
clientSocket=new TcpClient();
clientSocket.ReceiveTimeout=_receiveTimeOut;
clientSocket.SendTimeout=_sendTimeOut;
clientSocket.ReceiveBufferSize=_receiveBufferSize;
clientSocket.SendBufferSize=_sendBufferSize;
try
{
clientSocket.Connect(strHost,intPort);
}
catch(SocketException e)
{
Disconnect();
Utility.LogError("Connect():"+e.Message);
throw new PopServerNotFoundException();
}
reader=new StreamReader(clientSocket.GetStream(),Encoding.Default,true);
writer=new StreamWriter(clientSocket.GetStream());
writer.AutoFlush=true;
WaitForResponse(ref reader,WaitForResponseInterval);
string strResponse=reader.ReadLine();
if(IsOkResponse(strResponse))
{
ExtractApopTimestamp(strResponse);
_connected=true;
OnCommunicationOccured(EventArgs.Empty);
}
else
{
Disconnect();
Utility.LogError("Connect():"+"Error when login, maybe POP3 server not exist");
throw new PopServerNotAvailableException();
}
}
public void Disconnect()
{
try
{
clientSocket.ReceiveTimeout=500;
clientSocket.SendTimeout=500;
SendCommand("QUIT",true);
clientSocket.ReceiveTimeout=_receiveTimeOut;
clientSocket.SendTimeout=_sendTimeOut;
reader.Close();
writer.Close();
clientSocket.GetStream().Close();
clientSocket.Close();
}
catch
{
//Utility.LogError("Disconnect():"+e.Message);
}
finally
{
reader=null;
writer=null;
clientSocket=null;
}
OnCommunicationLost(EventArgs.Empty);
}
~POPClient()
{
Disconnect();
}
public void Authenticate(string strlogin,string strPassword)
{
Authenticate(strlogin,strPassword,AuthenticationMethod.USERPASS);
}
public void Authenticate(string strlogin,string strPassword,AuthenticationMethod authenticationMethod)
{
if(authenticationMethod==AuthenticationMethod.USERPASS)
{
AuthenticateUsingUSER(strlogin,strPassword);
}
else if(authenticationMethod==AuthenticationMethod.APOP)
{
AuthenticateUsingAPOP(strlogin,strPassword);
}
else if(authenticationMethod==AuthenticationMethod.TRYBOTH)
{
try
{
AuthenticateUsingUSER(strlogin,strPassword);
}
catch(InvalidLoginException e)
{
Utility.LogError("Authenticate():"+e.Message);
}
catch(InvalidPasswordException e)
{
Utility.LogError("Authenticate():"+e.Message);
}
catch(Exception e)
{
Utility.LogError("Authenticate():"+e.Message);
AuthenticateUsingAPOP(strlogin,strPassword);
}
}
}
private void AuthenticateUsingUSER(string strlogin,string strPassword)
{
OnAuthenticationBegan(EventArgs.Empty);
if(!SendCommand("USER " + strlogin))
{
Utility.LogError("AuthenticateUsingUSER():wrong user");
throw new InvalidLoginException();
}
WaitForResponse(ref writer,WaitForResponseInterval);
if(!SendCommand("PASS " + strPassword))
{
if(_lastCommandResponse.ToLower().IndexOf("lock")!=-1)
{
Utility.LogError("AuthenticateUsingUSER():maildrop is locked");
throw new PopServerLockException();
}
else
{
Utility.LogError("AuthenticateUsingUSER():wrong password or " + GetResponseContent());
throw new InvalidPasswordException();
}
}
OnAuthenticationFinished(EventArgs.Empty);
}
private void AuthenticateUsingAPOP(string strlogin,string strPassword)
{
OnAuthenticationBegan(EventArgs.Empty);
if(!SendCommand("APOP " + strlogin + " " + MyMD5.GetMD5HashHex(strPassword)))
{
Utility.LogError("AuthenticateUsingAPOP():wrong user or password");
throw new InvalidLoginOrPasswordException();
}
OnAuthenticationFinished(EventArgs.Empty);
}
private string[] GetParameters(string input)
{
string []temp=input.Split(' ');
string []retStringArray=new string[temp.Length-1];
Array.Copy(temp,1,retStringArray,0,temp.Length-1);
return retStringArray;
}
public int GetMessageCount()
{
return SendCommandIntResponse("STAT");
}
public bool DeleteMessage(int intMessageIndex)
{
return SendCommand("DELE " + intMessageIndex.ToString());
}
public bool DeleteAllMessages()
{
int messageCount=GetMessageCount();
for(int messageItem=messageCount;messageItem>0;messageItem--)
{
if (!DeleteMessage(messageItem))
return false;
}
return true;
}
public bool QUIT()
{
return SendCommand("QUIT");
}
public bool NOOP()
{
return SendCommand("NOOP");
}
public bool RSET()
{
return SendCommand("RSET");
}
public bool USER()
{
return SendCommand("USER");
}
public MIMEParser.Message GetMessageHeader(int intMessageNumber)
{
OnMessageTransferBegan(EventArgs.Empty);
MIMEParser.Message msg=FetchMessage("TOP "+intMessageNumber.ToString()+" 0", true);
OnMessageTransferFinished(EventArgs.Empty);
return msg;
}
public string GetMessageUID(int intMessageNumber)
{
string[] strValues=null;
if(SendCommand("UIDL " + intMessageNumber.ToString()))
{
strValues = GetParameters(_lastCommandResponse);
}
return strValues[1];
}
public ArrayList GetMessageUIDs()
{
ArrayList uids=new ArrayList();
if(SendCommand("UIDL"))
{
string strResponse=reader.ReadLine();
while (strResponse!=".")
{
uids.Add(strResponse.Split(' ')[1]);
strResponse=reader.ReadLine();
}
return uids;
}
else
{
return null;
}
}
public ArrayList LIST()
{
ArrayList sizes=new ArrayList();
if(SendCommand("LIST"))
{
string strResponse=reader.ReadLine();
while (strResponse!=".")
{
sizes.Add(int.Parse(strResponse.Split(' ')[1]));
strResponse=reader.ReadLine();
}
return sizes;
}
else
{
return null;
}
}
public int LIST(int intMessageNumber)
{
return SendCommandIntResponse("LIST " + intMessageNumber.ToString());
}
private string ReceiveContent(int intContentLength)
{
string strResponse=null;
StringBuilder builder = new StringBuilder();
WaitForResponse(ref reader,WaitForResponseInterval);
strResponse = reader.ReadLine();
int intLines=0;
int intLen=0;
while (strResponse!=".")
{
builder.Append(strResponse + "\r\n");
intLines+=1;
intLen+=strResponse.Length+"\r\n".Length;
WaitForResponse(ref reader,1);
strResponse = reader.ReadLine();
if((intLines % _receiveContentSleepInterval)==0) //make an interval pause to ensure response from server
Thread.Sleep(1);
}
builder.Append(strResponse+ "\r\n");
return builder.ToString();
}
public MIMEParser.Message GetMessage(int intNumber, bool blnOnlyHeader)
{
OnMessageTransferBegan(EventArgs.Empty);
MIMEParser.Message msg=FetchMessage("RETR " + intNumber.ToString(), blnOnlyHeader);
OnMessageTransferFinished(EventArgs.Empty);
return msg;
}
public MIMEParser.Message FetchMessage(string strCommand, bool blnOnlyHeader)
{
_receiveFinish=false;
if(!SendCommand(strCommand))
return null;
try
{
string receivedContent=ReceiveContent(-1);
MIMEParser.Message msg=new MIMEParser.Message(ref _receiveFinish,_basePath,_autoDecodeMSTNEF,receivedContent,blnOnlyHeader);
WaitForResponse(_receiveFinish,WaitForResponseInterval);
return msg;
}
catch(Exception e)
{
Utility.LogError("FetchMessage():"+e.Message);
return null;
}
}
}
}