In today's computing world, most people rely on such programs as Microsoft Outlook or Eudora to handle all their email wants. But what happens when you need to seriously customize the way it works? OK, so Outlook now supports VBA scripting, but that still leaves you having to have Outlook installed and handle its object model. In this article, I will teach you the basics of communicating with a POP3 internet server, and reading mail.
Making a POP3 Client
Well, lets start with the basics first. POP3 stands for Post Office Protocol version 3. It is (along with IMAP) the standard protocol for receiving email across a network. You only need several things to connect. These include a valid username and password, and the address of the POP server. For those of you using a dial up connection, this address will probably look something like this:
Where ispname is the name of your Internet Service Provider. That is it as far as the normal email client goes, but when you have to do the business yourself, you need to know a little more about how everything works.
To start with, you need to connect to the correct port. Usually, the standard port for POP communications is port 110. If you know that you Local Area Network uses a different port, then you will need to make sure that you set that when connecting.
For this article, I used the Winsock control to operate with. I will now give a few details about how the Winsock control operates.
The Winsock control does not provide us with many properties, but the ones we have, along with the methods and events make it a very powerful control. If you have read my previous article about the Winsock control (see Communicating over a network) then you will know how easy it is to connect two PCs together and send some data. In that example, we had to define a standard protocol for sending messages. First we sent the type of content, then the size and then the content. To communicate with a POP server, you need to understand the commands used.
A good way to learn about the commands is by downloading the trial version of MDaemon (http://www.mdaemon.com/) This is a very good mail server that allows you to see all the messages that are sent and received when it communicates with another server.
Anyway, let me explain how things work.
When you send some data, you have a keyword first, such as USER, then the value, and then a vbCrlf character. Below I have listed some of the commands used in the sample project:
- USER - Sends the username
- PASS - Sends the password
- QUIT - Ends the current session
- DELE - Deletes a mail message from the server
- RSET - Undos any changes made within the current session
- STAT - Returns the number of messages on the server
- RETR - Retrieves the content of a message
I won't go through what each one does because the descriptions are pretty self explanatory. Anyway, after sending a message, you need to listen for a reply. If everything is working, then you will receive a +OK message back from the server. If there is a problem, then the server will return a -ER message. Here is some code that sends a user id:
Winsock1.SendData "USER Sam" & vbCrlf
To get the response from the server, we need to look in the Winsock1_DataArrival event. This event does not actually provide us with any data, it just notifies us that data is arriving and how big it is. We need to use the Winsock1.GetData method to retrieve something:
Private Sub WInsock1_DataArrival(ByVal bytesTotal As Long) Dim strData As String Winsock1.GetData strData, vbString WholeThing = WholeThing & strData ResponseState = Left$(WholeThing, 3) End Sub
The GetData method accepts two parameters. The first is a variable where the data retrieved can be placed in and the second is the format in which to receive the data. In the example above, we fill the ResponseState variable with what will either be a +OK command or a -ER command. The best thing to do is to make the ResponseState variable a private/public member of the module so that the program can detect whether it is ok to proceed.
The Winsock control also provides a Winsock1_Error event. This event gives us plenty of information about the error, helping us to tell the user what has happened. Here is a sample Winsock1_Error event procedure:
Private Sub Winsock1_Error(ByVal Number As Integer, _ Description As String, ByVal Scode As Long, _ ByVal Source As String, ByVal HelpFile As String, _ ByVal HelpContext As Long, CancelDisplay As Boolean) Msgbox "Error number: " & Number & vbCrlf & _ "Error Description: " & Description End Sub
The thing that I like very much about doing your own POP comms is that you can choose to leave the messages on the server. This way you can be on the road, download your email and read it, then reply to the important ones and delete them from the server so you know they are gone, and then disconnect leaving the rest of your mail intact, allowing you to pick it up back at the office/home. You could extend the sample program to store the email on your hard drive, so that you can look at it later.
If you are thinking about deploying email access on the web, then I wouldn't try and just put a VB control on there because it runs very slowly and requires you to download the runtimes and any additional controls onto your machine if they are not already there. I would suggest writing a Perl or Java program or possibly wrapping it into a VB DLL and using ASP to view it. To get a good look at a service that deploys web email, and allows you to download email from other servers, check out BT's Talk21 service: http://www.talk21.com/
So, lets make a connection! First, I will put out the code and after you have had a look through it, I will explain what's going on:
Private Function ConnectToPOP(strServer As String, _ strUser As String, strPwd As String)As Boolean Dim strOut As String ConnectToPOP = False Winsock1.Connect strServer, 110 ' Change the port as necessary WaitFor 1, strOut If strOut = "+OK" Then Winsock1.SendData "USER " & strUser & vbCrlf Else ConnectToPOP = False Exit Function End If WaitFor 1, strOut If strOut = "+OK" Then Winsock1.SendData "PASS " & strPwd & vbCrlf Else ConnectToPOP = False Exit Function End If WaitFor 1, strOut If strOut = "+OK" Then ConnectToPOP = True Else ConnectToPOP = False End If End Function
As you can see, the function takes a bit of getting used to. Remember, after each time we send some data, we have to wait for a response. I have wrapped the waiting code into a procedure called WaitFor (you can see this in the sample project). Firstly, we use the Winsock1.Connect method and specifiy the server and the port to connect on. We then wait for a response, and check that the response is +OK, otherwise we bail out. If the response was +OK, then we send the username using the USER command. Again, we wait for a response and if everything is ok, we send the password. If after all this sending, waiting and checking things are still ok, then we are now connected to the server!
The next thing we want to do is to download a list of the messages on the server. To do this we use the STAT command. In the sample code you will notice that I have used a User Defined Type structure and an array to store each message in. You may come up with another way that is better or more suited to your needs, but for the moment, I will just present the UDT:
Type tMailItem From As String Subject As String DateSent As String Bytes As Long Body As String Loaded As Boolean Deleted As Boolean End Type
The names tell you quite basically what each one does. I would just like to point out that the last two properties, Loaded and Deleted play an important part in the sample project. The Loaded flag tells us if the message is currently loaded in the viewing window. The Deleted flag tells us if the message is to be deleted from the server when we disconnect. Any incorrect handling of the Deleted flag could cause serious problems in your application.
I hope that this article has given you enough understanding to be able to download the sample project (a fully functional POP client) and look through the code and know what's going on.