Folder management using IMAP (create, delete, rename)

Here’s the simple example that creates, renames and deletes an IMAP folder using Mail.dll IMAP library:

// C# version:

using Limilabs.Mail;
using Limilabs.Client.IMAP;

class Program
{
    static void Main(string[] args)
    {
       using (Imap imap = new Imap())
       {
           imap.Connect("server.company.com");
           imap.Login("user", "password");

           imap.SelectInbox();

           imap.CreateFolder("New folder");
           imap.RenameFolder("New folder", "Better name");
           imap.DeleteFolder("Better name");

           imap.Close();
       }
    }
};
' VB.NET version:

Imports Limilabs.Mail
Imports Limilabs.Client.IMAP

Public Module Module1
    Public Sub Main(ByVal args As String())

        Using imap As New Imap()
            imap.Connect("server.company.com")
            imap.Login("user", "password")

            imap.SelectInbox()

            imap.CreateFolder("New folder")
            imap.RenameFolder("New folder", "Better name")
            imap.DeleteFolder("Better name")

            imap.Close()
        End Using

    End Sub
End Module

Checking if folder exist

The simplest way is to get a list with all folders and check if it contains the name you are looking for.

List<FolderInfo> all = imap.GetFolders();
bool exists = all.Find(x => x.Name == "INBOX/Test folder") != null;

Mail.dll uses FolderInfo class to represent IMAP folder. It contains much useful folder information such as Name, Flags, HasChildren and CanSelect properties.

Creating IMAP folder

Creating folder is easy and not related to currently selected folder. Folder is always created at root.

imap.CreateFolder("Test folder");

To create nested folder, you need to know IMAP server’s separator character. Most common characters are: ‘/’ (slash) and ‘.’ (dot):

imap.CreateFolder("INBOX/Test folder");

Every FolderInfo instance contains SeparatorCharacter property:

char separatorCharacter = (char)imap.GetFolders()[0].SeparatorCharacter;

List sub folders

Listing direct sub folders:

List<FolderInfo> direct = imap.GetFoldersOneLevelDown("INBOX");

Listing all sub folders:

List<FolderInfo> all = imap.GetFolders("INBOX");

Get message count

If you want to get the number of messages in the folder you can use FolderStatus class returned by Imap.Examine and Imap.Select methods

FolderStatus status = imap.Examine("folder");
long count = status.MessageCount;

To get unseen message count you need to use IMAP search, and simply check the Count property of the returned uid list.

Copying, moving email messages

This next sample will shoe how to copy all messages from one folder to another:

imap.Select("INBOX/Source folder");
List<long> uids = imap.GetAll();
imap.CopyByUID(uids, "INBOX/Destination folder");

You can use Mail.dll .NET IMAP library to move messages between folders:

imap.Select("INBOX/Source folder");
List<long> uids = imap.GetAll();
imap.MoveByUID(uids, "Inbox/Destination folder");

Deleting IMAP folder

Deleting IMAP folder is simple, as it does not need to be empty before the operation:

imap.DeleteFolder("INBOX/folder to delete");

Issue a custom command to IMAP server

You can send any command to IMAP server using Mail.dll .NET IMAP component.

In this example we will issue a standard NOOP (NO OPeration) command. This command can be used as a periodic poll for new messages. Can also be used to reset any inactivity auto-logout timer on the IMAP server.

Of course there is a Noop() method on Imap class, but this example is about issuing any command yourself.

// C# version:

using System;
using Limilabs.Mail;
using Limilabs.Client.IMAP;

class Program
{
    static void Main(string[] args)
    {
       using (Imap imap = new Imap())
       {
           imap.Connect("imap.example.com");
           imap.Login("user", "password");

           imap.SelectInbox();

           ImapResponse response = imap.SendCommand("NOOP");
           foreach (string line in response.Lines)
           {
               Console.WriteLine(line);
           }

           imap.Close();
       }
    }
};
' VB.NET version:

Imports System
Imports Limilabs.Mail
Imports Limilabs.Client.IMAP


Using imap As New Imap()
	imap.Connect("imap.example.com")
	imap.Login("user", "password")

	imap.SelectInbox()

	Dim response As ImapResponse = imap.SendCommand("NOOP")
	For Each line As String In response.Lines
		Console.WriteLine(line)
	Next

	imap.Close()
End Using

Move emails to different folder with IMAP

This article describes how to move email messages from one folder (mailbox) to another using Mail.dll .NET IMAP library.

// C# version

using Limilabs.Mail;
using Limilabs.Client.IMAP;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        using (Imap imap = new Imap())
        {
            imap.Connect("imap.example.com");   // or ConnectSSL for SSL
            imap.UseBestLogin("user", "password");

            imap.SelectInbox();
            List<long> uids = imap.Search(Flag.Seen);
            foreach (long uid in uids)
            {
                imap.MoveByUID(uid, "Inbox/Seen");
            }
            imap.Close();
        }
    }
};
' VB.NET version:

Imports Limilabs.Mail
Imports Limilabs.Client.IMAP
Imports System.Collections.Generic

Public Module Module1
    Public Sub Main(ByVal args As String())

        Using imap As New Imap()
            imap.Connect("imap.example.com")   ' or ConnectSSL for SSL
            imap.UseBestLogin("user", "password")

            imap.SelectInbox()
            Dim uids As List(Of Long) = imap.Search(Flag.Seen)
            For Each uid As Long In uids
                imap.MoveByUID(uid, "Inbox/Seen")
            Next
            imap.Close()
        End Using

    End Sub
End Module

You can also use bulk methods to move, copy and delete emails:

// C# version

using (Imap imap = new Imap())
{
    imap.Connect("imap.example.com");
    imap.Login("user", "password");

    imap.SelectInbox();
    List<long> uids = imap.Search(Flag.Seen);
    imap.MoveByUID(uids, "Inbox/Seen");
    imap.Close();
}
' VB.NET version:

Using imap As New Imap()
	imap.Connect("imap.example.com")
	imap.Login("user", "password")

	imap.SelectInbox()
	Dim uids As List(Of Long) = imap.Search(Flag.Seen)
	imap.MoveByUID(uids, "Inbox/Seen")
	imap.Close()
End Using

List all folders using IMAP

IMAP protocol sometimes calls folders mailboxes. It’s not very fortunate as mailbox usually means email address (john.smith@example.com) or account attached to an email address.

You can use Mail.dll .NET IMAP component to retrieve a list of all IMAP folders existing on the server, by using GetFolders method. It returns a list of FolderInfo objects. You can use this object to get a folder name (FolderInfo.Name). You can also use FolderInfo instance as a parameter for SelectFolderInfo() method to access this folder.

// C# version:

using Limilabs.Mail;
using Limilabs.Client.IMAP;
using System;

class Program
{
    static void Main(string[] args)
    {
        using (Imap imap = new Imap())
        {
            imap.Connect("imap.example.com");   // or ConnectSSL
            imap.UseBestLogin("user", "password");

            foreach (FolderInfo folder in imap.GetFolders())
            {
                Console.WriteLine(folder.Name);
            }
            imap.Close();
        }
    }
};
' VB.NET version:

Imports Limilabs.Mail
Imports Limilabs.Client.IMAP

Public Module Module1
    Public Sub Main(ByVal args As String())

        Using imap As New Imap()
            imap.Connect("imap.example.com")  ' or ConnectSSL
            imap.UseBestLogin("user", "password")

            For Each folder As FolderInfo In imap.GetFolders()
                Console.WriteLine(folder.Name)
            Next
            imap.Close()
        End Using

    End Sub
End Module

FolderInfo object contains detailed information about the folder (Name, SeparatorChar, Flags)

You can read more about folder management using IMAP.

On some servers it is possible to get information about the purpose (spam, sent items) of each IMAP folder.

Save images embedded in HTML email to disk using IMAP

This article shows how to save all images embedded in HTML email message to disk. The messages are downloaded using Mail.dll .NET IMAP library and IMAP protocol.

In most cases HTML body of the message references such images using special “cid:” protocol, that specifies Content-ID of the image that should be used:

This is our <strong>brand new</strong> logo: <br />
<img src="cid:logo@example.com" />

In such case actual image is embedded inside an email, as part of the mime tree, as an element related to HTML body and with content-disposition header set to inline. This means that invoking GetMessageByUID method is going to download entire email message, including all images. This makes message bigger, but images don’t need to be stored on your web server (remember that emails tend to be archived for years).

Mail.dll exposes all attachments as well-known .NET collections. There are 4 collections that may contain attachments:

  • IMail.Attachments – all attachments (includes Visuals, NonVisuals and Alternatives).
  • IMail.Visuals – visual elements, files that should be displayed to the user, such as images embedded in an HTML email.
  • IMail.NonVisuals – non visual elements, “real” attachments.
  • IMail.Alternatives – alternative content representations, for example ical appointment.

As you can see the most interesting from this article’s point of view is IMail.Visuals collection. As with regular attachments, visual elements are represented by MimeData objects.

// C#

using Limilabs.Client.IMAP;
using Limilabs.Mail;
using Limilabs.Mail.MIME;
using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
       using (Imap imap = new Imap())
       {
           imap.Connect("imap.example.com");
           imap.UseBestLogin("user", "password");

           imap.SelectInbox();

           List<long> uids = imap.Search(Flag.Unseen);
           foreach (long uid in uids)
           {
               var eml = imap.GetMessageByUID(uid);
               IMail email = new MailBuilder()
                   .CreateFromEml(eml);
               Console.WriteLine(email.Subject);

               foreach (MimeData mime in email.Visuals)
               {
                   mime.Save(@"c:\" + mime.SafeFileName);
               }
           }
           imap.Close();
       }
    }
};
' VB.NET

Imports Limilabs.Client.IMAP
Imports Limilabs.Mail
Imports Limilabs.Mail.MIME
Imports System
Imports System.Collections.Generic

Public Module Module1
    Public Sub Main(ByVal args As String())

        Using imap As New Imap()
            imap.Connect("imap.example.com")
            imap.UseBestLogin("user", "password")

            imap.SelectInbox()
            Dim uids As List(Of Long) = imap.Search(Flag.Unseen)

            For Each uid As Long In uids
                Dim eml = imap.GetMessageByUID(uid)
                Dim email As IMail = New MailBuilder() _
                    .CreateFromEml(eml)
                Console.WriteLine(email.Subject)

                For Each mime As MimeData In email.Attachments
                    mime.Save("c:\" + mime.SafeFileName)
                Next
            Next
            imap.Close()
        End Using

    End Sub
End Module

You can also save attachment to stream MimeData.Save(Stream stream), get direct access to it as stream MemoryStream MimeData.GetMemoryStream()
or as byte array using byte[] MimeData.Data property.

You can also use SaveHtmlAs method to save entire message as regular HTML page with all required images and styles to a single folder:

// C#

IMail email = ...
email.SaveHtmlAs(@"c:\tmp\email.html");
' VB.NET

Dim email As IMail = ...
email.SaveHtmlAs("c:\tmp\email.html")

What is also worth mentioning is the fact that you can use Content-Id to search through IMail.Visuals collection:

// C#

IMail email = ...;
MimeData logo = email.Visuals["logo@example.com"];
// VB.NET

Dim email As IMail = ...
Dim logo As MimeData = email.Visuals("logo@example.com")