Imap IDLE

IDLE is an IMAP feature described in RFC 2177 that allows a client to indicate to the server that it is ready to accept real-time notifications.

IMAP4 servers that support IDLE will include this programming string in the result of their CAPABILITY command.

You can use SupportedExtensionsmethod to check server’s capability list

// C# code

using (Imap client = new Imap())
{
     client.ConnectSSL("imap.server.com");
     foreach (ImapExtension extension in client.SupportedExtensions())
     {
          Console.WriteLine(extension.Name);
     }

     bool supportsIdle = client.SupportedExtensions()
        .Contains(ImapExtension.Idle);

     client.Close();
}
' VB.NET code

Using client As New Imap()
     client.ConnectSSL("imap.server.com")
     For Each extension As ImapExtension In client.SupportedExtensions()
          Console.WriteLine(extension.Name)
     Next

     Dim supportsIdle As Boolean = client.SupportedExtensions() _
          .Contains(ImapExtension.Idle)

     client.Close()
End Using

Mail.dll IMAP client supports IDLE command.

There are two important methods:

  • Idle() – starts accepting real-time notifications. The method hangs until a notification is received.
  • StopIdle() – stops accepting real-time notifications.
// C# code

using (Imap client = new Imap())
{
    client.ConnectSSL("imap.server.com");
    client.Login("user@server.com", "password");

    FolderStatus folderStatus = client.SelectInbox();
    Console.WriteLine("Total message count: {0}",
        folderStatus.MessageCount);

    while(true)
    {
        FolderStatus currentStatus = client.Idle();
        Console.WriteLine("Total message count: {0}",
                currentStatus.MessageCount);
        foreach(long uid in client.SearchFlag(Flag.Unseen))
        {
            IMail email = new MailBuilder().CreateFromEml(
                client.GetHeadersByUID(uid));
            Console.WriteLine(email.Subject);
        }
    }
    client.Close();
}
' VB.NET code

Using client As New Imap()
	client.ConnectSSL("imap.server.com")
	client.Login("user@server.com", "password")

	Dim folderStatus As FolderStatus = client.SelectInbox()
	Console.WriteLine("Total message count: {0}",_
		folderStatus.MessageCount)

	While True
		Dim currentStatus As FolderStatus = client.Idle()
		Console.WriteLine("Total message count: {0}",_
			currentStatus.MessageCount)
		For Each uid As Long In client.SearchFlag(Flag.Unseen)
			Dim email As IMail = New MailBuilder()_
 				.CreateFromEml(client.GetHeadersByUID(uid))
			Console.WriteLine(email.Subject)
		Next
	End While
	client.Close()
End Using

Now lets handle stop gracefully:

// C# code

using (Imap client = new Imap())
{
    client.ConnectSSL("imap.server.com");
    client.Login("user@server.com", "password");

    FolderStatus folderStatus = client.SelectInbox();
    Console.WriteLine("Total message count: {0}",
        currentStatus.MessageCount);

    bool stop = false;
    // We start a new thread to handle user input, <enter> = stop idle
    new Thread(() =>
	{
		Console.ReadLine();
		client.StopIdle();
		stop = true;
	}).Start();

    while(stop == false)
    {
        FolderStatus currentStatus = client.Idle();
        if (stop == true)
            break;

        Console.WriteLine("Total message count: {0}",
            currentStatus.MessageCount);

        foreach(long uid in client.SearchFlag(Flag.Unseen))
        {
            IMail email = new MailBuilder().CreateFromEml(
                client.GetHeadersByUID(uid));
            Console.WriteLine(email.Subject);
        }
    }
    client.Close();
}
' VB.NET code

Using client As New Imap()
	client.ConnectSSL("imap.server.com")
	client.Login("user@server.com", "password")

	Dim folderStatus As FolderStatus = client.SelectInbox()
	Console.WriteLine("Total message count: {0}",_
		currentStatus.MessageCount)

	Dim [stop] As Boolean = False
	' We start a new thread to handle user input, <enter> = stop idle
	New Thread(Function() Do
		Console.ReadLine()
		client.StopIdle()
		[stop] = True
	End Function).Start()

	While [stop] = False
		Dim currentStatus As FolderStatus = client.Idle()
		If [stop] = True Then
			Exit While
		End If

		Console.WriteLine("Total message count: {0}",_
			currentStatus.MessageCount)

		For Each uid As Long In client.SearchFlag(Flag.Unseen)
			Dim email As IMail = New MailBuilder()_
				.CreateFromEml(client.GetHeadersByUID(uid))
			Console.WriteLine(email.Subject)
		Next
	End While
	client.Close()
End Using

Tags: , , , ,

3 Responses to “Imap IDLE”

  1. Scott Says:

    Is there a command where client.SelectInbox() can be replaced so that you can get the all mail folder instead? I figure that would be better so that only one IDLE connection is required for an account. Is there a way to find out which email goes with which folder in this case?

  2. Pawel Lesnikowski Says:

    @Scott

    You can use any folder name:

    client.Select("All Mail")
    

    In case of Gmail you may want to use CommonFolders class to get the All Mail folder name:
    http://www.lesnikowski.com/blog/localized-gmail-imap-folders

    > Is there a way to find out which email goes with which folder in this case?
    In case of Gmail you can get all labels for specified message:
    http://www.lesnikowski.com/blog/get-gmail-labels-for-specified-messages

  3. Download emails from Gmail via POP3 Says:

    [...] use push email [...]

Leave a Reply