viernes, 18 de febrero de 2011

Enviar correos electrónicos mediante Java Mail

JavaTomcat
En algún caso puede que necesitemos enviar correos electrónicos desde una aplicación java. En esta entrada vamos a ver como realizarlo desde una aplicación web desplegada en un servidor tomcat y a través de una cuenta de correo de gmail.

Con estas premisas, sin más, el código java para enviar un correo elctrónico es el siguiente, que no sería muy distinto si utilizásemos otro servidor de aplicaciones e incluso no fuese una aplicación web:

...

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

...
try {
    // Obtener la sesión para enviar correos electrónicos del directorio JNDI
    Context ic = new InitialContext();
    Session session = (Session) ic.lookup("java:comp/env/mail/gmail");
   
    // Crear el mensaje a enviar
    MimeMessage mm = new MimeMessage(session);
  
    // Establecer las direcciones a las que será enviado 
    // el mensaje (test2@gmail.com y test3@gmail.com en copia oculta)
    mm.setFrom(new InternetAddress("test1@gmail.com"));
    mm.addRecipient(Message.RecipientType.TO, new InternetAddress("test2@gmail.com"));
    mm.addRecipient(Message.RecipientType.BCC, new InternetAddress("test3@gmail.com"));

    // Establecer el contenido del mensaje
    mm.setSubject("Hola mundo!");
    mm.setText("Hola mundo!");

    // Enviar el correo electrónico
    Transport.send(mm);
} catch (Exception e) {
    e.printStackTrace();
}

...

¿Pero donde se configura como nos conectamos al servidor de gmail para enviar los correos electrónicos? Pues bien, esto lo podemos hacer en la configuración de contexto para la aplicación. Estos  recursos se definen normalmente en un archivo «$TOMCAT_HOME/conf/Catalina/localhost/[contexto app].xml» y básicamente se asocia a un nombre del árbol JNDI un objeto de interfaz javax.mail.Session que será el que obtengamos en la aplicación y utilicemos para enviar los correos electrónicos. Esto es lo que hace la etiqueta Resource del ejemplo. JNDI es básicamente un registro donde se asocian nombres con servicios, en este caso el nombre «java:comp/env/mail/gmail» con objeto de interfaz javax.mail.Session que utilizaremos para enviar los correos electrónicos. La configuración para el tomcat sería:

<Context docBase="/home/tomcat/web">
    <Resource type="javax.sql.DataSource"
            auth="Container"
            maxActive="30" 
            maxIdle="10"
            maxWait="10000" 
            name="jdbc/db"
            driverClassName="com.mysql.jdbc.Driver"
            url="jdbc:mysql://localhost/db?autoReconnect=true"
            username="root"
            password=""/>
    <Resource type="javax.mail.Session"
            auth="Container"
            name="mail/gmail"
            mail.transport.protocol="smtp"
            mail.smtp.host="smtp.googlemail.com"
            mail.smtp.port="465"
            mail.smtp.auth="true"
            mail.smtp.user="test1@gmail.com"
            password=""
            mail.smtp.starttls.enable="true"
            mail.smtp.socketFactory.port="465"
            mail.smtp.socketFactory.class="javax.net.ssl.SSLSocketFactory"
            mail.smtp.socketFactory.fallback="false"
            mail.smtp.debug="true"/>
</Context>

Al igual que podemos configurar un recurso de tipo javax.sql.DataSource en el mismo archivo de configuración de la aplicación  para obtener conexiones a bases de datos configuramos un recurso de tipo javax.mail.Session, lo que logicamente cambiará serán los parametros para configurar uno y otro. En ambos casos el parámetro name indica en que punto del árbol JNDI donde se deja disponible el recurso. En el ejemplo los parámetros indicados son los necesarios para conectarse al servidor smtp con una cuenta de gmail.

¿Y porque configuramos el DataSource y la Sesion en el tomcat? Podríamos evitarnos esta configuración y meterla en el código de la aplicación pero esto tiene la desventaja de que para utilizar una nueva configuración necesitaríamos recompilar la aplicación, en el caso de tener la configuración externalizada en un archivo «$TOMCAT_HOME/conf/Catalina/localhost/[contexto app].xml» únicamente sería necesario un redespliegue de la aplicación lo que es más rápido y sencillo.

Para hacer uso de las clases java del paquete javax.mail.* necesitaremos la librerias de java mail (http://www.oracle.com/technetwork/java/javamail/index.html) pero también necesitaremos las clases de JAF (JavaBeans Activation Framework) (http://www.oracle.com/technetwork/java/javase/downloads/index-135046.html). Ambas librerias activation.jar y mail.jar deberemos colocarlas en el directorio lib de tomcat (en la versión 7.x). El lugar donde ponerlas es importante ya que si las colocamos en el directorio WEB-INF/lib de la aplicación java mail no va a funcionar.

Desde luego este es un ejemplo básico de como enviar un mensaje de correo electrónico de un texto plano desde java y si tenemos necesidad de enviar correos electrónicos puede que también necesitemos enviarlos en formato html para lo cual quizá nos convenga hacer uso de motores de plantillas como freemarker o velocity.

Referencia:
http://es.wikipedia.org/wiki/JNDI
http://tomcat.apache.org/tomcat-7.0-doc/config/context.html
http://tomcat.apache.org/tomcat-7.0-doc/config/resources.html
http://tomcat.apache.org/tomcat-7.0-doc/jndi-resources-howto.html