Click here to Skip to main content
Click here to Skip to main content

How to Access Emails Using the IMAP Protocol

, 26 May 2014 GPL3
Rate this:
Please Sign up or sign in to vote.
This article explains how to use the IMAP protocol to access emails. It explains how to use some of the common IMAP commands.

Introduction

IMAP (Internet Message Access Protocol) is an email messaging protocol which allows transferring of e-mail messages from a server. The protocol is based on commands which are sent from a client such as Mozilla Thunderbird or Microsoft Outlook. These commands allow you to login to a mailbox, get the total message count and the unread message count, view your messages, as well as create, delete, and rename mailboxes.

There are many IMAP controls available for various programming languages, and many articles explaining how to use these controls, but what if you would like to understand how the protocol is used to help you develop your own IMAP control? You may want to develop a small application that sits on your desktop informing you of new emails, or just displaying how many unread email messages you have. If you’re a very adventurous developer, you can try to develop your own email client.

In this article, I will explain how to connect to a mailbox to retrieve emails. This article is intended to be a brief introduction to some of the main IMAP commands. I will not discuss any error handling to make the code more understandable. You can add the error handling yourself.

Connecting to the mailbox

IAMP operates on port 143. In order to connect to the mailbox, we need to connect to this port number using a hostname.

Listing 1.1 below shows all the namespaces we need to include in our project.

Listing 1.1

using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text.RegularExpressions;

Now that we have included the required namespaces, let’s start coding by declaring all the classes we need. Listing 1.2 below shows all the classes we need to declare.

Listing 1.2

private TcpClient _imapClient;
private NetworkStream _imapNs;
private StreamWriter _imapSw;
private StreamReader _imapSr;

We are going to use the TcpClient class to connect to the mailbox server on port 143. Examine the InitializeConnection() method in listing 1.3 below.

Listing 1.3

private void InitializeConnection(string hostname, int port)
{
    try
    {
        _imapClient = new TcpClient(hostname, port);
        _imapNs = _imapClient.GetStream();
        _imapSw = new StreamWriter(_imapNs);
        _imapSr = new StreamReader(_imapNs);

        Console.WriteLine("*** Connected ***");
        Response();
    }
    catch (SocketException ex)
    {
        Console.WriteLine(ex.Message);
    }
}

The InitializeConnection() method takes two arguments, the mailbox hostname and the port number. A TcpClient is instantiated, and the NetworkStream class is used to read and write to the stream. A SocketExeption will be raised if the _imapClient object is unable to connect to the mailbox server.

After successfully connecting to the mailbox server, the server will respond with a message. This is usually an “OK” message indicating that you have connected to the server. The code in Listing 1.4 below shows a very simple method to receive data from the mailbox server.

Listing 1.4

private string Response()
{
    byte[] data = new byte[_imapClient.ReceiveBufferSize];
    int ret = _imapNs.Read(data, 0, data.Length);
    return Encoding.ASCII.GetString(data).TrimEnd();
}

Every time we send a command to the mailbox server, we will use the above Response() method to get the response data from the mailbox server. After getting a response from the server, we need to login using our login credentials.

Login command

The first command we will send to the mailbox server is the login command. Listing 1.5 below is the AuthenticateUser() method, which takes two arguments, the username and the password.

Listing 1.5

public void AuthenticateUser(string username, string password)
{
    _imapSw.WriteLine("$ LOGIN " + username + " " + password);
    _imapSw.Flush();
    Response();
}

The above AuthenticateUser() method sends a “LOGIN” command to the mailbox server. The structure of this command is shown below.

PREFIX LOGIN USERNAME PASSWORD

Each command is followed by a prefix. In the AuthenticateUser() method, the prefix used is the $ symbol. You can use a different prefix of your own, but some characters such as * will not work. Take notice of the Response() method which is being called from the AuthenticateUser() method. As I mentioned earlier, every time we send a command to the mailbox server, we need to get the response from the server. You can print the response to the console, but I decided not to do this.

If the supplied username and password are successfully authenticated, the server will respond with a message such as "$ OK User Loged In". Notice the prefix at the beginning of the message. This prefix will be the prefix you are using.

If, however, your login credentials are not authenticated, the server will respond with a message such as "$ NO Login failed: authentication failure". Using the server's response message, you can do your own exception handling. You can read the first four characters from the response, and determine if the response was an OK or a NO, in which case you can inform the user.

After successful authentication, we can perform a number of tasks, such as get the total number of messages. The MailCount() method in listing 1.6 sends a command to examine the INBOX folder and get the total message count from the server.

Listing 1.6

public int MailCount()
{
    _imapSw.WriteLine("$ STATUS INBOX (messages)");
    _imapSw.Flush();

    string res = Response();
    Match m = Regex.Match(res, "[0-9]*[0-9]");
    return Convert.ToInt32(m.ToString());
}

The STATUS command takes two arguments. The first is the folder, and the second is what is known as a flag. The flag (messages) indicates that you want to get the total number of messages in the inbox. If the command was executed successfully, the server will respond with a message similar to the following:

* STATUS INBOX (MESSAGES 3)

Notice that the server has responded with the total message count in the INBOX folder; in the above response, the total message count is 3. We can also find out how many new messages there are in the inbox. The MailUnreadCount() in listing 1.7 below sends a STATUS command, but it sends an (unseen) flag. This flag tells the mailbox server to return the total count of unread messages.

Listing 1.7

public int MailUnreadCount()
{
    _imapSw.WriteLine("$ STATUS INBOX (unseen)");
    _imapSw.Flush();

    string res = Response();
    Console.WriteLine(res);
    Match m = Regex.Match(res, "[0-9]*[0-9]");
    return Convert.ToInt32(m.ToString());
}

It is time to get some messages from the mailbox server. Before we begin to fetch any messages, we must first select the folder to retrieve the messages from. The SelectInbox() method selects the INBOX folder. After selecting the INBOX folder, we can begin to get messages. Listing 1.8 below sends the SELECT command to the server to select the INBOX folder.

Listing 1.8

public void SelectInbox()
{
    _imapSw.WriteLine("$ SELECT INBOX");
    _imapSw.Flush();
    Response();
}

Finally, we can now send a command to get a single message from the mailbox sever. The command used to get a message is the FETCH command. This command takes two arguments: the first is the message number to retrieve, and the second is a combination of message flags. The GetMessageHeaders () method in Listing 1.9 below takes a single argument of type int.

Listing 1.9

public object GetMessageHeaders(int index)
{
    _imapSw.WriteLine("$ FETCH " + index + 
                      " (body[header.fields (from subject date)])");
    _imapSw.Flush();

    return Response();
}

The above method GetMessageHeaders() sends a FETCH command to the mailbox server, and only gets the from, subject, and date fields from the header of a selected message. This is useful if you want to display messages in a list control to show all the messages, but not the message body.

To get the body of the email, you need to send the FETCH command to the server, but you use the body[text] flag. Listing 2.0 below shows the command to get the message body.

Listing 2.0

public object GetMessage(int index)
{
    _imapSw.WriteLine("$ FETCH " + index + " body[text]");
    _imapSw.Flush();

    return Response();
}

Finally, after we have finished with the mailbox server, we need to logout. This is as easy as sending a LOGOUT command to the server. Listing 2.1 below shows the Disconnect() method which sends a logout command to the mailbox server.

Both the GetMessageHeaders() and GetMessage() methods will return a response which is not formatted. You will need to format the response from the server, and add your own error handling by handling exceptions. To keep the code simple, I have not added any exception handling.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

Share

About the Author

Syed M Hussain
Web Developer
United Kingdom United Kingdom
No Biography provided

Comments and Discussions

 
Questionconnection close Pinmembermedasatheesh21-Oct-14 5:54 
AnswerRe: connection close PinmemberSyed M Hussain21-Oct-14 6:24 
Question"$ BAD could not parse command" when getting message PinmemberMember 1033197518-Aug-14 0:26 
AnswerRe: "$ BAD could not parse command" when getting message PinmemberSyed M Hussain18-Aug-14 6:30 
QuestionRe: "$ BAD could not parse command" when getting message PinmemberL_Wlodar25-Aug-14 2:14 
GeneralMy vote of 5 PinmemberHumayun Kabir Mamun26-May-14 20:01 
QuestionHow to Read unread messages? PinmemberMember 1065496511-Mar-14 20:57 
AnswerRe: How to Read unread messages? PinmemberSyed M Hussain12-Mar-14 1:50 
QuestionWriting content to a text file PinmemberMember 106549659-Mar-14 6:33 
AnswerRe: Writing content to a text file PinmemberSyed M Hussain10-Mar-14 4:31 
GeneralRe: Writing content to a text file Pinmembershahinhr11-Mar-14 5:31 
QuestionThankyou [modified] PinmemberRosieC19-Feb-14 7:14 
Questionsir plz give instructions how to test or use it Pinmemberheemanshubhalla10-Feb-14 2:48 
QuestionGoogle Access!! PinmemberDull Developer24-Nov-11 3:43 
AnswerRe: Google Access!! Pinmemberdarima7-Dec-13 2:04 
GeneralRe: Google Access!! Pinmembernewinter24-Mar-14 13:09 
QuestionGet unread message number from IMAP Pinmemberfarogh haider27-Oct-11 2:44 
QuestionRequire email message status Pinmemberb96781236-Jul-11 0:50 
GeneralHelp about store flag "UNSEEN" Pinmemberjymitra11-Oct-10 22:14 
GeneralRe: Help about store flag "UNSEEN" Pinmemberdedeblank19-Nov-10 14:00 
GeneralRe: Help about store flag "UNSEEN" Pinmemberjymitra19-Nov-10 19:07 
GeneralMy vote of 1 Pinmemberlegendicus3-Mar-10 5:13 
QuestionHow to Access Emails Using the IMAP Protocol PinmemberExplorativeGuy9-Feb-10 21:47 
GeneralGooglemail Access PinmemberJayyyman21-Dec-09 23:53 
GeneralRe: Googlemail Access PinmemberSyed M Hussain22-Dec-09 1:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 26 May 2014
Article Copyright 2008 by Syed M Hussain
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid