If you were to ask the average person if there is anything to the Internet besides the Web and email, Im sure youd get no for an answer. Most programmers know that Javas strength, besides the platform-independence thing, lies in its networking capabilities. Knowing that, as well as knowing that email is such a huge part of everyday life, its not a reach to assume Java has email capabilities. Java does have these capabilities in JavaMail. This article tells you how to use JavaMail to send an email message and how to give Web applications a professional touch.
We all get annoying email, like those messages from users who dont know how the Caps Lock button works or spam mail. Of course, email was never meant to be annoying; the early pioneers who built the Internet intended it as a communication tool. One of those pioneers was Ray Tomlinson of the company Bolt, Beranek and Newman, which is now known as BBN Technologies and part of GTE.
In 1971, right about the time Reggie Jackson hit his historic 520-foot home run off a Tiger Stadium light tower during the All-Star game in Detroit, Tomlinson invented what we now know as email and sent the very first email message: Testing 1-2-3. He gave us the first functional email program about a year later, in 1972, when Jackson was about to become the first major-league baseball player with facial hair since 1914. But you already knew all that. Fast-forward 29 years: The novelty of email has been replaced by its status as an everyday part of life. Not only do we use email clients all the time, but now, with JavaMail, we can incorporate email into our Web applications as well.
Youve Got Mail
JavaMail Version 1.1.3 comes as an extension to the standard Java Development Kit (JDK), meaning that it is not included in any JDK download and must be downloaded separately. JavaMail works with the JavaBeans Activation Framework (JAF), which is also an extension of the JDK. This article presents a sample application that receives email via POP3. This means I need POP3 support, for which Ill use Suns free POP3 Provider. (Links to download these packages are listed in the References and Related Materials section of this article.)
The downloads of these products include various demos and documentation, but what youll need is three JAR files: activation.jar, mail.jar, and pop3.jar. First, Ill clarify the ingredients of this articles example. The mail.jar file is JavaMail. JavaMail requires the assistance of JAF, the activation.jar file, to handle the data content of the many different types of files that can be sent across the Internet. The activation.jar file handles many low- level tasks required by JavaMail, and chances are youll never use the classes in this archive unless you want to add attachments when sending email.
To receive mail, there are two main protocols in use today: POP3 and Internet Mail Access Protocol (IMAP). IMAP support is included in JavaMail and is superior to POP3 in virtually every way. The trouble is that POP3 is still much more widely used than IMAP. This is why, to have POP3 support when using JavaMail, you must download the POP3 Provider, which is pure Java but not included in the Java family in any way, not even as an extension. Also, JavaMail is built with client-side email in mind, and, as such, it cannot be used to build a mail server.
Attachment: Sample Code
Ill outline some key classes in JavaMail by showing you an example of a servlet that reads and sends regular text email and throws in a JavaServer Page (JSP) that acts as an error page, displaying exceptions and then sending a message to notify the appropriate personnel about the error.
The example servlet begins with a simple HTML form where a user enters values for his Simple Mail Transport Protocol (SMTP) and POP3 servers, user name, and password. The user name and password values are used for the POP3 server. Typically, SMTP servers dont require a login. The main servlet receives the parameters posted by the HTML form and (as shown in Figure 1) creates a list of email messages that are available to read.
Now Ill pick apart the code that gets you to this point. You first need to establish SMTP and POP3 services in the servlet before you can do anything. The SMTP host is used by JavaMail in a simple yet specific manner. When JavaMail needs to know the SMTP host name, it looks to the system Properties object for a property called smtp.mail.host; you must input the property and the propertys value. Setting up POP3 is a little more involved, but its an easy three-step process:
1. Get a Session object.
2. Get a Store object.
3. Connect to the Store.
A Session in the vernacular of JavaMail is not to be confused with an HttpSession of the servlet API. A JavaMail Session doesnt maintain the status, or state, of a connection as an HttpSession does. A Session object holds various user configuration properties, like the users email address and host names. Once you have the Session object, you can get the Store object by calling the Sessions getStore() method.
The code snippets in Figure 2 detail the process of setting up SMTP and POP3 support. As you can see in Figure 2, you supply the getStore() method with a String parameter, identifying what type of service youll need; in this case, its POP3. Finally, when you get the Store object, you can connect to the resource, using the host name, user name, and password supplied in the HTML form.
In the unabridged version of the code shown in Figure 2, I put the Store object to the HttpSession object so that I can use it after Ive logged on. If I didnt do this, Id need some way of recreating the Store object so that I could retrieve new messages during my HttpSession. Now that youre connected to a POP3 server, its time to get the mail. Now youll see the differences between POP3 and IMAP and how JavaMail makes life easy no matter what provider you use.
To get your mail, you need to instantiate a Folder object, which tells JavaMail where our messages are located on the mail server.
Folders are a natural concept for IMAP, but POP3 has no such thing. Fortunately, the JavaMail specification requires that POP3 providers implement a virtual folder called INBOX. This way, when you create the Store, using the method described earlier, you only need to change the string from POP3 to IMAP (or whatever mail-retrieving protocol comes down the pike).
After you create the folder, you can open it usingyou guessed itits open() method. The open() method takes an int as its parameter, which tells JavaMail what mode the folder will be in, or how you want to open the folder. Since this is an example of getting email through your browser, youll open the folder in read-only mode so that the messages stay on the server. Figure 2, section B, details the steps needed to retrieve email messages.
After youve gone through all the steps to set up POP3 and SMTP services and youve opened a folder on the host, youre ready to get the messages. Evoking the getMessages() method of the folder will give you an array of Message objects that you can use to create the message list. If youve ever used your favorite email client to view email source code, you know theres a lot more to an email message than just the body of the message. JavaMail gives you several methods in the Message class to get at that information, and the example uses a few of those methods to create the message list; namely, the ones that extract the date, sender, and subject of the message.
An important feature of JavaMail is that the Message class is lightweight. In laymans terms, that means you dont get parts of the message you havent asked for. So if your good buddy was gracious enough to send you an MPEG file of the entire movie Caddyshack, you wouldnt have to wait a week for it to download if your email client used JavaMail.
As shown in Figure 3, viewing an individual message from the list is one of the more involved portions of the servlet, which could get even more complicated quite easily. The details are in the read() method, where the Message you want to view is cast to, or changed into, a MimeMessage. Check the MimeMessage to see if its HTML mail; if so, just have the servlet send the message out through its OutputStream. If its regular text, the method formats the text a little, then sends it out to the browser; if its another type of MimeMessage called a MimeMultipart, that usually means there are attachments, and the example simply prints out what kind of attachments they are (i.e., their MIME types and their names).
Now that you have the lowdown on the key classes of retrieving and reading email, Ill get into what it takes to send email. Sending email is a little easier, except, as I mentioned before, if you want to send attachments. Ill leave it up to you to figure that one out.
Because the example doesnt send attachments, you get to use MimeMessage instead of MimeMultipart as the type of message to send. Once an instance of MimeMessage is available to use, you can employ some simple methods to construct the scary-looking email source I mentioned before. The example uses some of the methods of the MimeMessage object to set the sender, recipient, subject, and body of the message. These parameters are retrieved from an HTML form that the servlet itself puts out to a browser. After youve built the MimeMessage, you use one of the few methods of the Transport class called send() toyou guessed it againsend the message. The method takes the MimeMessage you created earlier as its parameter.
Thats it for sending email. All the code for sending messages is shown in Figure 2, section C.
One of the features I put into the servlet is a JSP error page. Of course, there are only a million things that could go wrong when sending an email across the Internet. If something does go wrong, the error will be captured and displayed along with some words that are meaningful to an actual user, and the cryptic text of the error will be sent as an email to somebody who can decipher its meaning (presumably to an IT person). Without going into lengthy detail about how JSP error pages work, Ill point you to Figure 2, section D, which shows the 3 lines of code youll need to send exceptions to a JSP error page.
Once the JSP has control of the application and has the Exception object, simply get the text of the Exception object, as shown in Figure 2, section E, and send it, using the same procedures I discussed for sending email. Figure 4 shows what happens when I try to log on to my POP3 server using an invalid password. The error page displays a brief message and explains that a message was sent to somebody who could do something about it. Figure 5 shows the message sent by the JSP error page. To spice up the page a little, you could add several other items of interest to the email, like query string parameters, cookie text, or headers.
More Email Ideas
Youve seen how using JavaMail in your Web applications is not difficult. In addition to being easy to use, itll give your Web applications a nice touch.
There are several different applications of JavaMail. You could set up some email accounts to receive messages of a different variety on your mail server. Using, for example, a servlet that reads a calendar file and sends an email to everyone in your company, reminding them of the cutoff date for month-end or inventory processing. A servlet could check inventory files and send email to appropriate personnel when levels reach a certain strike level, either high or low. Brainstorm a while, and youll find there are many ways to employ JavaMail in your company.
REFERENCES AND RELATED MATERIALS
BBN Technologies Web site: www.gte.com/AboutGTE/gto/bbnt/index.html
JavaBeans Activation Framework Web site: http://java.sun.com/beans/glasgow/jaf.html
JavaMail API Web site (to download JavaMail and POP3 Provider): www.java.sun.com/products/javamail/index.html
Figure 1: This list of email messages is displayed upon logging in to a POP3 server.
Code snippets from ServletMail.java
A) Setting up SMTP and POP3 services
Properties p = System.getProperties();
mailSession = Session.getInstance(p, null);
store = mailSession.getStore(pop3);
store.connect(pop3Svr, usr, pwd);
B) Retrieving messages
inbox = store.getFolder(INBOX);
messages = inbox.getMessages();
C) Sending messages
MimeMessage message = new MimeMessage(mailSession);
D) Sending an exception from a servlet to a JSP
. . .
RequestDispatcher rd = getServletContext().getRequestDispatcher(/error.jsp);
E) Getting an Exception ready to send as text
StringBuffer buffer = new StringBuffer();
StringWriter writer = new StringWriter();
Figure 2: These are code snippets from both ServletMail.java and error.jsp.
Figure 3: This message is displayed upon selecting a message from the list of emails.
Figure 4: This is the output of error.jsp after successfully sending an email about an error in ServletMail.
Figure 5: This detailed error message is sent by error.jsp.