In a previous article in this issue (See page 67), we’ve looked at how POP3 works. We shall now code a very simple C# POP3 client, which will take the name or IP address of the POP3 server and credential details from the user, connect to the server, and tell you how many e-mail messages are present in the inbox. To run the executable, you’ll need the Microsoft Next Generation Windows Services (NGWS) Beta 1 installed on your system. You’ll find the code for the client in cspop3.cs on the CD.
Here, we’ll explain the code that’s on the CD. So, open cspop3.cs from cdrom\\sorc_code and let’s get started.
The program is built around the class, CSPOP3. The main method kicks off by displaying the welcome text, followed by instantiation of cspop3¸which is an object of the class, CSPOP3. Also, conPOP3, an object of class TCPClient, is instantiated. This object is used to connect to the POP3 server. The TCPClient class provides a high-level abstraction over the underlying Sockets class and encapsulates the generic functionality required to code any kind of TCP client, like our POP3 client. It’s available under the Systems.Net.Sockets namespace.
Next, the GetInputs method is called, which takes the required inputs from the user, namely, the POP3 server’s name or IP address, and the username and password for authentication.
The CheckMailCount method is called after this, which tries to count the number of e-mail messages in the user’s inbox.
Next, we call the Connect method of conPOP3 that we mentioned earlier. The Connect method is overloaded and we use the overload, which takes in a string containing the name or the IP address of the host to connect to, along with an integer port number. This overloaded version of the Connect method is prototyped as:
public int Connect(string hostname, int port);
The method tries to connect to the host and returns 0 (zero) if the connection is successfully made. If a connection is successfully made, we declare a few variables for working.
Next, we acquire the network stream to send and receive data to or from the server. You can picture the network stream as a tunnel in which traffic can go both ways. We acquire the network stream using the GetStream method of the TCPClient class, which returns a NetworkStream class object, ns. We then call the Read method on ns to read the message sent by the server. When we connect to the POP3 server, it sends a welcome message to the client, which we read from the stream using the Read method. This is prototyped in the NetworkStream class as:
public override int Read(byte  buffer, int offset, int count);
The override modifier tells us that this function is an override of a base class function, which happens to be the Read method of the Stream class in the System.IO namespace. The method expects an array of bytes as the first parameter into which the data from the stream shall be read into. The second parameter is the offset in the array starting from which the data shall be copied into the array, while the third parameter is the length of the byte array passed as the first parameter. If the read was successful, number of bytes read are returned, otherwise, 0 (zero) is returned.
We next convert the array of bytes read into the buffer to a string, using the overload of Encoding.ASCII.GetString, which takes an array of bytes and returns an equivalent ASCII string. It’s for this purpose that we’ve put a reference to the System.Text namespace near the start of the code. We next check if the string contains the +OK success code sent by the server. If it doesn’t, we abort and return false.
The authentication process now starts off. We prepare the USER command to be sent to the server by appending the username to it and by appending a \\r\\n (carriage return-linefeed).
The command formed in the client_command string is then converted to an array of bytes using the Encoding.ASCII.GetBytes method, which takes in a string and returns an array of bytes. This byte array is then sent to the POP3 server using the Write method of the NetworkStream object, ns. It is prototyped like the Read method:
public override int Write(byte  buffer, int offset, int count);
The override modifier tells you that this function is an override of a base class function, which happens to be the Write method of the Stream class in the System.IO namespace. The method expects an array of bytes as the first parameter from which the data shall be written to the stream and sent to the server. The second parameter is the offset in the array starting from which the data shall be read and sent to the server. The third parameter is the length of the byte array passed as the first parameter. If the read was successful, number of bytes written to the stream are returned. Otherwise, 0 (zero) is returned if the connection was closed by the server.
Next, we read in the reply sent by the POP3 server, and check if the reply received contains the expected success code. If yes, we continue the authentication by passing the password using the same procedure. If the server doesn’t reply with the success code, we abort and return false.
Once the authentication is successful, we prepare the STAT command like the USER and PASS commands and send it to the server. The server shall reply back, containing the number of messages present in the inbox, along with their total size. We read this reply, convert it to a text string, and extract the portion containing the number of messages. The server reply will be something like this:
S: +OK 2 250
Note that there is always a space separating the +OK and the number of messages, 2. Likewise, there’s a space separating the number of messages and the message size, 250. We use the overloaded IndexOf method of the String class, which takes in a string and returns its position of first occurrence. Using this method, we get the position of the first space, saving it in the variables fpos.
Next, we use the overload of IndexOf method which takes in the string to be searched and position from which the search has to commence. We set this position one more than fpos. This gets us to the position of the second space, which we store in spos. Finally, we use the Substring method of the String class and extract the substring containing the number of messages in the inbox, which are then displayed to the user. The Substring method takes the starting position, from which specified length of the string will be extracted. The overloaded version we used is prototyped as:
public string Substring(int start, int length);
Finally, we proceed to send the QUIT command to the POP3 server, to enter the update state, and terminate the connection.
So that was our simple C# POP3 client. To compile the code, enter the following command line:
csc /reference:system.net.dll cspop3.cs
where csc is your C# compiler and cspop3.cs contains the above explained code. Here ends our journey through the world of e-mail. I hope that you now have a fair idea about how one of the world’s fastest communication systems works.
Kumar Gaurav Khanna runs www.wintools.f2s.com