JavaData & JavaMonitoring Email Accounts (IMAP) in Java

Monitoring Email Accounts (IMAP) in Java

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Monitoring an email account is a little complex then mere sending one. The functionality provided by the JavaMail API is extensive enough to write a full-fledged email clients application. An email-intensive application, such as a mailing list manager, may suffice to take care of sending and receiving a little email, but imagine a server monitoring application that may require the operation to periodically load pages from a web server running on a different host and email the webmaster if the web server has crashed. Sounds complicated, right? But, the JavaMail class library makes it lot simpler with APIs dedicated to handling almost every aspect of email communication. This article focuses on some of the important aspects of email monitoring and their implementation through code.

JavaMail Anatomy

JavaMail is not the only answer to handle email communication. We can write Java programs that use sockets to communicate with mail servers. However, in this case, the application requires detailed knowledge of protocols such as SMTP, POP, and IMAP. The JavaMail API made it much simpler by helping us focus on the message rather than tangled up with the low-level protocol details. The architecture clearly shows that when broadly divided into:

  • The Application part, which provides the necessary API for email communication irrespective of underlying protocols. They roughly follow the abstract factory pattern. These patterns allow us to write code based on the abstract super classes without worrying about the lower-level details.
  • The Service part, which is attuned with the protocols and speak a protocol-specific language for communication. These protocols are basically a group of concrete subclasses of abstract JavaMail API that specialize the general API to a particular protocol and mail format.

IMAP4 vs POP3

IMAP (Internet Message Access Protocol) and POP (Post Office Protocol) are two protocols built for the same purpose such as retrieving messages, searching through mailboxes, and so forth. The significant difference is that POP3 assumes that the client stores and manages the mail archive. It, however, gives you the tool to download the mail from the server but must implement its own storage system on the client. Once downloaded, POP3 creates local copies and removes the original mail from the server. IMAP, on the other hand, allows you to use the storage of the mail server to be kept intact until the user opts to delete them manually, much like what we do in our Gmail account. In a word, POP3 uses client storage for mail with virtually unlimited storage capacity.

IMAP, on the other hand, uses remote email server storage and, as is obvious, has limited storage capacity. POP3 is by no means is less popular and is particularly suitable for developing email client application such as Outlook Express or Thunderbird. IMAP is a popular player of the omnipresent cloud that can be accessed anytime anywhere through simple browser like the webmails—Gmail, Yahoo!, and the like. As we go deep down these protocols, there are a lot of intricacies involved, but for implementing in JavaMail perhaps this basic idea would be a good place to start.

Monitoring an Email Account

The following example demonstrates how to retrieve email from an inbox folder. The IMAP server provider used in the code is Gmail. With a little tweaking, it would work on other providers as well.

package org.mano.imapexample;

import java.util.Properties;

import javax.mail.Address;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;

public class MailBean {

   private Properties getServerProperties(String protocol,
         String host, String port) {
      Properties properties = new Properties();
      properties.put(String.format("mail.%s.host",
         protocol), host);
      properties.put(String.format("mail.%s.port",
         protocol), port);
      properties.setProperty(
         String.format("mail.%s.socketFactory.class",
            protocol), "javax.net.ssl.SSLSocketFactory");
      properties.setProperty(
         String.format("mail.%s.socketFactory.fallback",
            protocol), "false");
      properties.setProperty(
         String.format("mail.%s.socketFactory.port",
            protocol), String.valueOf(port));

      return properties;
   }

   public void getNewEmails(String protocol, String host,
         String port, String userName, String password) {
      Properties properties = getServerProperties(protocol,
         host, port);
      Session session = Session.getDefaultInstance(properties);

      try {
         Store store = session.getStore(protocol);
         store.connect(userName, password);

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

         int count = inbox.getMessageCount();
         Message[] messages = inbox.getMessages(1, count);
         for (Message message : messages) {
            if (!message.getFlags().contains(Flags.Flag.SEEN)) {
               Address[] fromAddresses = message.getFrom();
               System.out.println("...................");
               System.out.println("t From: "
                  + fromAddresses[0].toString());
               System.out.println("t To: "
                  + parseAddresses(message
                  .getRecipients(RecipientType.TO)));
               System.out.println("t CC: "
                  + parseAddresses(message
                  .getRecipients(RecipientType.CC)));
               System.out.println("t Subject: "
                  + message.getSubject());
               System.out.println("t Sent Date:"
                  + message.getSentDate().toString());
               try {
                  System.out.println(message.getContent()
                     s.toString());
               } catch (Exception ex) {
                  System.out.println("Error
                     reading content!!");
                  ex.printStackTrace();
               }
            }

         }

         inbox.close(false);
         store.close();
      } catch (NoSuchProviderException ex) {
         System.out.println("No provider for protocol: "
            + protocol);
         ex.printStackTrace();
      } catch (MessagingException ex) {
         System.out.println("Could not connect to
            the message store");
         ex.printStackTrace();
      }
   }

   private String parseAddresses(Address[] address) {

      String listOfAddress = "";
      if ((address == null) || (address.length < 1))
         return null;
      if (!(address[0] instanceof InternetAddress))
         return null;

      for (int i = 0; i < address.length; i++) {
         InternetAddress internetAddress =
            (InternetAddress) address[0];
         listOfAddress += internetAddress.getAddress()+",";
      }
      return listOfAddress;
   }
}


package org.mano.imapexample;

public class mailapp {

   public static void main(String[] args){

   MailBean bean=new MailBean();
      bean.getNewEmails("imap", "imap.gmail.com", "993",
         "user1", "****");

   }

}

How It Works

Once connected to the IMAP server, the store is set up to be connected as follows:

Store store = session.getStore(protocol);
store.connect(userName, password);

We are now ready to open a folder in the store. This section is more oriented to IMAP than POP because POP servers do not keep track of different folders. They simply provide all information about incoming mail as one undivided amalgam.

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

We skip over the messages that are marked SEEN. This is achieved through the following code:

if (!message.getFlags().contains(Flags.Flag.SEEN))

Unseen messages are printed with detail information. Each message contains list of information, such as from, to, cc, subject, sent date, the message content, and so on. We also can ascertain the type of message content, whether is plain text or HTML, and process accordingly. ParseAddress methods extract the email address because the Address objects of JavaMail are generic and can represent Internet or newsgroup addresses. So, the method parses the Address object and retrieves the actual e-mail address.

Conclusion

The preceding code is a simple demonstration of email account monitoring. Observe how simple it is to implement them through JavaMail. Programmers do not have to be bogged down by the complexity of protocols. Because mail arrives from the network at unpredictable times, JavaMail also provides a mechanism to handle events. It relies on an event-based callback mechanism to handle incoming mail much like AWT events. These features can be exploited to create a full-fledged email application, be it a client app through POP3 or webmail through IMAP.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories