ProblemYou need to read mail. SolutionUse a JavaMail Store. DiscussionThe 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.
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).
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.javaimport 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.javaimport 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. |