• Embed Doc
  • Readcast
  • Collections
  • CommentGo Back
Download
 
Library 
tutorials & articles
 How to POP3 in C#
Introduction
This is the second in a series of articles on Internet programming with Microsoft's new C# programming language. Inthe first article, I wrote a simple SMTP class. In this article, I'm going to write a simple POP3 class. The SMTP classthat I wrote was not very useful, except maybe as an exercise, as there already exists a similar SMTP class in the
Web.Mail
namespace of the .NET framework called
SmtpMail
. Our POP3 class in this article will be a little moreuseful as it doesn't already exist in the .NET framework. I have encountered many POP3 C# classes in my searchesof the Internet and most were sufficient to begin programming email clients.
Getting Started
I usually begin writing new classes by introducing an exception class that I can use to throw and catch all exceptionsof the class.I will not explain the exception class, but rather I expect the reader have enough expertise with C# to understand thisexception class before reading the rest of the article.Next I created a small class that defines a POP3 message.When you retrieve lists of POP3 messages from a POP3 server, the list includes a message number and number ofbytes. You can then use the message number to retrieve the message content. You'll see this later when we defineour List and Retrieve methods. We derive our Pop3 class from the
System. Net.Sockets.TcpClient
class inthe .NET framework.The
TcpClient
class and the other classes in the
System.Net.Sockets
namespace of the .NET framework aregreat encapsulations of the familiar function-oriented socket library.
Connecting and Disconnecting
The first method of our Pop3 class is the Connect method. This method takes a server name, username andpassword parameter to connect to a remote (sometimes local) POP3 server.We begin by calling the
TcpClient.Connect
method passing the server name and the 110 port. The 110 portnumber is the well known port number for POP3 operations. What that means is that POP3 servers by default shouldlisten for connections on port 110. When the POP3 server connects to a client, it should immediately respond with the
+OK
acknowledgement message. Next we send two messages,
USER
and
PASS
, back to the server. The POP3 servershould acknowledge a successful login by acknowledging both messages. If the POP3 server returns anything but
public class Pop3Exception : System. ApplicationException{  public Pop3Exception( string str)    : base( str)  {  }}public class Pop3Message{ public long number; publiclong bytes;   public bool retrieved;  public string message;}public class Pop3 : System.Net.Sockets.TcpClient {public void Connect(string server, string username, string password){  string message;  string response;  Connect(server, 110);  response = Response();  if (response.Substring(0, 3) != "+OK")  {    throw new Pop3Exception(response);  }  message = "USER " + username + "\r\n";  Write(message);  response = Response();  if (response.Substring(0, 3) != "+OK")  {    throw new Pop3Exception(response);  }  message = "PASS " + password + "\r\n";  Write(message);  response = Response();  if (response.Substring(0, 3) != "+OK")  {    throw new Pop3Exception(response);  }}
By
Randy Charles Morin
, published on 01 Oct 2003
Comments (5)
PDF
Join us Sign in Chelmsford 
Want to stay in touch with what's going on? Follow us on twitter 
 
 
+OK
, then the message will contain the reason for the failure. In the advent of a failure, I attach that failure message toour exception class and throw it back to the client. It should be noted that some POP3 servers don't requireauthentication and may reject the calls to
USER
and
PASS
. I haven't
encountered such a POP3 server, but the protocolallows it. In those cases, you'll have to slightly modify the class to make things work.Any use of our Pop3 class should begin with a call to
Connect
and end with a class to
Disconnect
.
The
Disconnect
method sends a
QUIT
message to the POP3 server.
Retrieving Messages
Between the calls to
Connect
and
Disconnect
,
the client may call three other methods,
List
,
Retrieve
and
Delete
,
any number of times. The client will usually begin by calling our
List
method to retrieve an array ofmessages that are queued on the POP3 server.After sending the
LIST
message to the POP3 server, the server will respond with a
+OK
acknowledgement, followedby several lines representing one message each and finally by a line with a single period indicating the end of themessages. Each message line has two numbers, the first indicating the unique number of the message and thesecond indicating the message size in bytes.Our
List
method will return a list of
Pop3Message
objects. The objects will only contain the message number andsize of each message. In order to retrieve the full message, you can pass the message object to the
Retrieve
 method. The
Retrieve
method will then respond with another
Pop3Message
containing the message content.To retrieve a message from a POP3 server, we send a
RETR
message with the unique message number. The server
public void Disconnect(){  string message;  string response;  message = "QUIT\r\n";  Write(message);  response = Response();  if (response.Substring(0, 3) != "+OK")  {    throw new Pop3Exception(response);  }}public ArrayList List(){  string message;  string response;  ArrayList retval = new ArrayList();  message = "LIST\r\n";  Write(message);  response = Response();  if (response.Substring(0, 3) != "+OK")  {    throw new Pop3Exception(response);  }  while (true)  {    response = Response();    if (response == ".\r\n")    {      return retval;    }    else    {      Pop3Message msg = new Pop3Message();      char[] seps = { ' ' };      string[] values = response.Split(seps);      msg.number = Int32.Parse(values[0]);      msg.bytes = Int32.Parse(values[1]);      msg.retrieved = false;      retval.Add(msg);      continue;    }  }}public Pop3Message Retrieve(Pop3Message rhs){  string message;  string response;  Pop3Message msg = new Pop3Message();  msg.bytes = rhs.bytes;  msg.number = rhs.number;  message = "RETR " + rhs.number + "\r\n";  Write(message);  response = Response();  if (response.Substring(0, 3) != "+OK")  {    throw new Pop3Exception(response);  }  msg.retrieved = true;  while (true)  {    response = Response();    if (response == ".\r\n")    {      break;    }    else    {      msg.message += response;    }  }  return msg;}
 
then responds with the
+OK
acknowledgement, the message content and finally the single period terminating line.
Removing Messages
Retrieving a message does not remove the message from the POP3 server. A further call to LIST will still return themessage. To remove a message from POP3 server, you have to call the
Delete
method.The Delete method sends a
DELE
message with the message number to the POP3 server. The server will respondwith the
+OK
acknowledgment message, if successful.
Supporting Functions
The
List
,
Retrieve
and
Delete
methods used two private methods,
Write
and
Response
, to
send and receivemessages from the POP3 server.C# native strings, like Java native strings, are UNICODE. We therefore need to encode and decode the strings to andfrom ASCII. After encoding the string, we can then retrieve the socket stream by calling the
TcpClient.GetStream
 method. I finish the
Write
method by called the
Debug.Writeline
method. This sends the string to the debugstream for help with debugging.The
Response
method is similar to the
Write
method accept that we retrieve bytes from the stream before decodingthem. Again we call the
Debug.WriteLine
method to send the read data to the debug stream and help withdebugging. Note that we have a limitation in the
Response
method. We can only retrieve or send up to 1024 bytes at atime. I'll fix this in a later release. If you intend to use this in production, then you'll have to do the same first.
Using the Class
Using the new class is pretty easy.
public void Delete(Pop3Message rhs){  string message;  string response;  message = "DELE " + rhs.number + "\r\n";  Write(message);  response = Response();  if (response.Substring(0, 3) != "+OK")  {    throw new Pop3Exception(response);  }}private void Write(string message){  System.Text.ASCIIEncoding en = new System.Text.ASCIIEncoding() ;  byte[] WriteBuffer = new byte[1024] ;  WriteBuffer = en.GetBytes(message) ;  NetworkStream stream = GetStream() ;  stream.Write(WriteBuffer, 0, WriteBuffer.Length);  Debug.WriteLine("WRITE:" + message);}private string Response(){  System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();  byte[] serverbuff = new Byte[1024];  NetworkStream stream = GetStream();  int count = 0;  while (true)  {    byte[] buff = new Byte[2];    int bytes = stream.Read(buff, 0, 1 );    if (bytes == 1)    {      serverbuff[count] = buff[0];      count++;      if (buff[0] == '\n')      {        break;      }    }    else    {      break;    };  };  string retval = enc.GetString(serverbuff, 0, count );  Debug.WriteLine("READ:" + retval);  return retval;}static void Main(string[] args){  try  {    Pop3 obj = new Pop3();    obj.Connect("mail.xxx.com", "yyy", "zzz");    ArrayList list = obj.List();    foreach (Pop3Message msg in list )    {      Pop3Message msg2 = obj.Retrieve(msg);      System.Console.WriteLine("Message {0}: {1}",        msg2.number, msg2.message);    }    obj.Disconnect();  }  catch (Pop3Exception e )  {
of 00

Leave a Comment

You must be to leave a comment.
Submit
Characters: ...
You must be to leave a comment.
Submit
Characters: ...