19.3 Receiving Mail


Receiving mail is considerably more complex than sending it. For instance, where a simple HELO command is sufficient to access most SMTP servers (a fact that is the source of much forged email and spam), retrieving email generally requires providing both a username and a password. SMTP uses only 14 different commands, and a simple email client can be implemented with just five of them. POP3, however, has 12 commands, almost all of which a client must be able to handle; IMAP4 has 24 different commands.

The JavaMail API is designed around the idea that you're retrieving messages from an IMAP or perhaps an NNTP server. That is, it assumes the server can return headers separate from the messages they belong to, search through mailboxes, provide the storage for the messages rather than the client, and so forth. The JavaMail API provides less of what you need for client-oriented mail access protocols, such as POP3, that assume the client stores and manages the mail archive, but it still gives you the tools to download the mail from the server. You just have to implement your own storage system on the client.

We'll begin with the simpler POP protocol, then move on to IMAP. From the perspective of JavaMail, IMAP can be viewed largely as POP plus some commands for manipulating folders. For simple programs that operate only on the INBOX folder, POP and IMAP clients are more or less the same.

There are about 12 steps to reading a remote mailbox (the number of steps can vary a little, since some steps are optional or can be combined with or replaced by others):

  1. Set up the properties you'll use for the connection.

  2. Construct the Authenticator you'll use for the connection.

  3. Get a Session object with Session.getDefaultInstance( ) .

  4. Use the session's getStore( ) method to return a Store .

  5. Connect to the store.

  6. Get the INBOX folder from the store with the getFolder() method.

  7. Open the INBOX folder.

  8. Open the folder you want inside the INBOX folder. Repeat as many times as necessary to reach the folder you're seeking.

  9. Get the messages from the folder as an array of Message objects.

  10. Iterate through the array of messages, processing each one in turn using the methods of the Message class. For instance, you might print out each message or simply display the sender, subject, and other vital information in a GUI for the user to select from, as in Figure 19-3.

  11. Close the folder.

  12. Close the store.

Figure 19-3. A GUI for selecting mail messages

Each of these steps is individually quite simple. The first is to set up the properties for the mail session. Properties you might want to set include mail.host , mail.store.protocol , mail.user , mail.pop3.user , and mail.pop3.host . However, you don't absolutely need to set any of these. If the Session will only be used to retrieve mail, an empty Properties object is enough. For example:

 Properties props = new Properties( ); 

Next, you'll want to create an instance of the javax.mail.Authenticator class (more properly, an instance of a concrete subclass of the abstract Authenticator class) that can ask the user for a password. For now, we'll simply hardcode those values and pass null instead of an actual Authenticator . We'll fix this later when we discuss authentication:

 Authenticator a = null; 

Next, use these Properties and Authenticator objects to get a Session instance, like this:

 Session session = Session.getDefaultInstance(props, a); 

Ask the session for a store for the provider. Here, we want a provider for POP3:

 Store store = session.getStore("POP3"); 

Finally, you're ready to actually connect to the store using the connect( ) method. You'll need to provide the host to connect to and the username and password to use:

 store.connect("mail.cloud9.net", "elharo", "my_password"); 

You can pass null for the password to indicate that the previously specified Authenticator should be queried for the password.

Now that the store is connected, you're ready to open a folder in the store. This step is really more oriented to IMAP than POP, since POP servers don't keep track of different folders. They simply provide all of a user's incoming mail as one undifferentiated amalgam. For purposes of the JavaMail API, POP3 providers use the folder name INBOX:

 Folder inbox = store.getFolder("INBOX"); 

The folder is closed when you get it. You can perform some operations on a closed folder including deleting or renaming it, but you can't get the messages out of a closed folder. First you have to open it. You can open a folder for read access by passing the mnemonic constant Folder.READ_ONLY to the open( ) method for read access, or Folder.READ_WRITE for read/write access:


Now you're ready to download the messages with the getMessages( ) method, which returns an array containing all the messages in the folder:

 Message[] messages = inbox.getMessages( ); 

(If you were using IMAP instead of POP, this step would not actually download the messages. Each one would stay on the server until you accessed it specifically . You'd just get a pointer to the actual message.)

The Message class provides many methods for working with individual messages. It has methods to get the various header fields of the message, get the content of the message, reply to the message, and more. We'll discuss these soon, when we talk about the Message and MimeMessage classes. For now, we'll do just about the simplest thing imaginableprint each message on System.out using the message's writeTo( ) method:

 for (int i = 0; i < messages.length; i++) {   System.out.println("------------ Message " + (i+1)     + " ------------");    messages[i].writeTo(System.out); } 

Once you're done with the messages, close the folder and then close the message store with the aptly named close() methods:

 inbox.close(false); store.close( ); 

The false argument to the folder's close( ) method indicates that we do not want the server to actually expunge any deleted messages in the folder. We simply want to break our connection to this folder.

Example 19-4 puts this all together with a simple program that downloads and prints out the contents of a specified POP mailbox. Messages are simply dumped on System.out in the default encoding. The servers, usernames, and so forth are all hardcoded. However, Example 19-4 quickly demonstrates most of the key points of receiving mail with the JavaMail API. A more advanced program would include an appropriate GUI.

Example 19-4. POP3Client
 import javax.mail.*; import javax.mail.internet.*; import java.util.*; import java.io.*; public class POP3Client {   public static void main(String[] args) {          Properties props = new Properties( );      String host = "utopia.poly.edu";     String username = "eharold";     String password = "mypassword";     String provider = "pop3";     try {       // Connect to the POP3 server       Session session = Session.getDefaultInstance(props, null);       Store store = session.getStore(provider);       store.connect(host, username, password);              // Open the folder       Folder inbox = store.getFolder("INBOX");       if (inbox == null) {         System.out.println("No INBOX");         System.exit(1);       }         inbox.open(Folder.READ_ONLY);              // Get the messages from the server       Message[] messages = inbox.getMessages( );       for (int i = 0; i < messages.length; i++) {         System.out.println("------------ Message " + (i+1)           + " ------------");         messages[i].writeTo(System.out);       }        // Close the connection        // but don't remove the messages from the server       inbox.close(false);       store.close( );            }      catch (Exception ex) {       ex.printStackTrace( );     }       } } 

Here's some sample output I got when I pointed it at an account I don't use much:

 D:\JAVA\JNP3\examples>  java POP3Client  ------------ Message 1 ------------ Received: (from eharold@localhost)         by utopia.poly.edu (8.8.8/8.8.8) id QAA05728         for eharold; Tue, 30 Nov 1999 16:14:29 -0500 (EST) Date: Tue, 30 Nov 1999 16:14:29 -0500 (EST) From: Elliotte Harold <eharold@utopia.poly.edu> Message-Id: <199911302114.QAA05728@utopia.poly.edu> To: eharold@utopia.poly.edu Subject: test Content-Type: text X-UIDL: 87e3f1ba71738c8f772b15e3933241f0 Status: RO hello you ------------ Message 2 ------------ Received: from russian.cloud9.net (russian.cloud9.net [ .4])         by utopia.poly.edu (8.8.8/8.8.8) with ESMTP id OAA28428         for <eharold@utopia.poly.edu>; Wed, 1 Dec 1999 14:05:06 -0500 ( Received: from [] (macfaq.dialup.cloud9.net [168.100.203         by russian.cloud9.net (Postfix) with ESMTP id 24B93764F         for <eharold@utopia.poly.edu>; Wed,  1 Dec 1999 14:02:50 -0500 Mime-Version: 1.0 X-Sender: macfaq@mail.cloud9.net Message-Id: <v04210100b46b1f97969d@[]> Date: Wed, 1 Dec 1999 13:55:40 -0500 To: eharold@utopia.poly.edu From: Elliotte Rusty Harold <elharo@macfaq.com> Subject: New system Content-Type: text/plain; charset="us-ascii" ; format="flowed" X-UIDL: 01fd5cbcf1768fc6c28f9c8f934534b5 Just thought you'd be happy to know that now that I've got my desk moved over from my old apartment, I've finally ordered the Windows NT system I've been promising for months. -- David 

About the only change you'd need to make to port this program to IMAP would be setting the provider variable to imap instead of pop3 .

Java Network Programming
Java Network Programming, Third Edition
ISBN: 0596007213
EAN: 2147483647
Year: 2003
Pages: 164

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