Introduction to the Java Mail API

Learn how easy it is to develop e-mail applications using the Java Mail API

The design of the Java Mail API is a good example of Sun's continuing efforts to provide common API frameworks for the Java development community. Emphasizing these common frameworks, as opposed to vendor-specific solutions, bodes well for the creation of an increasingly open development environment.

On the e-mail messaging front, higher level (consumer) developers can shop around for the implementation of the common API framework that best fits their needs -- or even support multiple implementations simultaneously. Lower level implementation providers can develop solutions that ensure efficient access to their mail server products. As an example of what this means, a small startup company can concentrate on developing that killer mail client and be assured of easily supporting it for any mail system environment. And the bluechip IT giant can focus on providing widespread access to its newly developed industrial-strength mail services, assured of a rich wealth of application support. The big winners are the IS customers, who can mix and match the best vendor products or solutions to develop their systems yet still swap components as requirements dictate (whether these be performance, financial, or political).

One key to developing highly reusable and open API frameworks is to emphasize abstract interfaces in a way that supports existing standards but does not limit future enhancements or alternative implementations. The Java Mail API does just that! Furthermore, Sun is also rapidly developing -- or providing through third parties -- default implementations and utilities for the most commonly available protocols and standards. For example, default implementations such as POP3, SMTP, and IMAP protocol servers are currently available, so you can start developing that award-winning killer app now without having to reinvent the protocol wheel unless you want to (or really need to).

A close-up look at the Java Mail API

The layout of packages and classes in the Java Mail API demonstrates one of the primary goals of its designers -- that the level of effort required by the developer to build an application should be dictated by the complexity of the application and the level of control required by the developer for the application. In other words, keep the API as simple as possible. The example application included in this article and the examples that ship with the Java Mail API amply demonstrate this point. (For a brief look at Java Mail terminology, turn to our Java Mail Glossary.)

On first glance, the number of Java Mail API classes and the detailed layout of these classes may cause you to believe you're in for a heavy learning curve. But in reality, once you get working, you'll find that this API is a simple and handy tool for implementing robust mail/messaging functionality in your applications.

Analysis of the primary Java Mail API package classes provides insight into the common mechanics of e-mail messaging systems. A high-level overview of the classes in the relative order in which they are normally encountered in a typical application reveals the simplicity of the Java Mail API.

Although the Java Mail API contains many more classes than those discussed here, concentrating on some of the core classes to start with makes it easy to understand the essence of the API. The following is a detailed description of these core classes, which include javax.mail.Session, javax.mail.Store, javax.mail.Transport, javax.mail.Folder, and javax.mail.Message.

javax.mail.Session

The javax.mail.Session class is the top-level entry class for the Java Mail API, and its most commonly used methods provide the ability to control and load the classes that represent the service provider implementations (SPI) for various mail protocols. For example, instances of the javax.mail.Store and javax.mail.Session classes -- described below -- are obtained via the Session class. (Note: A service provider is a developer and/or vendor that provides an implementation for an API; examples of Java Mail API implementations include POP3, SMTP, and IMAP4 -- some are available from Sun, others via third parties.)

javax.mail.Store

The javax.mail.Store class is implemented by a service provider, such as a POP Mail implementation developer, and allows for read, write, monitor, and search access for a particular mail protocol. The javax.mail.Folder class is accessed through this class and is detailed below.

javax.mail.Transport

The javax.mail.Transport class is another provider-implemented class and is used for sending a message over a specific protocol.

javax.mail.Folder

The javax.mail.Folder class is implemented by a provider; it gives hierarchical organization to mail messages and provides access to e-mail messages in the form of javax.mail.Message class objects.

javax.mail.Message

The javax.mail.Message class is implemented by a provider and models all the details of an actual e-mail message, such as the subject line, sender/recipient e-mail address, sent date, and so on. The guidelines for providers who implement the javax.mail.Message dictate that the actual fetching of e-mail message components should be delayed as long as possible in order to make this class as lightweight as possible.

The Java Mail API and JAF

One design fact worth mentioning is that the Java Mail API is tied to, or rather leverages, another Java extension: the Java Activation Framework (JAF). The JAF is intended to unify the manner of working with the multitude of data formats that are available, whether they be simple text or extremely complex documents composed of images, audio, video, and even "live" objects. In this sense, it might be useful to think of the JAF as providing for Java what plug-ins provide to a Web browser. (See this month's article on the Java Plug-in.)

A sample Java Mail application

A "list server application" serves as the focal point for a distributed group discussion system based on e-mail. As such, it is a very common and useful way for subscribers to discuss common-interest subjects.

The following Java Mail API-based application is a working example of a useful middletier list server application. The Java Mail API makes this application easy to create (using the default POP3 and SMTP implementations) and ensures that it will easily support any provider-implemented systems that should arise. For example, the current application easily supports POP3, SMTP, and IMAP servers, and adding support for Lotus e-mail, say, would be as simple as plugging in an implementation from IBM and abstracting any hardcoded references to protocols.

Running the ListServer application is very simple. Just remember to include the JAR files for Java Mail, JAF, and the default POP3 implementation in the CLASSPATH, as shown in the following MS-DOS batch file example. (You can obtain these JAR files from the Java Mail home page link provided in the Resources section at the end of this article.)

    @echo off
    PATH .;d:\jdk1.1\bin
    set CLASSPATH=.;d:\jdk1.1\lib\classes.zip;activation.jar;mail.jar;pop3.jar
    java ListServer %1 %2 %3 %4 %5 %6 %7 %8 %9

Upon starting, the ListServer main() routine will read in the settings, including the appropriate mail servers, mail accounts, and update frequency. Next, an instance of a ListServer is instantiated and created, and the program enters an infinite loop of processing new messages and sleeping, until it is time to check for messages again.

The use of java.lang.Properties throughout the application is worth pointing out: properties are used as a way to implicitly control the behavior of some Java Mail API methods. It should be noted that sometimes the implicit property arguments can be overridden by explicit arguments. The disadvantages of allowing implicit property argument behavior versus explicit argument behavior is (hopefully) more than balanced by the increased standardization of how applications, and especially applets, are configured without modifying Java source code.

The heart of this ListServer program occurs in the process() routine, which directs the reading and broadcasting of all new messages. The significant Java Mail API-specific code snippets in the method process() perform the following actions:

  • Obtains a javax.mail.Session instance, which is used to obtain an instance of a javax.mail.Store instance

  • Uses the javax.mail.Store instance to obtain the default INBOX javax.mail.Folder instance

  • Uses the javax.mail.Folder object to fetch the array of new messages in an array of javax.mail.Message objects

  • Creates a javax.mail.FetchProfile to (potentially) optimize the retrieval of specific message components

The use of the javax.mail.FetchProfile class is also interesting from a design-and-implementation perspective. The FetchProfile class provides the option for Java Mail protocol providers to support more efficient prefetching of Message components. The design of the Java Mail API encourages the retrieval of Message components to be delayed as long as possible (that is, until actually used). While this improves response times, certain operations, such as displaying a list of message subjects, also benefit from the FetchProfile class. The following code illustrates the use of FetchProfile when fetching Messages from a Folder:

        // Get attributes & flags for all messages
        //
        Message[] messages = folder.getMessages();
        FetchProfile fp = new FetchProfile();
        fp.add(FetchProfile.Item.ENVELOPE);
        fp.add(FetchProfile.Item.FLAGS);
        fp.add("X-Mailer");
        folder.fetch(messages, fp);

The sendMsg() routine is called by processMsg(), and is responsible for calling routines to fully read and then broadcast a message. The first step is to set up and retrieve the default session so that the javax.mail.Transport object that is retrieved has the correct protocol and host:

        // create some properties and get the default Session
        //
        Properties props = new Properties();
        props.put("mail.smtp.host", _smtpHost);
        Session session = Session.getDefaultInstance(props, null);
        .
        .
        .
        // Send newMessage
        //
        Transport transport = session.getTransport(SMTP_MAIL);
        transport.connect(_smtpHost, _user, _password);
        transport.sendMessage(newMessage, _toList);

The code for setting up the message fields such as to, from, subject, and date is very simple:

        // create a message
        //
        Address replyToList[] = { new InternetAddress(replyTo) };
        Message newMessage = new MimeMessage(session);
        if (_fromName != null)
            newMessage.setFrom(new InternetAddress(from,
                               _fromName + " on behalf of " + replyTo));
        else
            newMessage.setFrom(new InternetAddress(from));
        newMessage.setReplyTo(replyToList);
        newMessage.setRecipients(Message.RecipientType.BCC, _toList);
        newMessage.setSubject(subject);
        newMessage.setSentDate(sentDate);

Setting the contents of the message requires reading in the desired contents and then calling the appropriate setContents...() routine as follows:

        // Set message contents
        //
        Object content = message.getContent();
        String debugText = "Subject: " + subject + ", Sent date: " + sentDate;
        if (content instanceof Multipart)
        {
            debugMsg("Sending Multipart message (" + debugText + ")");
            newMessage.setContent((Multipart)message.getContent());
        }
        else
        {
            debugMsg("Sending Text message (" + debugText + ")");
            newMessage.setText((String)content);
        }

The javax.mail.internet.MimeMessage content-reading routines are notable for their ability to read in complex, multipart, hierarchical messages with one simple call, as in the getContent() example above.

The source code for ListServer is very basic but provides a fully functional list server. Furthermore, this basic list server can easily be enhanced by adding features such as automatic subscribe and unsubscribe.

To download the complete source code for this application, see ListServer.java.

Upcoming features

As it stands now, the Java Mail API is already a powerful framework for developing mail/messaging systems. And, if my prediction is accurate, we'll soon see a lot more Java Mail implementations (for proprietary e-mail systems such as Lotus Notes, for example), making it a de facto standard for developing mail/message applications -- similar to how the JDBC API has become a standard for developing database applications in Java.

Conclusion

The Java Mail API presents an excellent opportunity for developers to integrate advanced mail capabilities into their applications with all the benefits that this API can provide: ease of development, multiple protocol support, and flexible integration of future advances. With the introduction to the key Java Mail classes provided in this article, you should now have a good understanding of some of the capabilities of this API.

Nemil is a senior software engineering consultant for Divya Incorporated (http://divya.com), a consulting firm specializing in Java/Internet software solutions. Tony has been developing imaging, algorithmic, and client/server solutions for close to ten years. Anil Hemrajani is a senior consultant for Divya Incorporated. Anil Hemrajani provides Java/Internet-based architecture, design, and development solutions to Fortune 500 companies and occasionally writes articles and lectures at conferences.

Learn more about this topic

Join the discussion
Be the first to comment on this article. Our Commenting Policies