Recipe 19.7 Reading Email


Problem

You need to read mail.

Solution

Use a JavaMail Store.

Discussion

The JavaMail API is designed to be easy to use. Store encapsulates the information and access methods for a particular type of mail storage; the steps for using it are listed in the sidebar.

Ian's Basic Steps: Reading Email Using Store

Here is how you read email using Store:

  1. Get a Session object using Session.getDefaultInstance( ) . You can pass System.getProperties( ) as the Properties argument.

  2. Get a Store from the Session object.

  3. Get the root Folder.

  4. If the root Folder can contain subfolders, list them.

  5. For each Folder that can contain messages, call getMessages( ), which returns an array of Message objects.

  6. Do what you will with the messages (usually, display the headers and let the user select which message to view).


Sun provides a Store class for the IMAP transport mechanism, and optionally for POP3.[3] In these examples I use the Unix mbox protocol[4] (when I started with Unix there was no POP3 protocol; it was traditional to access your mail spool file directly on a server). However, you could use all these programs with the POP or IMAP stores just by passing the appropriate protocol name where "mbox" appears in the following examples. I've tested several of the programs using Sun's POP store and several POP servers (CUCIpop and PMDF).

[3] The POP3 Store classes must be downloaded and manually installed from http://java.sun.com/products/javamail/.

[4] This is free (GPL) software, which can be downloaded from the Giant Java Tree, http://www.gjt.org.

I delete most of the email I get on one of my systems, so there were only two messages to be read when I ran my first " mailbox lister" program:

daroad.darwinsys.com$ java MailLister mbox localhost - - /var/mail/ian Getting folder /var/mail/ian. Name: ian(/var/mail/ian) No New Messages irate_client@nosuchd  Contract in Hawaii                       mailer-daemon@kingcr  Returned mail: Data format error         daroad.darwinsys.com$

The main program shown in Example 19-8 takes all five arguments from its command line.

Example 19-8. MailLister.java
import com.darwinsys.util.*; import java.util.Properties; import javax.mail.*; import javax.mail.internet.*; /** * List all available folders. */ public class MailLister {     static StringAlign fromFmt =          new StringAlign(20, StringAlign.JUST_LEFT);     static StringAlign subjFmt =          new StringAlign(40, StringAlign.JUST_LEFT);     public static void main(String[] argv) throws Exception {         String fileName = MailConstants.PROPS_FILE_NAME;         String protocol = null;         String host = null;         String user = null;         String password = null;         String root = null;         // If argc == 1, assume it's a Properties file.         if (argv.length == 1) {             fileName = argv[0];             FileProperties fp = new FileProperties(fileName);             fp.load( );             protocol = fp.getProperty(MailConstants.RECV_PROTO);             host = fp.getProperty(MailConstants.RECV_HOST);             user = fp.getProperty(MailConstants.RECV_USER);             password = fp.getProperty(MailConstants.RECV_PASS);             root = fp.getProperty(MailConstants.RECV_ROOT);         }         // If not, assume listing all args in long form.         else if (argv.length == 5) {             protocol = argv[0];             host = argv[1];             user = argv[2];             password = argv[3];             root = argv[4];         }         // Otherwise give up.         else {             System.err.println(                 "Usage: MailLister protocol host user pw root");             System.exit(0);         }         boolean recursive = false;         // Start with a Session object, as usual         Session session = Session.getDefaultInstance(             System.getProperties( ), null);         session.setDebug(false);         // Get a Store object for the given protocol         Store store = session.getStore(protocol);         store.connect(host, user, password);         // Get Folder object for root, and list it         // If root name = "", getDefaultFolder( ), else getFolder(root)         Folder rf;         if (root.length( ) != 0) {             System.out.println("Getting folder " + root + ".");             rf = store.getFolder(root);         } else {             System.out.println("Getting default folder.");             rf = store.getDefaultFolder( );         }         rf.open(Folder.READ_WRITE);         if (rf.getType( ) == Folder.HOLDS_FOLDERS) {             Folder[] f = rf.list( );             for (int i = 0; i < f.length; i++)                 listFolder(f[i], "", recursive);         } else                 listFolder(rf, "", false);     }     static void listFolder(Folder folder, String tab, boolean recurse)     throws Exception {         folder.open(Folder.READ_WRITE);         System.out.println(tab + "Name: " + folder.getName( ) + '(' +             folder.getFullName( ) + ')');         if (!folder.isSubscribed( ))             System.out.println(tab + "Not Subscribed");         if ((folder.getType( ) & Folder.HOLDS_MESSAGES) != 0) {             if (folder.hasNewMessages( ))                 System.out.println(tab + "Has New Messages");             else                 System.out.println(tab + "No New Messages");             Message[] msgs = folder.getMessages( );             for (int i=0; i<msgs.length; i++) {                 Message m = msgs[i];                 Address from = m.getFrom( )[0];                 String fromAddress;                 if (from instanceof InternetAddress)                     fromAddress = ((InternetAddress)from).getAddress( );                 else                     fromAddress = from.toString( );                 StringBuffer sb = new StringBuffer( );                 fromFmt.format(fromAddress, sb, null);                 sb.    append("  ");                 subjFmt.format(m.getSubject( ), sb, null);                 System.out.println(sb.toString( ));             }         }         if ((folder.getType( ) & Folder.HOLDS_FOLDERS) != 0) {             System.out.println(tab + "Is Directory");         if (recurse) {             Folder[] f = folder.list( );             for (int i=0; i < f.length; i++)                 listFolder(f[i], tab + "", recurse);             }         }     } }

This program has the core of a full mail reader but doesn't actually fetch the articles. To display a message, you have to get it (by number) from the folder, then call methods like getSubject( ) , getFrom( ), and others. The listFolder( ) method does this to obtain identifying information on each message, and formats them using the StringAlign class from Recipe Recipe 3.5.

If we add a GUI and a bit of code to get all the relevant header fields, we can have a working mail reader. We'll show the messages in a tree view, since some protocols let you have more than one folder containing messages. For this we'll use a JTree widget, the Swing GUI component for displaying text or icons in a tree-like view. The objects stored in a JTree must be Node objects, but we also want them to be Folders and Messages. I handled this by subclassing DefaultMutableNode and adding a field for the folder or message, although you could also subclass Folder and implement the Node interface. Arguably, the way I did it is less "pure OO," but also less work. Example 19-9 is my MessageNode ; FolderNode is similar, but simpler in that its toString( ) method calls only the Folder's getName( ) method.

Example 19-9. MessageNode.java
import javax.mail.*; import javax.mail.internet.*; import javax.swing.tree.*; /** A Mutable Tree Node that is also a Message. */ public class MessageNode extends DefaultMutableTreeNode {     Message m;     StringAlign fromFmt = new StringAlign(20, StringAlign.JUST_LEFT);     StringAlign subjFmt = new StringAlign(30, StringAlign.JUST_LEFT);     MessageNode(Message m) {         this.m = m;     }     public String toString( ) {         try {             Address from = m.getFrom( )[0];             String fromAddress;             if (from instanceof InternetAddress)                 fromAddress = ((InternetAddress)from).getAddress( );             else                 fromAddress = from.toString( );             StringBuffer sb = new StringBuffer( );             fromFmt.format(fromAddress, sb, null);             sb.    append("  ");             subjFmt.format(m.getSubject( ), sb, null);             return sb.toString( );         } catch (Exception e) {             return e.toString( );         }     } }

These are all put together into a mail reader in Recipe 19.8.



Java Cookbook
Java Cookbook, Second Edition
ISBN: 0596007019
EAN: 2147483647
Year: 2003
Pages: 409
Authors: Ian F Darwin

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