Posts Tagged ‘IMAP’

Free Yahoo! Mail via IMAP

Sunday, May 30th, 2010

It is possible to get direct Yahoo! IMAP access.
Yahoo! operates IMAP servers (imap.mail.yahoo.com in particular), which are globally accessible.

However they require a specific, but non-standard IMAP command to be sent before login is done. The command is: “ID (“GUID” “1″)”

// C#
imap.SendCommand(@"ID (""GUID"" ""1"")");
' VB
imap.SendCommand("ID (""GUID"" ""1"")")

There is also an IMAP server running at imap-ssl.mail.yahoo.com; it uses SSL on the standard port 993.

Here’s the full C# version of the code:

using (Imap imap = new Imap())
{
    imap.Connect("imap.mail.yahoo.com");
    imap.SendCommand(@"ID (""GUID"" ""1"")");

	imap.Login("user", "password");

	imap.SelectInbox();
	List<long> uidList = imap.Search(Expression.All());
	foreach (long uid in uidList)
	{
		IMail email = new MailBuilder()
    			.CreateFromEml(imap.GetMessageByUID(uid));
		Console.WriteLine(email.Subject);
	}
	imap.Close(true);
}

and VB.NET version:

Using imap As New Imap()
	imap.Connect("imap.mail.yahoo.com")
	imap.SendCommand("ID (""GUID"" ""1"")")

	imap.Login("user", "password")

	imap.SelectInbox()
	Dim uidList As List(Of Long) = imap.Search(Expression.All())
	For Each uid As Long In uidList
		Dim email As IMail = New MailBuilder() _
			.CreateFromEml(imap.GetMessageByUID(uid))
		Console.WriteLine(email.Subject)
	Next
	imap.Close(True)
End Using

Differences:
- non-standard command ID command is required before any other command.
- Examine explicitly requires CLOSE command (Imap.CloseCurrentFolder), otherwise subsequent SELECT (Imap.Select) has no effect and mailbox is still in read-only state
- IDLE is not implemented.
- SELECT for not existing folder does not create new folder.

You can download the latest version of Mail.dll .NET IMAP client here

Imap IDLE

Thursday, April 15th, 2010

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 Capability method to check server’s capability list

// C# code

using (Imap client = new Imap())
{
	client.ConnectSSL("imap.server.com");
	client.Capability().ForEach(Console.WriteLine);
	client.Close();
}
' VB.NET code

Using client As New Imap()
	client.ConnectSSL("imap.server.com")
	client.Capability().ForEach(Console.WriteLine)
	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

New Mail.dll tutorial video

Wednesday, April 7th, 2010

New Mail.dll tutorial video is out. You can watch it here:

Mail.dll tutorial video.

Delete email permanently in GMail

Tuesday, March 23rd, 2010

If you delete a message from your Inbox or one of your custom folders, it will still appear in [Gmail]/All Mail.

Here’s why: in most folders, deleting a message simply removes that folder’s label from the message, including the label identifying the message as being in your Inbox.

[Gmail]/All Mail shows all of your messages, whether or not they have labels attached to them.

If you want to permanently delete a message from all folders:

  1. Move it to the [Gmail]/Trash folder.
  2. Delete it from the [Gmail]/Trash folder.

All emails in [Gmail]/Spam and [Gmail]/Trash are deleted after 30 days.
If you delete a message from [Gmail]/Spam or [Gmail]/Trash, it will be deleted permanently.

Here’s how this looks like using Mail.dll IMAP client:

// C# version:

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

	// Find all emails we want to delete
	imap.SelectInbox();
	List<long> uids = imap.Search(
		Expression.Subject("email to delete"));

	// Delete each email permanently
	foreach (long uid in uids)
	{
		// Move to Trash
		long uidInTrash = (long)imap.MoveByUID(uid, "[Gmail]/Trash");

		// Delete from Trash
		imap.Select("[Gmail]/Trash");
		imap.DeleteMessageByUID(uidInTrash);
	}
	imap.Close(true);
}
' VB.NET version:

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

	' Find all emails we want to delete
	imap.SelectInbox()
	Dim uids As List(Of Long) = imap.Search(_
		Expression.Subject("email to delete"))

	' Delete each email permanently
	For Each uid As Long In uids
		' Move to Trash
		Dim uidInTrash As Long = imap.MoveByUID(uid, "[Gmail]/Trash")

		' Delete from Trash
		imap.[Select]("[Gmail]/Trash")
		imap.DeleteMessageByUID(uidInTrash)
	Next
	imap.Close(True)
End Using

Localized GMail IMAP Folders

Monday, March 22nd, 2010


There are no well-know names for common folders such as Drafts, Trash, Spam, … on IMAP servers.

The problem is even worse when you use localized version of IMAP client. GMail folder names are localized with respect to the user localization settings, so ‘[Gmail]/All Mail’ show as ‘[Gmail]/Todos’ to Spanish users for example.

Google and Apple developed a special IMAP command XLIST to address this issue.

IMAP XLIST command returns a list of folders and their well-know flags (\Inbox, \Drafts, \Trash, \Sent, \Spam).

Mail.dll IMAP client supports XLIST command. It is used automatically when server advertises support for this feature.

Take a look at the examples:

// C# version:

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

    CommonFolders folders = new CommonFolders(imap.GetFolders());

    Console.WriteLine("Inbox folder: " + folders.Inbox.Name);
    Console.WriteLine("Sent folder: " + folders.Sent.Name);

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

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

	Dim folders As New CommonFolders(imap.GetFolders())

	Console.WriteLine("Inbox folder: " + folders.Inbox.Name)
	Console.WriteLine("Sent folder: " + folders.Sent.Name)

	imap.Close(True)
End Using