POP3 Tutorial

Applies to: Rebex Total Pack, Rebex Mail Pack, Rebex POP3

Namespaces and assemblies 

For information on TLS/SSL security, check out our TLS/SSL Tutorial!

There are several assemblies which have to be reference in your project to be able to use all features of Mail for .NET described here. Rebex.Pop3.dll is needed for any POP3 operations and contains the Pop3 class and others in Rebex.Net namespace. Rebex.Mail.dll contains classes that make it possible to read, create and write e-mail messages in MIME format and contains the MailMessage class in Rebex.Mail namespace and a number of classes that represent mail message headers in Rebex.Mime.Headers namespace.Rebex.Common.dll and Rebex.Networking.dll need to be referenced too as assembly referenced by Rebex.Pop3.dll and Rebex.Mail.dll .

To gain access to all described functionality, reference the two assemblies from your project and import the following namespaces in your source files:

using Rebex.Net;
using Rebex.Mail;
using Rebex.Mime.Headers;
Imports Rebex.Net
Imports Rebex.Mail
Imports Rebex.Mime.Headers

POP3 basics - connecting, logging in and disconnecting 

Typical POP3 session goes like this:

  • Connect to the POP3 server
  • Login - authenticate with user name and password
  • Work with messages in your mailbox
  • Disconnect

POP3 is basically a single-session and single-folder protocol. While you are connected and authenticated, you are not going to be informed when any new message arrives, and you only have access to messages that were available at the time of authentication. Because of this, many POP3 servers only allow a single session for a single account at a time, so don't forget to call Disconnect method when you are done with the mailbox, or you might experience problems connecting again until the previous session either expires or the Ftp object is claimed by .NET's garbage collector. Also, due to the nature of the POP3 protocol, you will need to connect periodically if you wish to check for new messages.

And now let's look at some sample code.

// create client and connect
Pop3 client = new Pop3();
client.Connect("pop3.example.org");

// authenticate
client.Login("username", "password");

// work with messages
//...

// disconnect
client.Disconnect();
'create client and connect
Dim client As New Pop3
client.Connect("pop3.example.org")

'authenticate
client.Login("username", "password")

'work with messages
'...

'disconnect
client.Disconnect()

Authenticating to a POP3 server 

The POP3 protocol supports several authentication methods. Normally, you just have to supply your credentials to the Login method. The library will automatically choose the best (most secure) authentication method available and log you in.

Additionally, you can retrieve the list of supported authentication methods using the Pop3 object's GetSupportedAuthenticationMethods method, and specify which one is to be used for login. (Or specify Pop3Authentication.Auto that will do this automatically.)

Pop3 client = new Pop3();
client.Connect("pop3.example.org");

// authenticate - let the library choose the best method
client.Login("username", "password");

// or choose one yourself
// client.Login("username", "password", Pop3Authentication.Plain);
'create client and connect
Dim client As New Pop3
client.Connect("pop3.example.org")

'authenticate - let the library choose the best method
client.Login("username", "password")

'or choose one yourself
'client.Login("username", "password", Pop3Authentication.Plain)

Authentication using NTLM 

By default, the Login method won't try NTLM authentication, because it might not work correctly in some situations. However, if NTLM does work with your server, nothing stops you from using it. Just read the information on Microsoft Exchange in the FAQ first if you use that server.

// create client and connect
Pop3 client = new Pop3();
client.Connect("pop3.example.org");

// authenticate using NTLM
client.Login("domain\\username", "password", Pop3Authentication.Ntlm);
' create client and connect
Dim client As New Pop3()
client.Connect("pop3.example.org")

'authenticate using NTLM
client.Login("domain\username", "password", SmtpAuthentication.Ntlm)

NTLM also makes it possible to authenticate as the user under whose context your application is running. This makes it possible for the user to log in without the need to specify his or her password.

// create client and connect
Pop3 client = new Pop3();
client.Connect("pop3.example.org");

// authenticate using NTLM
client.Login(Pop3Authentication.Ntlm);
' create client and connect
Dim client As New Pop3()
client.Connect("pop3.example.org")

' authenticate using NTLM's single-sign-on feature
client.Login(SmtpAuthentication.Ntlm)

Obtaining info about the mailbox 

There are two pieces of information available - the number of messages in the mailbox can be obtained using the GetMessageCount method and the total size of them using the GetMailboxSize method.

// create client, connect and log in
Pop3 client = new Pop3();
client.Connect("pop3.example.org");
client.Login("username", "password");

Console.Write("Number of messages in the mailbox is: ");
Console.Write(client.GetMessageCount());
Console.WriteLine();

client.Disconnect();
'create client, connect and log in
Dim client As New Pop3
client.Connect("pop3.example.org")
client.Login("username", "password")

Console.Write("Number of messages in the mailbox is: ")
Console.Write(client.GetMessageCount())
Console.WriteLine()

client.Disconnect()

Sequence numbers and unique IDs 

The POP3 protocol uses two different IDs to identify messages.

ID type Description
int sequenceNumber A number between 1..[number of messages in the POP3 mailbox]. This number does not change during POP3 session - even when one or more messages are deleted, the remaining messages retaing their sequence number. However, these numbers are specific to a single session - when you disconnect and log in again later, the same sequence numbers will be assigned to different messages.
string uniqueID Unlike sequence number, the message unique ID is permanent and does not change between sessions. A message will retain its unique ID until it is deleted.

Most POP3 methods that deal with messages only accept sequenceNumber as a parameter for message identification. However, it is quite simple to map a given unique ID to a corresponding sequence number and vice-versa. Just retrieve the message list using use GetMessageList method, use its Find method to get info about the given message and read its UniqueId or SequenceNumber properties to get the required ID.

string localPath = "";

// some valid unique ID we already retrieved in past
string uniqueId = "abcd13954986";

// create client, connect and log in
Pop3 client = new Pop3();
client.Connect("pop3.example.org");
client.Login("username", "password");

// get message list
Pop3MessageCollection messages = client.GetMessageList();
Pop3MessageInfo info = messages.Find(uniqueId);
if (info == null)
{
    Console.WriteLine("Message not found, probably deleted?");
}
else
{
    // read the sequence number
    int sequenceNumber = info.SequenceNumber;

    // and use it to download the message
    client.GetMessage(sequenceNumber, localPath);
}

client.Disconnect();
Dim localPath As String = ""

'some valid unique ID we already retrieved in past
Dim uniqueId As String = "abcd13954986"

'create client, connect and log in
Dim client As New Pop3
client.Connect("pop3.example.org")
client.Login("username", "password")

'get message list
Dim messages As Pop3MessageCollection = client.GetMessageList()
Dim info As Pop3MessageInfo = messages.Find(uniqueId)
If info Is Nothing Then
    Console.WriteLine("Message not found, probably deleted?")
Else
    'read the sequence number
    Dim sequenceNumber As Integer = info.SequenceNumber

    'and use it to download the message
    client.GetMessage(sequenceNumber, localPath)
End If

client.Disconnect()

Retrieving the message list 

To get a list of messages in the mailbox, call the GetMessageList method. It accepts an optional parameter that specifies what information to retrieve from the server:

Parameter value Description
Pop3ListFields.SequenceNumber Message sequence number for current session.
Pop3ListFields.UniqueID Message unique ID that is permanent and does not change between sessions.
Pop3ListFields.Length Message data size in bytes.
Pop3ListFields.Fast Combination of SequenceNumber, UniqueId and Length. This is the default for GetMessageList method if no fieldsargument is specified.
Pop3ListFields.FullHeaders Same as Fast, but also downloads the message headers of each message as Date, From, To, Subject or Message ID fields. This variant is the most verbose, but also the slowest. See the next section for more discussion about this.

These fields are bit flags, which means that combinations of SequenceNumber|Length and UniqueId|Length are also possible - use bitwise OR operator for this (| in C#, Or in VB.NET).

The following code shows how to download a message list and show a unique ID and From/Subject headers of each message:

// create client, connect and log in
Pop3 client = new Pop3();
client.Connect("pop3.example.org");
client.Login("username", "password");

// get message list - full headers
Pop3MessageCollection messages =
        client.GetMessageList(Pop3ListFields.FullHeaders);

// display info about each message
Console.WriteLine("UID | From | To | Subject");
foreach (Pop3MessageInfo message in messages)
{
    Console.WriteLine
    (
        "{0} | {1} | {2} | {3}",
        message.UniqueId,
        message.From,
        message.To,
        message.Subject
    );
}

client.Disconnect();
'create client, connect and log in
Dim client As New Pop3
client.Connect("pop3.example.org")
client.Login("username", "password")

'get message list - full headers
Dim messages As New Pop3MessageCollection
messages = client.GetMessageList(Pop3ListFields.FullHeaders)

'display info about each message
Console.WriteLine("UID | From | To | Subject")
Dim message As Pop3MessageInfo
For Each message In messages
    Console.WriteLine( _
     "{0} | {1} | {2} | {3}", _
     message.UniqueId, _
     message.From, _
     message.To, _
     message.Subject)
Next

client.Disconnect()

Downloading message headers 

The simplest method for downloading all message headers is to call GetMessageList with parameter Pop3ListFields.FullHeaders, as described in the Retrieving the message list tutorial. It retrieves headers for all messages in the mailbox.

However, as mentioned earlier, this might take a very long time if there are too many messages in the mailbox or the connection bandwidth is limited. If this is the case, it is advisable to only ask for the message list with the IDs and length (Pop3ListFields.Fast) and retrieve message headers of each message separately using the GetMessageInfo method - and this can even be done later or only when needed.

// create client, connect and log in
Pop3 client = new Pop3();
client.Connect("pop3.example.org");
client.Login("username", "password");

int sequenceNumber = 1; // the first message

Pop3MessageInfo info = client.GetMessageInfo
(
    sequenceNumber,
    Pop3ListFields.FullHeaders
);

Console.Write("Date: " + info.Date);
Console.Write("From: " + info.From);
Console.Write("Subject: " + info.Subject);

client.Disconnect();
'create client, connect and log in
Dim client As New Pop3
client.Connect("pop3.example.org")
client.Login("username", "password")

Dim sequenceNumber As Integer = 1 'the first message

Dim info As Pop3MessageInfo = client.GetMessageInfo( _
 sequenceNumber, _
 Pop3ListFields.FullHeaders)

Console.Write("Date: " & info.Date.ToString())
Console.Write("From: " & info.From.ToString())
Console.Write("Subject: " & info.Subject)

client.Disconnect()

Downloading messages 

Finally, let's start downloading some messages! It is very simple - just call the GetMailMessage method and you retrieve an instance of the MailMessage class that contains the message corresponding to the supplied sequence number. You can read message headers, body and attachments from it, modify it, save it to disk or send it again using our Smtp class. For more info about this, check out our MailMessage class tutorial.

Alternatively, if all you need is to download the message data and save it to disk or write it into a stream, and you don't need to access the message content in any way at the moment, just call the GetMessage method instead. This won't return an instance of MailMessage and just writes the message data into the supplied local path or stream.

// create client, connect and log in
Pop3 client = new Pop3();
client.Connect("pop3.example.org");
client.Login("username", "password");

// get message list
Pop3MessageCollection list = client.GetMessageList();

if (list.Count == 0)
{
    Console.WriteLine("There are no messages in the mailbox.");
}
else
{
    // download the first message
    MailMessage message = client.GetMailMessage(list[0].SequenceNumber);
    //...
}

client.Disconnect();
'create client, connect and log in
Dim client As New Pop3
client.Connect("pop3.example.org")
client.Login("username", "password")

'get message list
Dim list As Pop3MessageCollection = client.GetMessageList()

If list.Count = 0 Then
    Console.WriteLine("There are no messages in the mailbox.")
Else
    'download the first message
    Dim message As MailMessage = client.GetMailMessage(list(0).SequenceNumber)
    '...
End If

client.Disconnect()

Deleting and undeleting messages 

Deleting messages in POP3 is quite straightforward, but might seem a bit awkward at first. To delete a message, call the Delete method with message sequence number as an argument.

The Delete method marks a message as deleted. These won't appear in subsequent message lists, but will actually only be removed from the mailbox after a call to Disconnect method. You can "undelete" messages that were not yet removed using one of the following methods:

  • Calling Undelete method. This recovers messages marked as deleted. It will appear in message lists again and won't be removed when the session ends.
  • Calling Disconnect(true). This will undelete all deleted messages and disconnect from the server. No deleted messages will be removed, and the next time you connect to this mailbox, they will be there again. Calling Disconnect() without parameter will commit all changes and remove all messages marked as deleted.
// create client, connect and log in
Pop3 client = new Pop3();
client.Connect("pop3.example.org");
client.Login("username", "password");

int sequenceNumber = 1;

// delete the first message
client.Delete(sequenceNumber);

// undo the delete operation
client.Undelete();

// and delete it again
client.Delete(sequenceNumber);

// commit changes and disconnect
client.Disconnect();
'create client, connect and log in
Dim client As New Pop3
client.Connect("pop3.example.org")
client.Login("username", "password")

Dim sequenceNumber As Integer = 1

'delete the first message
client.Delete(sequenceNumber)

'undo the delete operation
client.Undelete()

'and delete it again
client.Delete(sequenceNumber)

'commit changes and disconnect
client.Disconnect()

Using events and logging communication 

In case something goes wrong, it is very useful to have a log of commands sent to the server and responses received from it for diagnostics purposes. To make this possible, the Pop3 class declares the following events:

Event name Description
CommandSent Occurs when a command (for example CAPA or RETR) is sent to the server.
ResponseRead Occurs when response is received from the server.
StateChanged Occurs when the session state changes, such as from Disconnected to Ready, from Ready to Sending or from Sending to Reading.
TransferProgress Occurs when a block of message data is received from the server.

The CommandSent or ResponseRead events are particularly useful for the purpose of generating a communication log and the TransferProgress event can be used by a GUI application to display amount of transfered data or a progress bar.

Pop3 client = new Pop3();
client.CommandSent += client_CommandSent;
client.ResponseRead += client_ResponseRead;
client.Connect("pop3.example.org");
Dim client As New Pop3
AddHandler client.CommandSent, AddressOf client_CommandSent
AddHandler client.ResponseRead, AddressOf client_ResponseRead
client.Connect("pop3.example.org")

Back to tutorial list...