Chapter 19

Processing E-Mails with Java

People send and receive e-mails using e-mail client programs such as Microsoft Outlook and Gmail. Can you write your own program to send and receive e-mails? The chances are slim that you’ll need to develop a client to compete with Gmail, but enterprise Java applications often need the ability to send or receive e-mails in certain conditions.

For example, an application that processes credit card transactions suspects a fraudulent activity and needs to send an e-mail to the account owner. Such an application becomes an e-mail client. A Java application provided by your bank can run on your Android smartphone and have an integrated e-mail inbox that accumulates all messages sent to you by the bank.

Another good example involves the forgotten-password functionality. A user clicks the Forgot Your Password? hyperlink and enters a valid e-mail address in a text input field. A couple of seconds later an e-mail containing instructions for resetting the password arrives in her e-mail inbox. The server-side Java program sent this e-mail automatically using JavaMail’s application program interface (API).

In this lesson you’ll learn how to write a Java program that can send e-mails reminding you about your friends’ birthdays.

Protocols and Servers

For e-mail messaging you’ll be using standard protocols: Simple Mail Transfer Protocol (SMTP) for sending e-mails and Post Office Protocol (POP) or Internet Message Access Protocol (IMAP) for retrieving e-mails. The third version of this protocol is called POP3; IMAP is a more advanced alternative to POP3. The format of the message body and its attachments, if any, is defined by the Multipurpose Internet Mail Extensions (MIME) protocol.

Some vendors use proprietary protocols for e-mails, but we’ll stick to standards. For Java SE, JavaMail API is an optional package that has to be downloaded separately, but it is included with Java EE. The API is simple to use — it takes only a few lines of code to send an e-mail from a Java program.

To test a client program that sends e-mails you’ll need to know the hostname and port of some SMTP server and have an account with the service provider. Typically such servers use port 25 or 587 for e-mails encrypted using Transport Layer Security (TLS) protocol and port 465 for Secure Sockets Layer (SSL) encryption. Some ISPs may block these ports though.

Apart from an SMTP server hosted by your ISP, you can use the free public server smtp.gmail.com offered by Google. For the parameters of this server refer to the following Web page: http://mail.google.com/support/bin/answer.py?hl=en&answer=13287. Yahoo! also offers a free public SMTP server at smtp.mail.yahoo.com.

Here’s a word of caution: After you learn how easy it is to write a Java program that sends e-mails, you might have an urge to start sending mass e-mails to large lists of recipients to promote your business or share the latest jokes you’ve found online. Unsolicited e-mail is called spam, and if you write a program that sends dozens of e-mails per minute your ISP will probably notice it and give you a warning or even terminate your Internet access.

Creating Birthday Mailer

Because I’ll be writing a birthday mailer program using Java SE, I need to download the jars (libraries) with JavaMail classes. At the time of this writing JavaMail API 1.4.3 is the latest release, and you can download it from www.oracle.com/technetwork/java/index-138643.html.

Unzip the JavaMail archive — it includes all required jar files, demos, and documentation. Create an Eclipse project called Lesson19, right-click the project name, and select Properties Java Build Path. Go to the Libraries tab, click Add External JARs, and add mailapi.jar and smtp.jar to the project from the lib directory of the extracted archive. These jars contain all the classes from the javax.mail package required to send e-mails. If you are using a really old version of Java (prior to version 6) you’ll also need to download and add to your project the JavaBeans Activation Framework (JAF).

Required Supporting Classes

At a minimum you have to use the following classes to send an e-mail:

  • javax.mail.Session: This class knows important characteristics of your environment, such as the name of the mail server.
  • javax.mail.Message: This class represents your message, containing recipients, subject, content, and so on.
  • javax.mail.internet.InternetAddress: The recipient of your message will be represented by this class.
  • javax.mail.Transport: This class will pass your message for the delivery to a protocol-specific transport.

Writing the Mail Sender

Now you’ll learn how to write a program to send e-mail messages. I’ll be using the publicly available SMTP server from Yahoo!, but if you decide to use the server provided by your ISP you can find out its hostname and port from the settings of your current e-mail client program. For example, Microsoft Outlook has this information in the menu Tools Accounts Mail Properties.

Typically SMTP servers require you to provide a valid e-mail address and password for authentication. Because your JavaMail program won’t use a log-on window, you can hard-code e-mail credentials in a subclass of JavaMail’s Authenticator, as shown in Listing 19-1.

download.eps

Listing 19-1: Authenticator class

package com.practicaljava.lesson19;
 
import javax.mail.Authenticator;
 
import javax.mail.PasswordAuthentication;
 
class MyMailAuthenticator extends Authenticator { 
 
    protected PasswordAuthentication getPasswordAuthentication() {
 
      return new PasswordAuthentication ("[email protected]", "password123");
 
    }
}

If MyMailAuthenticator isn’t able to authenticate using the provided e-mail/password combination, it’ll throw the AuthenticationFailedException with the error message “Access Denied.” If you’ll specify a nonexistent sender’s e-mail address, the program will throw SMTPSendFailedException with the error “From address not verified.” If authentication is not required, the class MyMailAuthenticator is not needed.

A sample file that stores the birthdays of your e-mail contacts is shown in Listing 19-2. It’s a file in a CSV format, where each line contains the birthday, name, and e-mail address of a contact.

download.eps

Listing 19-2: The file birthday.txt

Aug-9,Mary Lou,[email protected]
Mar-31,John Smith,[email protected]
Aug-9,David Lee,[email protected]

The Mailer program (see Listing 19-3) will read this file into an array, and if the birthday’s date is the same as the current date, it’ll send a “happy birthday” e-mail to this person. The program starts by creating an object with the properties of the SMTP server at Yahoo! Then it creates an instance of the MyMailAuthenticator class and gives both of them to the Session instance.

When this is done the method main() invokes the method readBirthdayFile(), which populates ArrayList friends with the data from the file birthday.txt. Then the method iterateThroughBirthdays() parses only those lines in which the birthday date is the same as the current date. This program uses the class java.util.Scanner, which parses the content of the String (the friend’s data) based on specified delimiters.

The setPropsAndSendEmail() method has the code for sending e-mails. First it creates an instance of the Message object and populates it with all the familiar parameters: from, recipient(s), subject, data, and the text of the message. The call to Transport.send() performs the actual process of sending this message.

download.eps

Listing 19-3: The Mailer class

package com.practicaljava.lesson19;
 
import java.io.*;
import java.text.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
 
public class Mailer      {
 
    private Session session = null;
 
    private static  String emailSenderAddress = "[email protected]";
    private static  String emailSubject = "Happy Birthday!!!";
    private String emailText = "Happy birthday dear %s!!!";
 
    ArrayList<String> friends = new ArrayList<String>();
 
    Mailer() {
 
        Properties sessionProperties = new Properties();
        sessionProperties.put("mail.smtp.host", "smtp.mail.yahoo.com");
        sessionProperties.put("mail.smtp.user", emailSenderAddress);
        sessionProperties.put("mail.smtp.port", "25");
        sessionProperties.put("mail.smtp.auth", "true");
 
        MyMailAuthenticator authentificatorForMessage = 
                                             new MyMailAuthenticator();
 
        session = Session.getInstance(sessionProperties, 
                                            authentificatorForMessage);
    }
 
 
    private void setPropsAndSendEmail(String emailRecipient, String emailText){
 
        try{
 
            Message emailMessage = new MimeMessage(session);
 
            emailMessage.setFrom(new InternetAddress(emailSenderAddress));      
            emailMessage.setRecipients(Message.RecipientType.TO, 
                              InternetAddress.parse(emailRecipient, false));
            emailMessage.setSubject(emailSubject);
            emailMessage.setSentDate(new Date());
            emailMessage.setText(emailText);
            Transport.send(emailMessage);
            System.out.println("Your email to " + emailRecipient + 
                                            " has been sent successfully");
        }catch(Exception e){
 
            System.out.println("Your email to " + emailRecipient + 
                                "  has not been sent: " + e.getMessage());
            e.printStackTrace();
        }
    }
 
 
    private void readBirthdayFile() throws IOException {
 
        FileInputStream birthdayFile = new FileInputStream("birthday.txt");
 
        BufferedReader birthdayFileReader = new BufferedReader(
                                      new InputStreamReader(birthdayFile));
 
        String friendInfo;
 
        while ((friendInfo = birthdayFileReader.readLine()) != null){
            friends.add(friendInfo);
        }
 
        birthdayFileReader.close();
 
        birthdayFile.close();
    }
 
    private void iterateThroughBirthdays(){
 
        Iterator<String> iterator = friends.iterator(); 
 
        while (iterator.hasNext()){
 
            scanForManInfoAndSendEmail(iterator.next());
 
        }
    }
 
      
    private void scanForManInfoAndSendEmail(String stringFromArray){
 
        Scanner scannerOfLines = new
                      Scanner(stringFromArray).useDelimiter("[,
]");
 
        if (scannerOfLines.next().equals(getCurrentDateMMMd())) {
 
            String emailAddressee = scannerOfLines.next();
            String emailAddress = scannerOfLines.next();
            setPropsAndSendEmail(emailAddress, 
                        String.format(emailText, emailAddressee));
        }
    }
 
    private static String getCurrentDateMMMd(){
 
        return new SimpleDateFormat("MMM-d", Locale.US).format(new 
                                      GregorianCalendar().getTime());
 
    }
 
    public static void main(String[] args){        
 
        Mailer mm = new Mailer();
 
        try {
 
            mm.readBirthdayFile();
            mm.iterateThroughBirthdays();
 
        } catch (IOException e) {
 
            e.printStackTrace();
        }
    }
}

How to Retrieve E-Mails

Even though more often than not the receivers of the messages sent by a Java application will use one of the popular e-mail clients already available, you may need to incorporate message-retrieving functionality into your application. In this section I’ll just give an overview of the process of retrieving e-mails programmatically, and in the “Try It” section you’ll write such a program on your own.

As in your local post office, incoming mail should be stored somewhere. The POP3 or IMAP mail server provides such storage. POP3 is an older protocol that retrieves messages from a single mailbox. IMAP is newer and more advanced: It allows the organization of messages in folders with filtering support.

To get access to the user’s incoming e-mails the Java program needs to connect to the mail server and get an instance of the Store object by calling the method getStore() on the Session object. You’ll need to know the hostname of your mail server, the protocol it uses, and the relevant user ID and password in order to get the Store instance.

The next step is establishing a connection with Store by calling its method connect(). After this is done, get store’s default root folder and then a specific sub-folder, such as INBOX.

Folders in JavaMail are represented by the class Folder. Its method open() will open the specified folder for READ_ONLY or READ_WRITE. Finally, the getMessages() method returns an array of Message objects. Iterating through this array will allow you to retrieve message data by calling getSubject(), getFrom(), getContent(), and so on.

Listing 19-4 shows a fragment of the code for retrieving messages from a Gmail account. To enable or disable the IMAP or POP protocol, go to Setting Forwarding POP/IMAP in your Gmail client.

download.eps

Listing 19-4: Fragment of code for e-mail retrieval from Gmail

        Properties properties = System.getProperties(); 
        Session session = Session.getDefaultInstance(properties);
 
        String host = "pop.gmail.com"; // or "imap.gmail.com"
        String username = "yakov";
        String password = "mypasswd";
        Store store = session.getStore("pop3s"); // or "imap"
        store.connect(host, username, password);
 
        Folder rootFolder = popStore.getDefaultFolder();
        defaultPopFolder = defaultPopFolder.getFolder("INBOX");
        defaultPopFolder.open(Folder.READ_ONLY);
 
        
        Message[] message = folder.getMessages();
 
        for (int i = 0; i < message.length; i++) {
             
             // get message parts here  
        }

JavaMail has full support for multipart messages with attachments (see the Multipart, MimeMultipart, and MimeBodyPart classes), but multipart message support is beyond the scope of this book. The description of these classes is available in the Java help system. Look for these class descriptions in the package javax.mail.

Useful Open-Source Components

Apache Commons is a community project that offers a number of open-source reusable components. One of the libraries contains classes for sending and receiving e-mails form Java. You can read about this project at http://commons.apache.org/email/userguide.html.

The process of sending a simple e-mail with this library comes down to creating an instance of one class, SimpleEmail. Then you need to set the properties of this object: host, port, from, to, authenticator, subject, and message body. When this is done, just call the send() method.

If all you need is to send simple e-mails, the benefits of using the Apache Commons e-mail library may not be so obvious. But if your program needs to send multipart e-mails with attachments, or HTML-formatted e-mails, consider using this library. One useful feature of this library is that it gives you the ability to specify an alternative recipient for bounced e-mails.

There is one more community project to consider: Apache Velocity (http://velocity.apache.org/). Imagine that you need to write a program that will perform mass mailing of pre-formatted letters, inserting customer-specific information (such as name and address) into each one. The Apache Velocity project would be quite handy for this purpose. It is also useful if you want to send automatic account registrations or password-change e-mails. Instead of hard-coding the letter text into your Java program, you can create text files (templates) containing special markup to be substituted with real values by your Java program during run time.

For further details, read the user guide at the following URL: http://velocity.apache.org/engine/devel/user-guide.html.

Third-party libraries (e.g. Spring Framework, discussed in Lesson 35) hide specifics of the use of JavaMail API. Check out the documentation on using e-mails with the Spring Framework at the following URL: http://static.springsource.org/spring/docs/2.0.x/reference/mail.html.

Try It

Write a Java program that will retrieve messages from your mail inbox and print their subjects on the system console.

Lesson Requirements

You should have Java installed. For this section I assume that you’ve created Eclipse project Lesson19 and that it contains a working version of the Mailer program.

note.ai

You can download the code and resources for this Try It from the book’s web page at www.wrox.com. You can find them in the Lesson19 folder in the download.

Step-by-Step

1. Add JavaMail libraries pop.jar and imap.jar to the project.

2. Read the chapter on message storage and retrieval in the document “JavaMail Design Specification” and code sample “Showing the message” from Listing B-X in Appendix B of “JavaMail Design Specification.” This document is located in the doc folder of the JavaMail distribution.

3. Write the Java program MailReader to retrieve and print on the system console the subjects of messages located in your inbox.

4. Run MailReader and compare the printed message subjects with the ones displayed by the mail client you use regularly.

cd.ai

Please select Lesson 19 on the DVD with the print book, or watch online at www.wrox.com/go/fainjava to view the video that accompanies this lesson.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.111.195