Hi Professionals,
I found these tutorials and codes regarding 'Retrieve E-Mail Through POP3' on an e-book entitled 'Microsoft Visual Basic .NET Programmer's Cookbook'. I understand what each functions/codes are but how do i design the GUI/interface to fit the codes?
Please advise. Thank you in advance.
Best Regards,
Md Azmil
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).
Here's 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. We'll explore this class piece by piece in this recipe. To see the complete code, download the recipes for this chapter in this book's 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
You'll 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 server's message is the excepted confirmation and throws an exception if it isn't.
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.