Check Your Email With Style - Updated
By Jeff Julian , MVP - XML
Published: 3/11/2003
Reader Level: Expert
Rated: 4.00 by 2 member(s).
Tell a Friend
Rate this Article
Printable Version
Discuss in the Forums

Check Your Email With Style

Have you ever wanted to write your own POP3 email client? Well now you can with the help of my C# example. This article explains how to use .NET to connect to a POP3 mail server, and the different commands to use with the server to get the results you want.

Connecting

To connect to another machine on the Internet like a mail server, you will need a TCP socket. Using the System.Net.Sockets collection of objects, you can do this with ease. The main object we will need is the Socket class. Here is an example of how to create this object and connect to the mail server.

Socket _socket;
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.Connect(new IPEndPoint(Dns.Resolve("mail.yourdomain.com").AddressList[0], 110));

With the connection created, it's almost time to talk to the server, but first we have to create the communication method. This method has to be able to send a message and receive a response. I will use a asynchronous socket during the receive process to ensure the data is handled properly. When using the Socket object, the message has to be converted into a byte array. This next example explains how to convert the string and send it through our Socket. POP3 mail servers require a carriage return after the message so it knows when to respond, so instead of adding it to every message, we will put it here.

_socket.Send(Encoding.ASCII.GetBytes(_lastCommand + " " + Message + "\r\n"));

Enough with sending, it is now time to see if the server has responded with a message and grab that message from the stream. The example below will grab portions of the message and add them to a StringBuilder object, then loop back and see if more data is available . This allows our method to be used for receiving small or large messages including email.

      private void SocketReceive(IAsyncResult _asyncResult)
     {
          State _state =  null;
          Socket _receiveSocket =  null;
          int _bytesRead = 0;
          string _receivedMessage =  null;

          try
          {
               _state = (State) _asyncResult.AsyncState;
               _receiveSocket = _state.Handler;

                if(_receiveSocket.Connected)
               {
                    _bytesRead = _receiveSocket.EndReceive(_asyncResult);

                     if(_bytesRead > 0)
                    {
                         _state.MessageBuilder.Append(Encoding.ASCII.GetString(_state.Buffer,0,_bytesRead));
                         _receivedMessage = _state.MessageBuilder.ToString();
                    }

                     if(_receivedMessage !=  null &&
                       (((_lastCommand == "LIST" || _lastCommand == "RETR") && 
                          _receivedMessage.Substring(_receivedMessage.Length - EOF.Length, EOF.Length) == EOF) ||
                        (_lastCommand != "LIST" && _lastCommand != "RETR")))
                    {
                         ParseMessage(_receivedMessage);
                         _state.MessageBuilder.Remove(0,_receivedMessage.Length);
                    }

                    _socket.BeginReceive(_state.Buffer,0,_state.BufferSize,0, new AsyncCallback(SocketReceive),_state);
               }
          }
           catch
          {
				
          }
     }

Communicating With The Post Office Protocol - Version 3

Ok, Ok, Ok. We now have our send and receive process done, we can now start communicating with our POP3 server.

Here is the list of POP3 commands we will use to communicate and descriptions of them:

  1. USER command is used to send the server your username.
  2. PASS command sends your password and responds with the status of your login.
  3. LIST will return the total amount of messages and the total size of the emails. Each line after the totals is the individual message IDs and the size of the message.
  4. RETR along with the message ID will grab and return the entire email message from the server.
  5. DELE along with the message ID will delete the message from the server.
  6. QUIT command will finialize the processes on the server and close the maildrop.
The POP3 server will respond two ways.
  1. +OK with a message.
  2. -ERR with an exception.

Check Your Email

Now that we have connected, built our communication methods, and know what to send the server, lets check our email. This method is fired from a delegate in the receive method once a message has been completely downloaded. The main purpose of this method is to parse the message and send the next message to the mail server.

     private void OnParseMessage(string Message)
     {
          if(Message.Substring(0,OK.Length).Trim() == OK)
          {
               switch(_lastCommand)
               {
                    case null:
                         Send("USER",_username);
                         break;
                    case "USER":
                         Send("PASS", _password);
                         break;
                    case "PASS":
                         Send("STAT","");
                         break;
                    case "STAT":
                         int _start = Message.IndexOf(OK) + OK.Length + " ".Length;
                         if(_start >= 0)
                         {
                              _messages = new int[int.Parse(Message.Substring(_start,Message.IndexOf(" ",_start) - _start))];
                              Send("LIST","");
                         }
                         else
                         {
                              this.LoginError();
                         }
                         break;
                    case "LIST":
                         int i = 0;
                         while(Message.Substring(0,1) != ".")
                         {
                              if(Message.Substring(0,OK.Length) != OK)
                              {
                                   _messages[i] = int.Parse(Message.Substring(0, Message.IndexOf(" ", 0)));
								
                                   if(_currentMessage < 0)
                                   {
                                        _currentMessage = i;
                                   }
                                   i++;
                              }
                              Message = Message.Remove(0, Message.IndexOf("\r\n") + "\r\n".Length);
                         }
                         if(_currentMessage > -1)
                         {
                              Send("RETR",_messages[_currentMessage].ToString());
                         }
                         else
                         {
                              this.MessagesFinished(_mailTable);
                         }
                         break;
                    case "RETR":
                         if(_mailTable == null)
                         {
                              _mailTable = new Hashtable();
                         }

                         _mailTable.Add(_messages[_currentMessage], Message);
                         this.MessageFound(_messages[_currentMessage]);
                         _currentMessage++;

                         if(_currentMessage == _messages.Length)
                         {
                              this.MessagesFinished(_mailTable);
                         }
                         else 
                         {
                              Send("RETR",_messages[_currentMessage].ToString());
                              break;
                         }
                         break;
               }
          }
          else
          {
               if(_lastCommand == "USER" || _lastCommand == "PASS")
               {
                    this.LoginError();
               }
          }
     }

Conclusion

During this process I hope you have learned a few things. One, how to check your email in C#, and the other, how easy it is to communicate to different servers using the protocols they are designed around in code. Other servers like FTP or IMAP will need simular classes made to communicate with them and with this example, you should be able to create your own classes to uses them.



Marketplace
(Sponsored Links)
What are the green links?
   



 
Copyright © 2007 CMP Tech LLC |
Privacy Policy (4/10/06) | Your California Privacy Rights (4/10/06) | Terms of Service | Advertising Info | About Us | Help