Monday, March 31, 2008

Reference of JavaMail

Looking Up a JavaMail Session

The standard Java Naming and Directory Interface™ (JNDI) subcontext for JavaMail sessions is java:comp/env/mail.

Registering JavaMail sessions in the mail naming subcontext of a JNDI namespace, or in one of its child subcontexts, is standard. The JNDI namespace is hierarchical, like a file system's directory structure, so it is easy to find and nest references. A JavaMail session is bound to a logical JNDI name. The name identifies a subcontext, mail, of the root context, and a logical name. To change the JavaMail session, you can change its entry in the JNDI namespace without having to modify the application.

The resource lookup in the application code looks like this:

InitialContext ic = new InitialContext();
String snName = "java:comp/env/mail/MyMailSession";
Session session = (Session)ic.lookup(snName);

For more information about the JNDI API, see Chapter 13, "Using the Java Naming and Directory Interface."


Sending Messages Using JavaMail

To send a message using JavaMail, perform the following tasks:

  1. Import the packages that you need:

import java.util.*;
import javax.activation.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.naming.*;

  1. Look up the JavaMail session, as described in Looking Up a JavaMail Session:

InitialContext ic = new InitialContext();
String snName = "java:comp/env/mail/MyMailSession";
Session session = (Session)ic.lookup(snName);

  1. Override the JavaMail session properties if necessary. For example:

Properties props = session.getProperties();
props.put("mail.from", "user2@mailserver.com");

  1. Create a MimeMessage. The msgRecipient, msgSubject, and msgTxt variables in the following example contain input from the user:

Message msg = new MimeMessage(session);
msg.setSubject(msgSubject);
msg.setSentDate(new Date());
msg.setFrom();
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(msgRecipient, false));
msg.setText(msgTxt);

  1. Send the message:

Transport.send(msg);


Reading Messages Using JavaMail

To read a message using JavaMail, perform the following tasks:

  1. Import the packages that you need:

import java.util.*;
import javax.activation.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.naming.*;

  1. Look up the JavaMail session, as described in Looking Up a JavaMail Session:

InitialContext ic = new InitialContext();
String snName = "java:comp/env/mail/MyMailSession";
Session session = (javax.mail.Session)ic.lookup(snName);

  1. Override the JavaMail session properties if necessary. For example:

Properties props = session.getProperties();
props.put("mail.from", "user2@mailserver.com");

  1. Get a Store object from the Session, then connect to the mail server using the Store object's connect() method. You must supply a mail server name, a mail user name, and a password.

Store store = session.getStore();
store.connect("MailServer", "MailUser", "secret");

  1. Get the INBOX folder:

Folder folder = store.getFolder("INBOX");

  1. It is efficient to read the Message objects (which represent messages on the server) into an array:

Message[] messages = folder.getMessages();


Secure JavaMail with JSSE

To read a message using JavaMail, perform the following tasks:

  1. Register JSSE providers, you can register them permanently in the <java home>\jre\lib\security\java.security properties file or register them dynamically by calling the Security.addProvider() method in your code:

Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

  1. Then you need to replace JavaMail's default socket factory with JSSE's SSL socket factory. This approach is similar to the one used in "Java Tip 96: Use HTTPS in Your Java Client Code"; however, in our case, we have no control over socket creation since sockets are created inside the JavaMail framework, not in the application code or storage provider. Fortunately, JavaMail accepts several undocumented properties, allowing you to set up a custom socket factory class and some other parameters. Those properties are:

mail.<protocol>.socketFactory.class
mail.<protocol>.socketFactory.fallback
mail.<protocol>.socketFactory.port
mail.<protocol>.timeout

  1. use the following code to replace a socket factory:

final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
Properties props = System.getProperties();
// IMAP provider
props.setProperty( "mail.imap.socketFactory.class", SSL_FACTORY);
// POP3 provider
props.setProperty( "mail.pop3.socketFactory.class", SSL_FACTORY);
// NNTP provider (if any)
// props.setProperty( "mail.nntp.socketFactory.class", SSL_FACTORY);

  1. If you want JavaMail to use only secure connections, you configure the appropriate properties so JavaMail doesn't fall back to an unsecure connection when a secure one fails:

// IMAP provider
props.setProperty( "mail.imap.socketFactory.fallback", "false");
// POP3 provider
props.setProperty( "mail.pop3.socketFactory.fallback", "false");
// NNTP provider (if any)
// props.setProperty( "mail.nntp.socketFactory.fallback", "false");

  1. then change the default port number to the corresponding port that your protocol's secure version uses; otherwise, you must use a fully qualified address (that includes a port number) in the URL passed to JavaMail (for example, imap://id:password@your.imap.server.com:993/folder/), or else you get an "unrecognized SSL handshake" exception. You specify these properties like so:

// IMAP provider
props.setProperty( "mail.imap.port", "993");
props.setProperty( "mail.imap.socketFactory.port", "993");
// POP3 provider
props.setProperty( "mail.pop3.port", "995");
props.setProperty( "mail.pop3.socketFactory.port", "995");
// NNTP provider (if any)
// props.setProperty( "mail.pop3.port", "563");
// props.setProperty( "mail.pop3.socketFactory.port", "563");

  1. After setting up all the properties, you can open a secure JavaMail session:

Session session = Session.getInstance(props);

 

Post a Comment
Google+