lunes, 7 de octubre de 2013

Enviado correos electronicos con JavaMail

Figura 1 - mail.jar
Figura 1 - mail.jar
Una de las funcionalidades deseables de algún sistema de manejo de datos seria el enviar automáticamente correos electrónicos al momento de que ocurra algún evento en particular, por fortuna si su sistema esta realizado en Java, agregar esta funcionalidad es bastante sencillo, gracias a la librería JavaMail.Para comenzar con su uso lo primero que necesitara es descargar dicha libreria desde la pagina http://www.oracle.com/technetwork/java/index-138643.html necesitara aceptar una licencia de terminos de uso para poder llevar a cabo la descarga, una vez que lo haga extraiga el archivo mail.jar del .zip que descargo


Ahora necesita crear un nuevo proyecto en Eclipse y agregar dicha libreria (mail.jar) al proyecto, instrucciones detalladas en como realizar esta acción pueden encontrarse en una entrada anterior de este blog, basta con que remplaze itext.jar con mail.jar http://hashblogeando.wordpress.com/2013/07/14/itext-generacion-de-archivo-pdf-en-java/ el proyecto resultante lucira similar a la figura 2

Figura 2 - Proyecto con mail.jar
Figura 2 - Proyecto con mail.jar

Notara que en la figura el proyecto contiene dos archivos en el paquete mx.com.develHash.correo, los cuales son el código de nuestro programa y el archivo de propiedades, este ultimo es un archivo de texto plano con este contenido:

mail.smtp.host=smtp.gmail.com
mail.smtp.socketFactory.port=465
mail.smtp.starttls.enable=true
mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
mail.smtp.port=465
mail.smtp.auth=true

Copie estos datos en un archivo gmail.properties y coloque dicho archivo en el mismo directorio donde esta el código de nuestro programa como muestra la figura 3

Figura 3 - Ubicación de archivo .properties
Figura 3 - Ubicación de archivo .properties


La ubicación del archivo es muy importante, ya que el archivo gmail.properties contiene los datos para conectarse con el servidor de gmail y enviar un correo usando SSL

Ahora si, cree una nueva clase Java con el nombre CorreoSender.Java y copie el siguiente código:

package mx.com.develHash.correo;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

/**
 * Crea y envia un correo electronico

 * @author david
 *
 */

public class CorreoSender {

    static public void main(String[] args) {
        
        // Nombre de usuario y contraseña del correo respectivamente
        final String usuario = "<Su correo en gMail>";
        final String passwd = "<Su contraseña>";

        Properties props = new Properties();
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Calendar cal = Calendar.getInstance();
        Session session;

        // Obtenemos los datos para utilizar el servidor de correo
        try {

            props.load(CorreoSender.class.getClassLoader().getResourceAsStream(
                    "mx/com/develHash/correo/gmail.properties"));

        } catch (IOException e) {
            System.err.println("********** Error al acceder a gmail.properties");
            e.printStackTrace();
        }

        // Iniciamos sesion para envio de correos
        session = Session.getInstance(props, new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(usuario, passwd);
            }
        });

        // Creamos el coreo
        try {

            Message message = new MimeMessage(session);

            message.setFrom(new InternetAddress(usuario));
            message.setRecipients(Message.RecipientType.TO,
                    InternetAddress.parse("<Destinatario>"));

            message.setSubject("Correo de prueba");

            message.setText("Mensaje de prueba generado en la fecha "
                    + dateFormat.format(cal.getTime() ) );

            // Enviamos el correo
            System.out.println("Enviando correo...");

            Transport.send(message);

            System.out.println("Correo enviado");

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
    }
}

Las lineas en rojo se detallaran a continuación:

final String usuario = "<Su correo en gMail>" y final String passwd = "<Su contraseña>": Estas dos cadenas de texto simplemente contienen el nombre de usuario y la contraseña de su correo, en este caso particular el usuario y contraseña de su cuenta en gmail, cabe mencionar que el usuario debe estar en la forma nombreUsuario@gmail.com o de lo contrario no funcionara.

props.load(CorreoSender.class.getClassLoader().getResourceAsStream( "mx/com/develHash/correo/gmail.properties")); Con esta linea cargamos el contenido del archivo gmail.properties, que ,como ya se menciono, contiene los parametros de conexión con el servidor de gmail, noatara que en la linea indicada se hace mencion  tanto al nombre de la clase, CorreoSender, como a la ruta interna del paquete, mx/com/develHash/correo/gmail.properties,  esto es vital para que nuestro programa funcione, por lo que si modifico alguno de esos datos el cambio debe de reflejarse aquí también.

 session = Session.getInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(usuario, passwd); } Iniciamos una sesión con el servidor de correo y nos identificamos con este por medio del usuario y contraseña que declaramos anteriormente.

 message.setFrom(new InternetAddress(usuario)); Indicamos quien es el remitente del correo

message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(<Destinatario>)); Indicamos a quien deseamos enviar el correo.

message.setSubject("Correo de prueba"); Establecemos cual es el asunto del mensaje.

message.setText("Mensaje de prueba generado en la fecha " + dateFormat.format(cal.getTime() ) ); indicamos el texto del mensaje, en este caso en particular se agrega la fecha y hora de envio.

Transport.send(message); Enviamos el mensaje.

Una vez que ejecute el programa, si todo salio bien, obtendrá una salida en consola similar a la figura 4, debo mencionar que el envio no es instantáneo de que aparezca el mensaje "Enviando Correo..." a que se muestre "Correo Enviado" tomara un par de segundos.

Figura 4 - Salida del programa
Figura 4 - Salida del programa

Puede comprobar que el correo se halla enviado adecuadamente con abrir la cuenta de destino que halla seleccionado, lo que debería mostrarle un mensaje similar a la figura 5

Figura 5 - Resultado
Figura 5 - Resultado


Ya para concluir debo recordar que el ejemplo usa el correo con SSL, si bien esto es una medida de seguridad extra que no esta demas podría darse el caso que desee evitarla, si asi fuera le recomiendo revisar los ejemplos indicados en el area de referencias, los cuales además podrian darle ideas que tal vez se ajusten mas a lo que desea obtener. Aparte las posibilidades con javamail son bastante extensas y espero cubrir mas de estas en el futuro.

Por lo pronto espero que la entrada halla sido de ayuda y nos vemos pronto.

Referencias

http://www.chuidiang.com/java/herramientas/javamail/empezar-javamail.php

http://www.mkyong.com/java/javamail-api-sending-email-via-gmail-smtp-example/

martes, 1 de octubre de 2013

Accediendo a archivos de propiedades en Java

Al momento de crear aplicaciones en Java puede necesitar almacenar parámetros que la aplicación necesitara, que puede ir desde direcciones de correo, direcciones para acceso a base de datos, información de conexión o datos varios, si bien hay varias formas de hacer esto, yendo desde bases de datos a crear uno mismo los archivos, Java nos proporciona un mecanismo integrado para realizar esto, los archivos de propiedades.

Estos son sencillamente archivos de texto con el formato

<nombre_clave>=<valor_clave>

Los cuales Java tiene mecanismos para acceder en forma nativa y que nos presenta una convención en donde deben ubicarse dichos archivos, de modo que mover la aplicación en el sistema de archivos o llevarla a otro sistema no cause problemas, esto se explicara con mas detalle a su momento.

Creando el proyecto.

Comenzaremos creando un proyecto en Java, como se ve en la figura 1, si a leído entradas anteriores ya habrá notado que siempre uso el paquete mx.com.hashSoft, esta vez no sera la excepción, pero ahora es parte vital del programa por lo que debe recordar agregarlo al momento de crear la clase Propiedades.

Figura 1 - Proyecto nuevo
Figura 1 - Proyecto


Figura 2 - Archivo de texto
Figura 2 - Archivo de texto

Ahora crearemos el archivo propiedades, para esto cree un archivo de texto, como se ve en la figura 2, ya que el archivo exista escriba en este lo siguiente:

version=1.0
tipo=texto
data="Datos Datos Datos Datos Datos"

Y guarde el archivo, esto le presentara un dialogo como el de la figura 3

Figura 3 - Ruta del archivo
Figura 3 - Ruta del archivo


En este caso es vital que siga la ruta indicada, esto es necesario, la idea general es que nuestro archivo properties este en la misma carpeta donde nuestra clase esta, esto es necesario para poder acceder a este.

Figura 4 - Codigo de la clase Propiedades
Figura 4 - Código de la clase Propiedades


Ahora procederemos a escribir el código de la clase Propiedades, el cual es el siguiente:

package mx.com.hashSoft;

import java.io.IOException;
import java.util.Properties;

public class Propiedades {

      static public void main(String[] args){
          Properties prop = new Properties();

          try {
               prop.load( Propiedades.class.getClassLoader().getResourceAsStream("mx/com/hashSoft/datos.properties") );

               System.out.println("Contenido del campo version:\t" + prop.getProperty("version") );
               System.out.println("Contenido del campo tipo:\t" + prop.getProperty("tipo") );
               System.out.println("Contenido del campo data:\t" + prop.getProperty("data") );
          }catch(IOException ex)
          {
                System.err.println("Error al acceder al archivo de propiedades");
                ex.printStackTrace();

           }
      }
}

De esta clase hay tres lineas relevantes, que son:

import java.util.Properties; - Con esta linea importamos la clase necesaria para manipular y acceder a los archivos de propiedades

prop.load( Propiedades.class.getClassLoader().getResourceAsStream("mx/com/hashSoft/datos.properties") ); - Con esta linea estamos indicando que archivo de propiedades deseamos cargar, en este caso deseamos cargar datos.properties, que se encuentra en la ruta mx/com/hashSoft, notara que si remplaza los / con . obtiene el paquete Java donde ubicamos el archivo properties, como en la figura 5 Eclipse genero esa ruta automáticamente de modo que la estructura de los paquetes Java coincida con al organización de los archivos

Figura 5 - Ruta del archivo properties
Figura 5 - Ruta del archivo properties

Todo esto podrá parecer demasiado rebuscado, mas por que es, en efecto, posible escribir directamente la ruta del archivo, sin embargo hay una razón para acceder a los archivos de este modo en la mayoría de los casos no puede saber a ciencia cierta detalles como la ruta de instalación o el directorio donde se esta ejecutando el programa no se diga cuando se trata de una aplicación que se ejecuta en un servidor, pero el classpath siempre esta perfectamente definido y se mantiene constante, lo que hace este el modo mas seguro para acceder a los archivos properties.

Ya que tenga ambos archivos puede ejecutar el programa , con lo que obtendrá una salida como la figura 6

Figura 6 - Salida
Figura 6 - Salida



Puede modificar el archivo properties y con eso modificar la salida del programa, como ejemplo digamos que escribiera "tipo" con mayúscula, si hace ese cambio y ejecuta el programa obtendrá la salida de la figura 7, lo que demuestra que las claves distinguen de mayúsculas y minúsculas.

Figura 7 - Archivo Modificado
Figura 7 - Archivo Modificado

Y si cambia el valor de la clave eso se refleja en la salida, como muestra la figura 8

Figura 8 - Cambio de valor
Figura 8 - Cambio de valor


Y notara que incluso puede cambiar el orden en que están las claves y aun así la salida es la esperada.

Espero que la entrada halla sido de ayuda, y nos vemos pronto.

Referencias

 Java Properties File Examples - http://www.mkyong.com/java/java-properties-file-examples/