Building your own Mail Client using C#

March 26, 2009 · Posted in .NET, C# 
Easy AdSense by Unreal

IMailPlus.zip

Introduction

The code here is written under the common creativity license you could download the project from the link above or clicking on the next link IMailPlus.zip It has been enspired from Rodolfo Finochietti POP3 Project I have redesigned it and implement it and added to it SSL Support and optimized the design so that you could easily add other email clients below you will find a screen shot from the created demo application imailplusdemo

This post will go with you step by step towards building your own Mail Client using C#, First to start I’ll start you need to first know the protocol you will be retrieving emails with I will discuss here the POP3 Protocol. The POP3 Protocols an application-layer Internet standard protocol along with IMAP4 they are the two most prevalent Internet standard protocols for e-mail retrieval. To understand how the protocol works lets examine a (Server – Client) communication example. First the server is waiting for connection from any client

S: <wait for connection on TCP port 110>
The Client opens a TCP Connection with the server
C: <open connection>
The Server then response with the +OK Ready State
S:    +OK POP3 server ready <1123.69123552@mail.ramymostafa.com>
Then we authenticate using the username and password
C:    USER username_here
S:    +OK send PASS
C:    PASS password
S:    +OK Welcome.
C:    LIST
S:    +OK 2 messages (320 octets)
S:    1 120
S:    2 200
S:    .
C:    RETR 1
S:    +OK 120 octets
S:    <the POP3 server sends message 1>
S:    .
C:    DELE 1
S:    +OK message 1 deleted
C:    RETR 2
S:    +OK 200 octets
S:    <the POP3 server sends message 2>
The QUIT command will remove retrieved messages from the server and sign off.
C:    QUIT
S:    +OK dewey POP3 server signing off (maildrop empty)
C:  <close connection>
S:  <wait for next connection>

Designing the Mail Client

imailpluslibrarydiagram

Now that we know how the POP3 protocol work we could start building our Mail Client. But before that let’s discuss the structure of an e-mail message.

mailmessage A mail message consists of

  • Header which includes things like
    • Mime type
    • Received Date
    • Subject
    • To
    • From
  • Body which includes the Messages
    • HTML Message
    • Text Message

So, Basically the email client should first connect to the server and then authenticate itself with the server then start to exchange the protocol messages with the server and parse the replies to extract from it the message data or the reply status itself etc…, It should be able also to retrieve the emails from the server and parse the message retrieve to extract from it the MailMessage Information.

email-client The EmailClient is an AbstractClass with some properties required when connecting to the server Like the server user name, password, port number, whether or not the server uses SSL or not etc. Also it has methods for connecting to the server and Executing Commands to it , Retrieving the Server Response string and Retrieving the MaiList. In order to work with the mail client you should create your a class that inherits from the EmailClient representing the MailClient Protocol In this sample I have implemented the POPEmailClient you could find it’s Members below

popmailclient The POPEmailClient overloads the Connect Method to connect with POP3 Commands also it overloads the CreateCommand Method to create POP3 Command Format using the provided command in the parameter The Disconnect Method is used to disconnect from the server and it’s called if you don’t want to keep a copy of your Email’s on the server if you do want to keep a copy from your emails you should not call this method. The class also overrides the GetMailList Method to retrieve the Emails From the POP3 Server and Parse it to a List of POP3Messages.

Implementing the Email Client

Connect the Client To The Server using the given username, password and server it takes as parameters the Mail Server Domain Reference, The Mail Account User Name and Password.

        public override void Connect(string server, string UserName, string Password)
{
       try
       {
           if (_isConnected)
           {
               return;
           }
           if (!UseSSL)
           {
               Connect(server, PortNumber);
               string response = Response();
               if (!response.Trim().StartsWith("+OK"))
               {
                    //TODO: Raise Error Event
               }
               else
               {
                   ExecuteCommand("USER", UserName);
                   ExecuteCommand("PASS", Password);
               }
               _isConnected = true;
           }
           else
           {
               byte[] bts;
               int res;
               string responseString = "";
               ResponseList.Clear();
               Connect(server, PortNumber);
               inStream = new SslStream(this.GetStream(), false,
                  new RemoteCertificateValidationCallback(ValidateServerCertificate),
                   new LocalCertificateSelectionCallback(SelectLocalCertificate));
               inStream.AuthenticateAsClient(server);
               bts = new byte[1024];
               res = inStream.Read(bts, 0, bts.Length);
               ResponseList.Add(Encoding.ASCII.GetString(bts, 0, res));
               responseString = ExecuteCommand("USER", UserName);
               ResponseList.Add(responseString);
               responseString = ExecuteCommand("PASS", Password);
               ResponseList.Add(responseString);
               if (!responseString.Trim().StartsWith("+OK"))
               {
                   //TODO: Raise Error Event
               }
               else
                   _isConnected = true;
            }
        }
        catch (Exception ex)
        {
            //TODO: Raise Error Event
        }
}

The GetMailList Method first Execute the Command List then it Retrieves a MetaMessageInfo from the Response String here the response string is parsed to retrieve Meta Information of the emails on the server like Number of Messages, and Messages Length

 List result = new List();
 string responseString = ExecuteCommand("LIST");
MetaMessageInfo info = new MetaMessageInfo(MailClientType.POP3,responseString);

Here we make a loop to retrieve messages until we retrieve all messages using the number of messages in the POPMessage constructor it extracts all the message info from the string to fill its attributes

for (int i = 1; i <= info.NumberOfMessages; i++)
{
    responseString = ExecuteCommand("RETR", i.ToString(), true);
    POPMessage message = new POPMessage(responseString);
    message.Number = i.ToString();
    message.Retrieved = true;
    if (message.MessageBoundaryId != null)
         result.Add(message);
}

The Method that prase the response string to retrieve info from the Email is the LoadMethod

public override void Load(string messageString)
{
    string message = messageString.Replace("+OK message follows", "");
    Message = message;
    string messageIdPure = MessageBoundaryId;
    //the start of the message body starts from MessageBoundaryId ex --- ID --- Here I extract the Message body from the complete
   //response string
    int bodyIndex = message.IndexOf("--" + messageIdPure, StringComparison.CurrentCultureIgnoreCase);
    int messageLength = message.Length - bodyIndex;
    if (bodyIndex < 0)
        return;
    string bodyString = message.Substring(bodyIndex, messageLength);
    string[] splitMessageOptions = new string[1];
    splitMessageOptions[0] = "--" + messageIdPure;
    //Here I Split with the message boundary Id to seperate the Text and HTML Messages
    string[] messages = bodyString.Split(splitMessageOptions, StringSplitOptions.RemoveEmptyEntries);
    //The Get Message Body Method retrieves the HTML, and Text Messages from the messages array
    GetMessageBody(messages);
}

to extract a header property I use

_from = GetHeaderValue(EmailHeaders.From);

Where the EmailHeaders.From is an enumerator with the headers and the GetHeaderValue Method extracts the required header value from the complete message string.

IMailPlusLibrary Usage

to use the library it’s simple all you need to to do is to do the below code

POPEmailClient popClient = new POPEmailClient();
popClient.UseSSL = account.UseSSL;
popClient.PortNumber = Convert.ToInt32(account.PortNumber);
popClient.Connect(account.Server, account.UserName, account.Password);
account.CurrentAccountMails = popClient.GetMailList();

Share Your Thoughts

Finally I hope that this project would be of a great help for you. Please feel free to contact me regarding anything you don’t understand in the code yo will find the library code fully XML documented. Also if you have any cool ideas or updates for it please share your thoughts here.

Short URL for this post: http://bit.ly/JyyGZ

Comments

20 Responses to “Building your own Mail Client using C#”

  1. Khalid on March 30th, 2009 8:48 am

    Great Article, with very well understanding of pop3.

  2. cjjer on April 8th, 2009 5:11 am

    nice job!

    but when i receive some chinese(not english) language email, the subject and body can not be read,

    wait for your answer

  3. admin on April 8th, 2009 8:09 am

    thanks, could you forward to my mail ramy.mostafa@gmail.com the email that has a problem so that I could check it?

    Regards
    Ramy

  4. admin on April 8th, 2009 8:12 am

    you could also debug it your self in the POPMessage Class GetHeaderValue Method for the subject as for the email body you could debug in the Load Method at the same class

    Regards
    Ramy

  5. Wicenty on April 12th, 2009 9:37 pm

    Hi there Basically not much noteworthy happening. I feel like an empty room. I’ve more or less been doing nothing. mix Interesting posts, besides those spam… dog, Kiss all of you

  6. Bogimilus on April 16th, 2009 8:28 pm

    Greetings. Kindest, Now I had more time to read your Homepage Keep it up!!

  7. Tekla on April 16th, 2009 8:53 pm

    Hello, and sorry for my mind. you’ve put so much thought into the site and thanked everyone who has ‘been there’ for you I like this site. Thanks

  8. Julian on April 16th, 2009 9:39 pm

    Hi! WELL DONE!!! Kindest regards With respect admiration.

  9. Honorata on April 23rd, 2009 6:11 pm

    This is a cool site!, Best Wishes

  10. John1250 on May 5th, 2009 8:47 am

    Perfect site, i like it!

  11. John1250 on May 5th, 2009 10:41 am

    Excellent site. It was pleasant to me.

  12. anand on May 14th, 2009 11:43 pm

    hi please check my comment on your same article in c# corner, hope you will address that issue in next version :-)
    here is its content

    “Dear Mr.Ramy,
    thanks for the superb code, coming to the point i found only one bottleneck in this code if the message is not a multipart message then the boundary you are trying to find and extract message based on that will not work, it even not get displayed in the list, how to over come this
    here is a sample mail header

    To: xxxxxxx@gmail.com
    Content-Transfer-Encoding: 7bit
    Subject: test
    Date: Thu, 14 May 2009 05:10:26 -0400
    X-MB-Message-Source: WebUI
    X-AOL-IP: 64.12.78.139
    X-MB-Message-Type: User
    MIME-Version: 1.0
    From: xxx@aol.in
    Content-Type: text/plain; charset=”us-ascii”
    X-Mailer: AOL Webmail 42949-STANDARD
    Received: from 59.96.134.162 by CEN1-L08.sis.aol.com (10.64.224.8) with HTTP (WebMailUI); Thu, 14 May 2009 05:10:26 -0400
    Message-Id: <8CBA28AF4275D76-7E8-1E96@CEN1-L08.sis.aol.com>
    X-Spam-Flag:NO

    test
    —————————————-

    just thought you might want to know this. Any ideas

    best regards”

  13. admin on May 15th, 2009 7:22 am

    Hi,

    Thanks for the comment its really useful and yes I am going to consider it in my next version :-)

    Regards
    Ramy

  14. anand on May 16th, 2009 3:10 am

    When is your next version release :-)

  15. admin on May 16th, 2009 11:12 am

    I would say that it would be at the end of June or the beginning of July currently I am working on another open source project for generating code based on templates. I believe it will be a cool one hope I will release it on the 10th of June or something then I will start on the second version of the IMailPlus

    Regards
    Ramy

  16. Anand on May 18th, 2009 2:49 am

    hi Mr.Ramy,

    if you would mind to share any ideas how to find the message starting in a plain text message so that i can do a bit with your source code and can test with them i am having some time to experiment. :-)

  17. John on November 17th, 2009 6:50 am

    Hi. That’s a great project! But it didin’t work on me. I need to build a POP3 client in C# but i don’t know how to do it. Can you help me out?

  18. Ramy Mostafa on November 20th, 2009 8:53 am

    Could you elaborate more what you need since this is a POP3 Client Library in C#?

    Regards
    Ramy

  19. Osman on December 14th, 2009 10:36 am

    hi Ramy Mostafa,

    You did a great job, but it doesnt really work when I publish it.
    I can login and recieve email, but i cant read in body or the content of the mail self.

    example.
    form: sender@gmail.com
    to: receiver@gmail.com
    Subject: test.
    Body html: empty
    Body tekst: empty.

    How can i change or solve that.

    Thank you in advance.

    Osman

  20. Sean on March 11th, 2010 11:10 am

    Hello sir, I have been investigating your library for a personal project I am working on and am finding it extremely capable, well written and easy to use. I am having one issue I thought you might be able to provide some help with. I am having trouble loading one type of email I commonly receive. It is an email consisting of a sms text message forwarded from the new Google voice project to Gmail. By debugging I can see it is failing at least in part because of a lack of boundary Ids (“”boundary=””) in the message string causing the boundary ID to remain null. I can see that some of the data is being parsed from the message but not all including the body text.
    Would you be as kind as to give me some insights as to what I should try to incorporate this type of email? As a test I connected my Outlook to this account and these messages are arriving there parsed correctly there. Thank you in advance and for making your work available for others.

Leave a Reply




Spam Protection by WP-SpamFree

























































download movies