Retrieve E-Mail Through POP3

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Hi Professionals,<br/> <br/> I found these tutorials and codes regarding Retrieve E-Mail Through POP3 on an e-book entitled <a><span class=b24-booktitle>Microsoft Visual Basic .NET Programmers Cookbook. I understand what each functions/codes are but how do i design the GUI/interface to fit the codes? <br/> <br/> Please advise. Thank you in advance.<br/> <br/> Best Regards,<br/> Md Azmil
<pre lang=x-vbnet>Problem

You want to retrieve messages from a POP3 mail server.
Solution

Create a dedicated class that sends POP3 commands over a TCP connection.
Discussion

POP3 is a common e-mail protocol used to download messages from a mail server. POP3, like many Internet protocols, defines a small set of commands that are sent as simple ASCII-encoded messages over a TCP connection (typically on port 110).

Heres a listing of a typical POP3 dialogue, starting immediately after the client makes a TCP connection:

Server sends:+OK <22689.1039100760@mail.prosetech.com>
Client sends:USER <UserName>
Server sends:+OK
Client sends:PASS <Password>
Server sends:+OK
Client sends:LIST
Server sends:+OK
Server sends:<Message list terminated by a period>
Clients sends:RETR <MessageNumber>
Server sends:+OK
Server sends:<Message body terminated by a period>
Client sends:QUIT
Server sends:+OK

To add this functionality to your .NET applications, you can create a Pop3Client class that encapsulates all the logic for communicating with a POP3 server. Your application can then retrieve information about messages using the Pop3Client class. Well explore this class piece by piece in this recipe. To see the complete code, download the recipes for this chapter in this books sample files.

The first step is to define a basic skeleton for the Pop3Client class. It should store a TcpClient instance as a member variable, which will be used to send all network messages. You can also add generic Send and ReceiveResponse messages, which translate data from binary form into the ASCII encoding used for POP3 communication.

Public Class Pop3Client
Inherits System.ComponentModel.Component

The internal TCP connection.
Private Client As New TcpClient()
Private Stream As NetworkStream

The connection state.
Private _Connected As Boolean = False
Public ReadOnly Property Connected() As Boolean
Get
Return _Connected
End Get
End Property

Private Sub Send(ByVal message As String)
Send the command in ASCII format.
Dim MessageBytes() As Byte = Encoding.ASCII.GetBytes(message)
Stream.Write(MessageBytes, 0, MessageBytes.Length)

Debug.WriteLine(message)
End Sub

Private Function GetResponse() As String
Build up the response string until the line termination
character is found.
Dim Character, Response As String
Do
Character = Chr(Stream.ReadByte()).ToString()
Response &= Character
Loop Until Character = Chr(13)

Response = Response.Trim(New Char() {Chr(13), Chr(10)})
Debug.WriteLine(Response)
Return Response
End Function

(Other code omitted.)

End Class

Youll notice that the Pop3Client is derived from the Component class. This nicety allows you to add and configure an instance of the Pop3Client class at design time using Microsoft Visual Studio .NET.

You can also add constants for common POP3 commands. One easy way to add constants is to group them in a private class nested inside Pop3Client, as shown here:

Some command constants.
Private Class Commands
These constants represent client commands.
Public Const List As String = "LIST" & vbNewLine
Public Const User As String = "USER "
Public Const Password As String = "PASS "
Public Const Delete As String = "DELE "
Public Const GetMessage As String = "RETR "
Public Const Quit As String = "QUIT" & vbNewLine

These two constants represent server responses.
Public Const ServerConfirm As String = "+OK"
Public Const ServerNoMoreData As String = "."
End Class

The next step is to create a basic method for connecting to the POP3 server and disconnecting from it. Because Pop3Client derives from Component, it indirectly implements IDisposable. Therefore, you can also override the Dispose method to ensure that connections are properly cleaned up when the class is disposed.

Public Sub Connect(ByVal serverName As String, ByVal userName As String, _
ByVal password As String)
If Connected Then Me.Disconnect()

Connect to the POP3 server
(which is almost always at port 110).
Client.Connect(serverName, 110)
Stream = Client.GetStream()

Check if connection worked.
CheckResponse(GetResponse())

Send user name.
Send(Commands.User & userName & vbNewLine)

Check response.
CheckResponse(GetResponse())

Send password.
Send(Commands.Password & password & vbNewLine)

Check response.
CheckResponse(GetResponse())

_Connected = True
End Sub

Public Sub Disconnect()
If Connected Then
Send(Commands.Quit)
CheckResponse(GetResponse())
_Connected = False
End If
End Sub

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then Disconnect()
MyBase.Dispose(disposing)
End Sub

Note

Some mail servers will not allow the password to be transmitted in clear text. In this case, you will need to manually encrypt the password information first using the appropriate algorithm before you submit it to the Pop3Client class.

The Pop3Client class uses a private CheckResponse procedure, which verifies that the servers message is the excepted confirmation and throws an exception if it isnt.

Private Sub CheckResponse(ByVal response As String)
If Not (response.Substring(0, 3) = Commands.ServerConfirm) Then
Client.Close()
_Connected = False
Throw New ApplicationException("Response " & response & _
" not expected.")
End If
End Sub

The only remaining step is to implement three higher-level methods: GetMessageList, which the client calls to retrieve a list of message headers, GetMessageContent, which the client calls to retrieve the body of a single message, and DeleteMessage, which is typically used to remove a message after its content is downloaded.

To support the GetMessageList method, you need to create a simple class for storing message header information, which includes a message number and size in bytes.

Public Class MessageHeader

Private _Number As Integer
Private _Size As Integer

Public ReadOnly Property Number() As Integer
Get
Return _Number
End Get
End Property

Public ReadOnly Property Size() As Integer
Get
Return _Size
End Get
End Property

Public Sub New(ByVal number As Integer, ByVal size As Integer)
Me._Number = number
Me._Size = size
End Sub

End Class

The GetMessageList method returns an array of MessageHeader objects. When the server returns a period (.) on a separate line, the list is complete.

Public Function GetMessageList() As MessageHeader()
If Not Connected Then Throw New _
InvalidOperationException("Not connected.")

Send(Commands.List)
CheckResponse(GetResponse())

Dim Messages As New ArrayList()
Do
Dim Response As String = GetResponse()

If Response = Commands.ServerNoMoreData Then
No more messages.
Return CType(Messages.ToArray(GetType(MessageHeader)), _
MessageHeader())
Else
Create an EmailMessage object for this message.
Include the header information.
Dim Values() As String = Response.Split()
Dim Message As New MessageHeader(Val(Values(0)), Val(Values(1)))

Messages.Add(Message)
End If
Loop
End Function

To retrieve the information for a single message, the client calls GetMessageContent with the appropriate message number. The message content includes headers that indicate the sender, recipient, and path taken, along with the message subject, priority, and body. A more sophisticated version of the Pop3Client might parse this information into a class that provides separate properties for these details.

Public Function GetMessageContent(ByVal messageNumber As Integer) As String
If Not Connected Then Throw New _
InvalidOperationException("Not connected.")

Send(Commands.GetMessage & messageNumber.ToString() & vbNewLine)
CheckResponse(GetResponse)
Dim Line, Content As String

Retrieve all message text until the end point.
Do
Line = GetResponse()
If Line = Commands.ServerNoMoreData Then
Return Content
Else
Content &= Line & vbNewLine
End If
Loop
End Function

Finally DeleteMessage removes a message from the server based on its message number.

Public Sub DeleteMessage(ByVal messageNumber As Integer)
If Not Connected Then Throw New _
InvalidOperationException("Not connected.")

Send(Commands.Delete & messageNumber.ToString() & vbNewLine)
CheckResponse(GetResponse())
End Sub

You can test the Pop3Client class with a simple program such as the following one, which retrieves all the messages for a given account:

Public Module Pop3Test

Public Sub Main()
Get the connection information.
Dim Server, Name, Password As String
Console.Write("POP3 Server: ")
Server = Console.ReadLine()
Console.Write("Name: ")
Name = Console.ReadLine()
Console.Write("Password: ")
Password = Console.ReadLine()
Console.WriteLine()

Connect.
Dim POP3 As New Pop3Client()
POP3.Connect(Server, Name, Password)

Retrieve a list of message, and display the corresponding content.
Dim Messages() As MessageHeader = POP3.GetMessageList()
Console.WriteLine(Messages.Length().ToString() & " messages.")

Dim Message As MessageHeader
For Each Message In Messages
Console.WriteLine(New String("-"c, 60))
Console.WriteLine("Message Number: " & Message.Number.ToString())
Console.WriteLine("Size: " & Message.Size.ToString())
Console.WriteLine()
Console.WriteLine(POP3.GetMessageContent(Message.Number))
Console.WriteLine(New String("-"c, 60))
Console.WriteLine()
Next

Console.WriteLine("Press Enter to disconnect.")
Console.ReadLine()
POP3.Disconnect()
End Sub

End Module

The output for a typical session is as follows:

POP3 Server: mail.server.com
Name: matthew
Password: opensesame

1 messages.
------------------------------------------------------------------------------
Message Number: 1
Size: 1380

Return-Path: <someone@somewhere.com>
Delivered-To: somewhere.com%someone@somewhere.com
Received: (cpmta 15300 invoked from network); 5 Dec 2002 06:57:13 -0800
Received: from 66.185.86.71 (HELO fep01-mail.bloor.is.net.cable.rogers.com)
by smtp.c000.snv.cp.net (209.228.32.87) with SMTP; 5 Dec 2002 06:57:13 -0800
X-Received: 5 Dec 2002 14:57:13 GMT
Received: from fariamat ([24.114.131.60])
by fep01-mail.bloor.is.net.cable.rogers.com
(InterMail vM.5.01.05.06 201-253-122-126-106-20020509) with ESMTP
id <20021205145711.SJDZ4718.fep01- mail.bloor.is.net.cable.rogers.com@fariamat>
for <someone@somewhere.com>; Thu, 5 Dec 2002 09:57:11 -0500
Message-ID: <004c01c29c6f$186c5150$3c837218@fariamat>
From: <someone@somewhere.com>
To: <someone@somewhere.com>
Subject: Test Message
Date: Thu, 5 Dec 2002 10:00:48 -0500
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2600.0000
X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
X-Authentication-Info: Submitted using SMTP AUTH LOGIN at fep01--
mail.bloor.is.net.cable.rogers.com from [24.114.131.60] at
Thu, 5 Dec 2002 09:57:11 -0500
Status: RO
X-UIDL: Pe9pStHkIFc7yAE

Hi! This is a test message!
------------------------------------------------------------------------------

Press Enter to disconnect.

[/code]
<br/>

View the full article
 
Back
Top