View RSS Feed

Java Mail

How to get e-mail with Java

Rating: 4 votes, 3.00 average.
by , 02-29-2012 at 03:39 PM (17310 Views)
In the article “How to send e-mail with Java”, you are familiar with the JavaMail API on sending e-mail messages from a SMTP server. What about receiving e-mail messages? Well, that is the topic of this article. We will study how the JavaMail API exposes classes and interfaces for retrieving e-mail messages from a server, to write a utility class that checks for new messages in inbox of an e-mail account from Gmail server.

Protocols for receiving e-mail

There are two standard protocols for e-mail retrieval: POP and IMAP.

  • POP (Post Office Protocol): This is the most widely used protocol. A POP client connects to the mail server briefly, only during the download of messages. POP limits only one client connected to the server at the same time. The current version is POP3.

  • IMAP (Internet Message Access Protocol): this protocol was defined after POP. An IMAP client maintains connection with the mail server regularly. IMAP allows multiple clients connected to the server simultaneously. The current version is IMAP4.


Most big e-mail services support both protocols, however the POP is more widely used then the IMAP.


The JavaMail API

Download the latest distribution of the JavaMail API at: JavaMail API

You will find the mail.jar file in the distribution, add this file to your project’s classpath in order to work with interfaces and classes provided by the JavaMail API.

Here is description for the main interfaces and classes that involve in receiving e-mail messages and parsing e-mail content from a mail server.

  • Session.java: this class represents a mail session. A session loads all properties and settings such as the protocol providers and server settings. There are two types of session: shared and unshared. A shared session can be obtained via the static method getDefaultInstance(); An unshared session can be created via the static method getInstance(). The shared session is shared by multiple applications running on the same JVM, while an unshared one is not.

  • Store.java: This abstract class represents a message store. It extends the javax.mail.Service class, which provides common methods for connecting to message stores. Actual implementations of Store class are the IMAPStore.java class and POP3Store.java class.

  • IMAPStore.java: represents a message store which supports IMAP protocol.

  • POP3Store.java: represents a message store which supports POP protocol.

  • Folder.java: this abstract class represents a folder for storing messages.

  • Message.java: This abstract class represents an email message. An e-mail message can be created for sending or when receiving. The MimeMessage class is a subclass of the Message class.

  • Multipart.java: represents content of a message as multi parts. An e-mail message is made up of several parts: body part, attachment parts… MimeMultipart is the implementation class.

  • Address.java: represents an address in a message. An e-mail message contains sender’s address, recipients’ addresses. Implementation classes are InternetAddress and NewsAddress.



POP3 settings

Since POP is the most widely used protocol for retrieving e-mail messages, the sample program in this article will use POP3 to receive e-mail messages from a Gmail account. The following properties should be specified for a POP3 session:

  • mail.pop3.host: host name of the POP3 server, such as pop.gmail.com for Gmail.

  • mail.pop3.port: port number of the POP3 server.

  • user name: user name of the e-mail account.

  • password: password of the e-mail account.



In addition, since Gmail provides POP3 over SSL (POP3S), we need to provide some properties for configure SSL:

  • mail.pop3.socketFactory.class: specifies the name of a class that implements the javax.net.SocketFactory interface to create POP3 sockets.

  • mail.pop3.socketFactory.fallback: set to true or false. If true, when the socket factory class fails to create the socket, a new instance of java.net.Socket class is created instead.

  • mail.pop3.socketFactory.port: port number for POP3S, is usually 995.


The settings are put into a java.util.Properties object which is passed to a Session object. For example:

Java Code: Set properties for POP3
        // sets POP3 properties
        Properties properties = new Properties();
        properties.put("mail.pop3.host", host);
        properties.put("mail.pop3.port", port);
       
        // sets POP3S properties
        properties.setProperty("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        properties.setProperty("mail.pop3.socketFactory.fallback", "false");       
        properties.setProperty("mail.pop3.socketFactory.port", "995");

Connect to the server

First, obtain the shared session:

Java Code: Obtain the shared Session object
Session session = Session.getDefaultInstance(properties);
Then obtain a POP3Store object from the session:


Java Code: Obtain a POP3Store object
POP3Store emailStore = (POP3Store) session.getStore("pop3");
And use the connect() method to make a connection to the POP3 server:

Java Code: Connect to the mail store
emailStore.connect(userName, password);

Iterate through the messages

To traverse through e-mail messages in the store, it requires opening the INBOX folder of the store. Inbox folder is the primary folder of a mail store:

Java Code: Obtain the INBOX folder
        Folder emailFolder = emailStore.getFolder("INBOX");
        emailFolder.open(Folder.READ_ONLY);
Note that the INBOX folder is opened in read only mode.


Then we invoke the getMessages() method on the folder object to retrieve all new e-mail messages in the inbox:

Java Code: Retrieve an array of new messages
Message[] messages = emailFolder.getMessages();
The method returns an array of Message object, so it’s trivial to use a for loop to iterate over the messages and print out the details of each message:

Java Code: Iterate through new mail messages
        for (int messageCount = 0; messageCount < messages.length; messageCount++) {
            Message aMessage = messages[messageCount];
            // print out details for each message

        }

Getting e-mail’s details

The information should be extracted from an e-mail are:

  • Sender’s e-mail address.
  • Subject.
  • Recipient addresses, in TO field and CC field.
  • Sent date.
  • Message content.



The following code extracts the information mentioned above:

Java Code: Parse details of a message
            String senderAddress = aMessage.getFrom()[0].toString();
            String subject = aMessage.getSubject();
           
            // parses recipient address in To field
            Address[] listTO = aMessage.getRecipients(RecipientType.TO);
           
            // parses recipient addresses in CC field
            Address[] listCC = aMessage.getRecipients(RecipientType.CC);
           
            String sentDate = aMessage.getSentDate().toString();

            String textMessage = aMessage.getContent();

Saving attachments

An e-mail may be in plain text, HTML and/or contain attachments. This can be determined the content type of the e-mail:

Java Code: Determine content type of the message
    String contentType = aMessage.getContentType();
           
    if (contentType.contains("text/plain") || contentType.contains("text/html")) {
        // plain text or HTML only email
    } else if (contentType.contains("multipart")) {
        // email contains attachments

    }
If the e-mail contains attachments, its content type must be multipart, so we cast the content of the e-mail to a Multipart object, then iterate over through the parts to find the attachments:

Java Code: Iterate through parts of a message
Multipart multiPart = (Multipart) aMessage.getContent();
int numberOfParts = multiPart.getCount();
for (int partCount = 0; partCount < numberOfParts; partCount++) {
    BodyPart part = multiPart.getBodyPart(partCount);
    if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {

        // part is attachment
        // store attachment to disk

    } else {

        // part is not attachment

    }
}
Note that a part may be the body part, which contains the text message, or may be the attachment part. The following method saves an attachment into a file on the disk:

Java Code: Save an attachment to file on disk
    private void storeAttachment(BodyPart part) throws MessagingException, IOException {
        String destFilePath = "D:/Attachment/" + part.getFileName();
       
        FileOutputStream output = new FileOutputStream(destFilePath);
       
        InputStream input = part.getInputStream();
       
        byte[] buffer = new byte[4096];
       
        int byteRead;
       
        while ((byteRead = input.read(buffer)) != -1) {
            output.write(buffer, 0, byteRead);
        }
        output.close();
    }

Write the utility class

We put all the pieces of code above into a single utility class, the EmailReceiver.java class:

Java Code: Code of EmailReceiver class
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;

import com.sun.mail.pop3.POP3Store;

/**
* A utility class the retrieves e-mail messages from a POP3 server
* @author Ha Minh Nam
*
*/
public class EmailReceiver {
   
    /**
     * Retrieves new incoming e-mail messages from inbox of a POP3 account
     * @param host host name of the POP3 server
     * @param port port number of the server
     * @param userName user name of the e-mail account
     * @param password password of the e-mail account
     * @throws MessagingException
     * @throws IOException
     */
    public void getEmail(String host, String port, String userName, String password)
            throws MessagingException, IOException {
        // sets POP3 properties
        Properties properties = new Properties();
        properties.put("mail.pop3.host", host);
        properties.put("mail.pop3.port", port);
       
        // sets POP3S properties
        properties.setProperty("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        properties.setProperty("mail.pop3.socketFactory.fallback", "false");       
        properties.setProperty("mail.pop3.socketFactory.port", "995");
       
        // connects to the POP3 server
        Session session = Session.getDefaultInstance(properties);
        POP3Store emailStore = (POP3Store) session.getStore("pop3");
        emailStore.connect(userName, password);       
       
        Folder emailFolder = emailStore.getFolder("INBOX");
        emailFolder.open(Folder.READ_ONLY);
        Message[] messages = emailFolder.getMessages();
       
        for (int messageCount = 0; messageCount < messages.length; messageCount++) {
            Message aMessage = messages[messageCount];
            String senderAddress = aMessage.getFrom()[0].toString();
            String subject = aMessage.getSubject();
           
            // parses recipient address in To field
            String toAddresses = "";
            Address[] listTO = aMessage.getRecipients(RecipientType.TO);
            if (listTO != null) {
                for (int toCount = 0; toCount < listTO.length; toCount++) {
                    toAddresses += listTO[toCount].toString() + ", ";
                }
            }   
            if (toAddresses.length() > 1) {
                toAddresses = toAddresses.substring(0, toAddresses.length() - 2);
            }
           
            // parses recipient addresses in CC field
            String ccAddresses = "";
            Address[] listCC = aMessage.getRecipients(RecipientType.CC);
            if (listCC != null) {
                for (int ccCount = 0; ccCount < listCC.length; ccCount++) {
                    ccAddresses = listCC[ccCount].toString() + ", ";
                }
            }           
            if (ccAddresses.length() > 1) {
                ccAddresses = ccAddresses.substring(0, ccAddresses.length() - 2);
            }           
           
            String sentDate = aMessage.getSentDate().toString();
           
            String contentType = aMessage.getContentType();
            String textMessage = "";
            String attachFiles = "";
           
            if (contentType.contains("text/plain") || contentType.contains("text/html")) {
                textMessage = aMessage.getContent() != null ? aMessage.getContent().toString() : "";
            } else if (contentType.contains("multipart")) {
                Multipart multiPart = (Multipart) aMessage.getContent();
                int numberOfParts = multiPart.getCount();
                for (int partCount = 0; partCount < numberOfParts; partCount++) {
                    BodyPart part = multiPart.getBodyPart(partCount);
                    if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
                        attachFiles += part.getFileName() + ", ";
                        storeAttachment(part);
                    } else {
                        textMessage = part.getContent() != null ? part.getContent().toString() : "";
                    }
                }
               
                if (attachFiles.length() > 1) {
                    attachFiles = attachFiles.substring(0, attachFiles.length() - 2);
                }
            }   
           
            // prints out the message details
            System.out.println("Message #" + messageCount + ":");
            System.out.println("\t From: " + senderAddress);
            System.out.println("\t To: " + toAddresses);
            System.out.println("\t CC: " + ccAddresses);
            System.out.println("\t Subject: " + subject);
            System.out.println("\t Sent Date: " + sentDate);
            System.out.println("\t Message: " + textMessage);
            System.out.println("\t Attachments: " + attachFiles);
            System.out.println("--------------------------------------");
           
        }
       
        // closes the folder and disconnects from the server
        emailFolder.close(false);
        emailStore.close();       
       
    }
   
    /**
     * Saves an attachment part to a file on disk
     * @param part a part of the e-mail's multipart content.
     * @throws MessagingException
     * @throws IOException
     */
    private void storeAttachment(BodyPart part) throws MessagingException, IOException {
        String destFilePath = "D:/Attachment/" + part.getFileName();
       
        FileOutputStream output = new FileOutputStream(destFilePath);
       
        InputStream input = part.getInputStream();
       
        byte[] buffer = new byte[4096];
       
        int byteRead;
       
        while ((byteRead = input.read(buffer)) != -1) {
            output.write(buffer, 0, byteRead);
        }
        output.close();
    }
}

The class contains only one method, getEmail(), which connects to a POP3 mail server using SSL, retrieves the new messages from INBOX, then iterate over the messages to print out details of each message and save attachments to disk if any.


Write a test program

And finally we create a test class to use the utility class, the TestEmailReceiver.java class:

Java Code: Code of TestEmailReceiver class
import java.io.IOException;

import javax.mail.MessagingException;

public class TestEmailReceiver {
    public static void main(String... args) throws MessagingException, IOException {
        String host = "pop.gmail.com";
        String port = "995";
        String userName = "youremailhere@gmail.com";
        String password = "yourpasswordhere";
       
        EmailReceiver emailUtil = new EmailReceiver();
        emailUtil.getEmail(host, port, userName, password);
    }
}
Although the POP3 settings are specific for Gmail e-mail account, it is similar for other e-mail services.

And here is the output of the program:

Name:  output.png
Views: 5504
Size:  32.9 KB
Figure: Details of each message printed out


Conclusion

E-mail messages retrieval is well supported by the JavaMail API, so you can automate e-mail retrieval process in your Java based applications.

Submit "How to get e-mail with Java" to Facebook Submit "How to get e-mail with Java" to Digg Submit "How to get e-mail with Java" to del.icio.us Submit "How to get e-mail with Java" to StumbleUpon Submit "How to get e-mail with Java" to Google

Categories
Mail API

Comments