Archive for the ‘Component’ Category

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

Send iCalendar meeting requests

Monday, May 10th, 2010

Mail.dll .NET email component has support for popular iCalendar standard.

iCalendar is used by most popular email clients like Outlook or GMail. It allows Internet users to send meeting requests and tasks to other Internet users, via email, or sharing files with an extension of .ics.

Recipients of the iCalendar data file (with supporting software, such as an email client or calendar application) can respond to the sender easily or counter propose another meeting date/time.

First make sure that your ‘usings’ or ‘Imports’ section includes all needed namespaces:

// C#

using Lesnikowski.Mail;
using Lesnikowski.Mail.Fluent;
using Lesnikowski.Mail.Appointments;
' VB.NET

Imports Lesnikowski.Mail
Imports Lesnikowski.Mail.Fluent
Imports Lesnikowski.Mail.Appointments

And now the code.

First we’ll create an appointment object add new event to it:

Appointment appointment = new Appointment();
Event e = appointment.AddEvent();

Then we need to set start and end dates:

e.Description = "Status meeting description";
e.Summary = "Status meeting summary";
e.Start = new DateTime(2010, 05, 10, 16, 00, 00);
e.End = new DateTime(2010, 05, 10, 17, 00, 00);

Now we’ll add all required and optional participants to it:

e.SetOrganizer(new Person("Alice", "alice@mail.com"));

e.AddParticipant(new Participant(
	"Bob", "bob@mail.com", ParticipationRole.Required, true));
e.AddParticipant(new Participant(
	"Tom", "tom@mail.com", ParticipationRole.Optional, true));
e.AddParticipant(new Participant(
	"Alice", "alice@mail.com", ParticipationRole.Required, true));

We’ll add an alarm to the event (set 15 minutes before the event start):

Alarm alarm = e.AddAlarm();
alarm.BeforeStart(TimeSpan.FromMinutes(15));

Finally we’ll create an email add the appointment to it and send it:

Mail.Text("Status meeting at 4PM.")
	.Subject("Status meeting")
	.From("alice@mail.com")
    .To("bob@mail.com")
    .AddAppointment(appointment)
    .UsingNewSmtp()
    .WithCredentials("alice@mail.com", "password")
	.Server("smtp.mail.com")
	.WithSSL()
	.Send();

The entire C# code looks as follows:

Appointment appointment = new Appointment();

Event e = appointment.AddEvent();
e.Description = "Status meeting description";
e.Summary = "Status meeting summary";
e.Start = new DateTime(2010, 05, 10, 16, 00, 00);
e.End = new DateTime(2010, 05, 10, 17, 00, 00);

e.SetOrganizer(new Person("Alice", "alice@mail.com"));

e.AddParticipant(new Participant(
	"Bob", "bob@mail.com", ParticipationRole.Required, true));
e.AddParticipant(new Participant(
	"Tom", "tom@mail.com", ParticipationRole.Optional, true));
e.AddParticipant(new Participant(
	"Alice", "alice@mail.com", ParticipationRole.Required, true));

Alarm alarm = e.AddAlarm();
alarm.BeforeStart(TimeSpan.FromMinutes(15));

Mail.Text("Status meeting at 4PM.")
	.Subject("Status meeting")
	.From("alice@mail.com")
    .To("bob@mail.com")
    .AddAppointment(appointment)
    .UsingNewSmtp()
    .WithCredentials("alice@mail.com", "password")
	.Server("smtp.mail.com")
	.WithSSL()
	.Send();

…and the VB.NET version:

Dim appointment As New Appointment()

Dim e As [Event] = appointment.AddEvent()
e.Description = "Status meeting description"
e.Summary = "Status meeting summary"
e.Start = New DateTime(2010, 5, 10, 16, 0, 0)
e.[End] = New DateTime(2010, 5, 10, 17, 0, 0)

e.SetOrganizer(New Person("Alice", "alice@mail.com"))

e.AddParticipant(New Participant( _
	"Bob", "bob@mail.com", ParticipationRole.Required, True))
e.AddParticipant(New Participant( _
	"Tom", "tom@mail.com", ParticipationRole.[Optional], True))
e.AddParticipant(New Participant( _
	"Alice", "alice@mail.com", ParticipationRole.Required, True))

Dim alarm As Alarm = e.AddAlarm()
alarm.BeforeStart(TimeSpan.FromMinutes(15))

Mail.Text("Status meeting at 4PM.") _
	.Subject("Status meeting") _
	.From("alice@mail.com") _
	.[To]("bob@mail.com") _
	.AddAppointment(appointment) _
	.UsingNewSmtp() _
	.WithCredentials("alice@mail.com", "password") _
	.Server("smtp.mail.com") _
	.WithSSL() _
	.Send()

You can download Mail.dll .NET email component 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