Recipe 17.10. Getting POP3 Emails


Problem

You want to access emails from an application, perhaps just to get a quick count of available emails or to get the complete contents.

Solution

Sample code folder: Chapter 17\Pop3Email

Use the TcpClient class in the System.Net. Sockets namespace. The Pop3 class presented here wraps this class with supporting code to make it easier to access your emails.

Discussion

The following class code creates Pop3 objects to simplify accessing emails from a standard POP3 server. Note that some servers require SSL or other authentication, in which case this code will need modification. For standard POP3 servers, it works well as presented.

Create a new Windows Forms application, add a new class named Pop3.vb, and use this code for its definition:

 Public Class Pop3    ' ----- The default TCP/IP port number for POP3 is 110.    Public Port As Integer = 110    Public Messages As Integer = 0    Private Const CommandFailure As String = "-ERR"    Private Pop3Server As TcpClient    Private CommandSender As NetworkStream    Private ContentReceiver As StreamReader    Public Sub Connect(ByVal serverName As String, _          ByVal userName As String, ByVal password As String)       ' ----- Initiate the connection to a POP3 server.       Dim commandData As String       Dim contentBuffer() As Byte       Dim responseString As String       Dim parts() As String       ' ----- Connect to the POP3 server.       Try          Pop3Server = New TcpClient(serverName, Port)          CommandSender = Pop3Server.GetStream()          ContentReceiver = New StreamReader(CommandSender)       Catch          Throw       End Try       If (userName <> "") Then          ' ----- Authenticate with the user ID.          commandData = "USER " & userName & vbCrLf          contentBuffer = _             System.Text.Encoding.ASCII.GetBytes( _             commandData.ToCharArray())          CommandSender.Write(contentBuffer, 0, _             contentBuffer.Length)          responseString = ContentReceiver.ReadLine()          If (Left(responseString, Len(CommandFailure)) = _                CommandFailure) Then             Throw New Exception("Invalid user name.")          End If          ' ----- Send the authenticating password.          commandData = "PASS " & password & vbCrLf          contentBuffer = _             System.Text.Encoding.ASCII.GetBytes( _             commandData.ToCharArray())          CommandSender.Write(contentBuffer, 0, _             contentBuffer.Length)          responseString = ContentReceiver.ReadLine()          If (Left(responseString, Len(CommandFailure)) = _                CommandFailure) Then             Throw New Exception("Invalid password.")          End If       End If       ' ----- Logged in. On some servers, the PASS command       '       is not enough to push the server into a       '       transaction state. Send a STAT command twice.       commandData = "STAT" + vbCrLf       contentBuffer = System.Text.Encoding.ASCII.GetBytes( _          commandData.ToCharArray())       CommandSender.Write(contentBuffer, 0, _          contentBuffer.Length)       responseString = ContentReceiver.ReadLine()       ' ----- Get a count of the messages.       commandData = "STAT" + vbCrLf       contentBuffer = System.Text.Encoding.ASCII.GetBytes( _          commandData.ToCharArray())       CommandSender.Write(contentBuffer, 0, _          contentBuffer.Length)       responseString = ContentReceiver.ReadLine()       If (Left(responseString, Len(CommandFailure)) = _             CommandFailure) Then          Throw New Exception( _             "Could not retrieve message count.")       End If       ' ----- The response includes two integers: a count       '       and a size, separated by a space. Skip over       '       the "+OK" part also.       parts = Split(responseString, " ")       Messages = Val(parts(1))    End Sub    Public Sub Disconnect()       ' ----- Disconnect from the   POP3 server.       Dim commandData As String       Dim contentBuffer() As Byte       Dim responseString As String       ' ----- Tell the server we're through.       commandData = "QUIT" & vbCrLf       contentBuffer = System.Text.Encoding.ASCII.GetBytes( _          commandData.ToCharArray())       CommandSender.Write(contentBuffer, 0, _          contentBuffer.Length)       responseString = ContentReceiver.ReadLine()       ' ----- End the connection.       ContentReceiver.Close()       CommandSender.Close()         Pop3Server.Close()    End Sub    Function GetMessage(ByVal whichMessage As Integer) _          As String       ' ----- Retrieve a single email message.       Dim commandData As String       Dim contentBuffer() As Byte       Dim responseString As String       Dim theMessage As New System.Text.StringBuilder       Dim oneLine As String       ' ----- Check for an invalid message.       If (whichMessage < 1) Or (whichMessage > Messages) Then          Throw New ArgumentOutOfRangeException(whichMessage, _             "Messages are numbered from 1 to the number " & _             "identified by the Messages property.")       End If       Try          ' ----- Request the message.          commandData = "RETR " & whichMessage & vbCrLf          contentBuffer = _             System.Text.Encoding.ASCII.GetBytes( _             commandData.ToCharArray())          CommandSender.Write(contentBuffer, 0, _             contentBuffer.Length)          responseString = ContentReceiver.ReadLine()          If (Left(responseString, Len(CommandFailure)) = _                CommandFailure) Then             Throw New Exception("Message retrieval failed.")          End If          ' ----- The message is all data until a line with          '       a single dot (.) appears.          Do While (ContentReceiver.EndOfStream = False)             oneLine = ContentReceiver.ReadLine()             If (oneLine = ".") Then Exit Do             theMessage.AppendLine(oneLine)          Loop       Catch ex As InvalidOperationException          MsgBox("Message retrieval failed: " & ex.Message)       End Try       ' ----- Return the constructed message.       Return theMessage.ToString()    End Function End Class 

Return to Form1, and add three TextBox controls named ServerName, UserName, and UserPassword. Set the UserPassword control's PasswordChar field to the asterisk character (*). Add a ListBox control named MessageList and two Button controls named ActGet and ActView. Set the Button controls' Text properties to Get Messages and View Message, respectively. Add informational labels if desired. The form should look like the one in Figure 17-12.

Figure 17-12. Controls for the POP3 sample


Now add the following code to Form1's class template:

 Private POP3Connection As Pop3 = Nothing Private Sub ActGet_Click(ByVal sender As System.Object, _       ByVal e As System.EventArgs) Handles ActGet.Click    ' ----- Initiate a POP3 connection.    Dim counter As Integer    ' ----- First, disconnect any previous connection.    If (POP3Connection IsNot Nothing) Then       Try          POP3Connection.Disconnect()       Catch ex As Exception          ' ----- Ignore.       End Try    End If    POP3Connection = Nothing    ' ----- Clear any previous messages.    MessageList.Items.Clear()    ' ----- Try the new connection.    Try         POP3Connection = New Pop3       POP3Connection.Connect(ServerName.Text, _          UserName.Text, UserPassword.Text)    Catch ex As Exception       MsgBox("Connection failure: " & ex.Message)       POP3Connection = Nothing       Return    End Try    ' ----- How many messages?    If (POP3Connection.Messages = 0) Then       MsgBox("No messages found.")       POP3Connection.Disconnect()       POP3Connection = Nothing       Return    End If    ' ----- Show each message.    For counter = 1 To POP3Connection.Messages       MessageList.Items.Add("Message Number " & counter)    Next counter End Sub Private Sub ActView_Click(ByVal sender As System.Object, _       ByVal e As System.EventArgs) Handles ActView.Click    ' ----- Show a message.    Dim whichMessage As Integer    Dim parts As String()    Dim content As String    ' ----- Which message? Each item has the format:    '          Message Number x    If (MessageList.SelectedIndex = -1) Then Return    parts = Split(CStr(MessageList.SelectedItem), " ")    whichMessage = CInt(Val(parts(2)))    ' ----- Get the content.    content = POP3Connection.GetMessage(whichMessage)    ' ----- Show the content.    MsgBox(content) End Sub Private Sub MessageList_DoubleClick(ByVal sender As Object, _       ByVal e As System.EventArgs) _       Handles MessageList.DoubleClick    ' ----- Same as the View button.    ActView.PerformClick() End Sub Private Sub Form1_FormClosing(ByVal sender As Object, _       ByVal e As System.Windows.Forms.FormClosingEventArgs) _       Handles Me.FormClosing    ' ----- Disconnect before leaving.    On Error Resume Next    If (  POP3Connection IsNot Nothing) Then       POP3Connection.Disconnect()       POP3Connection = Nothing    End If End Sub 

When you successfully connect to a POP3 server through the ActGet button, it displays a simple list of each message stored on the server. It's not as good as a real email program such as Microsoft Outlook because it hasn't yet read even the sender name or subject text, but it does add one entry for each available message. Clicking on the ActView button retrieves the content for one email message from the server through the Pop3 class's GetMessage() method. The connection to the email server is closed when the form closes.

Figure 17-13 shows the content from a test email retrieved from a POP3 server. This rather short sample email arrives with considerable overhead in the header details. The message body is near the end, and it shows the email was sent using HTML content.

Figure 17-13. An email retrieved from a POP3 server





Visual Basic 2005 Cookbook(c) Solutions for VB 2005 Programmers
Visual Basic 2005 Cookbook: Solutions for VB 2005 Programmers (Cookbooks (OReilly))
ISBN: 0596101775
EAN: 2147483647
Year: 2006
Pages: 400

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net