Monthly Archives: February 2011

Providing client’s certificate required by server

This topic explains how to authenticate the client using a certificate. IMAP servers might be configured to request the client to authenticate using its certificate during SSL negotiation. The client can either process, or inform the server that it has no suitable certificate.

The example below demonstrates how to use ComponentPro IMAP library and handle the CertificateRequired event of the ImapClient to find a suitable certificate for the client authentication:

C#:

public void HandleCertificateRequiredEvent()
{
   // Create a new instance.
   ImapClient client = new ImapClient();
   client.CertificateRequired += client_CertificateRequired;
   // Connect to the IMAP server.
   client.Connect("myserver", 143, SecurityMode.Explicit);
   // Authenticate.
   client.Authenticate("userName", "password");
   // Do something here...
   // ...
   // Disconnect.
   client.Disconnect();
}
void client_CertificateRequired(object sender, ComponentPro.Security.CertificateRequiredEventArgs e)
{
   // Load certificates from the local machine.
   X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
   my.Open(OpenFlags.ReadOnly);
   // Retrieve a list of available certificates.
   X509Certificate2Collection certs = my.Certificates;
   // If no certificate found, return.
   if (certs.Count == 0)
   {
       e.Certificate = null;
       return;
   }
   // Show all certificates.
   Console.WriteLine("Select certificate:");
   for (int i = 0; i <= certs.Count; i++)
   {
       if (i == 0)
       {
           Console.WriteLine(string.Format("{0}. [Nothing, skip this step]", i));
           continue;
       }
       Console.WriteLine(string.Format("{0}. {1}", i, certs[i - 1].SubjectName.Name));
   }
   // And ask user to choose an appropriate certificate.
   while (true)
   {
       Console.Write(string.Format("Select certificate [0 - {0}]: ", certs.Count));
       int certIndex;
       try
       {
           certIndex = int.Parse(Console.ReadLine());
       }
       catch
       {
           Console.WriteLine("ERROR: Wrong certificate index input!");
           continue;
       }
       if (certIndex > 0 && certIndex <= certs.Count)
       {
           e.Certificate = certs[certIndex];
           return;
       }
       if (certIndex == 0)
           break;
       Console.WriteLine(string.Format("ERROR: You must enter number between 0 and {0}.", certs.Count));
   }
}

VB.NET

Public Sub HandleCertificateRequiredEvent()
    ' Create a new instance.
    Dim client As New ImapClient()
    AddHandler client.CertificateRequired, AddressOf client_CertificateRequired
    ' Connect to the IMAP server.
    client.Connect("myserver", 143, SecurityMode.Explicit)
    ' Authenticate.
    client.Authenticate("userName", "password")
    ' Do something here...
    ' ...
    ' Disconnect.
    client.Disconnect()
End Sub
Private Sub client_CertificateRequired(ByVal sender As Object, ByVal e As ComponentPro.Security.CertificateRequiredEventArgs)
    ' Load certificates from the local machine.
    Dim my As New X509Store(StoreName.My, StoreLocation.CurrentUser)
    my.Open(OpenFlags.ReadOnly)
    ' Retrieve a list of available certificates.
    Dim certs As X509Certificate2Collection = my.Certificates
    ' If no certificate found, return.
    If certs.Count = 0 Then
        e.Certificate = Nothing
        Return
    End If
    ' Show all certificates.
    Console.WriteLine("Select certificate:")
    For i As Integer = 0 To certs.Count
        If i = 0 Then
            Console.WriteLine(String.Format("{0}. [Nothing, skip this step]", i))
            Continue For
        End If
        Console.WriteLine(String.Format("{0}. {1}", i, certs(i - 1).SubjectName.Name))
    Next i
    ' And ask user to choose an appropriate certificate.
    Do
        Console.Write(String.Format("Select certificate [0 - {0}]: ", certs.Count))
        Dim certIndex As Integer
        Try
            certIndex = Integer.Parse(Console.ReadLine())
        Catch
            Console.WriteLine("ERROR: Wrong certificate index input!")
            Continue Do
        End Try
        If certIndex > 0 AndAlso certIndex <= certs.Count Then
            e.Certificate = certs(certIndex)
            Return
        End If
        If certIndex = 0 Then
            Exit Do
        End If
        Console.WriteLine(String.Format("ERROR: You must enter number between 0 and {0}.", certs.Count))
    Loop
End Sub

Creating a new mail message

Introduction to the Non-MIME and MIME messages

Email messages can generally be separated into two broad categories:

  • Non-MIME messages.
  • MIME messages.

Non-MIME messages

A non-MIME message refers to any message that is created in the original format defined in RFC822. These messages are generally made up of simple text and Uuencoded or Yencoded attachments.

MIME messages

MIME (Multipurpose Internet Mail Extensions) was defined to expand upon the original RFC822 message structure’s ability to transport files and the inability to create a complex-multipart message. These types of messages are usually recognizable by the “MIME-VERSION : 1.0″ header line and the MIME-boundary separating the parts of the message.

Since almost all email readers today are MIME compatible, it is recommended to create all messages as MIME messages. Create a non-MIME messages only if it is likely that the mail reader used to receive the message will be unable to read MIME.

The examples below show how to create a simple mail message using the UltimateMail component:

C#:

// Create a new instance of the MailMessage class.
MailMessage msg = new MailMessage();
msg.From.Add("john@somedomain.com");
msg.To.Add("someone@somedomain.com");
msg.Subject = "Hello";
msg.BodyText = "How are you?";

VB.NET:

' Create a new instance of the MailMessage class.
Dim msg As New MailMessage()
msg.From.Add("john@somedomain.com")
msg.To.Add("someone@somedomain.com")
msg.Subject = "Hello"
msg.BodyText = "How are you?"