jueves, 11 de julio de 2013

Funciones de Resumen MD5 y SHA en JAVA [aplicado a archivos]


El la publicación anterior compartí el código java para generar funciones hash a una cadena  utilizando los algoritmos MD2, MD5, SHA-1,SHA-256,SHA-384,SHA-256.

Si deseas puedes consultar  el post Funciones de Resumen MD5 y SHA en JAVA en el cual explico brevemente las funciones hash.

Para realizar las capturas de pantalla utilizo la aplicación publicada aquí: Aplicacion Java para realizar capturas de pantalla.


El código para obtener la cadena hash de un archivo es el siguiente:

import java.io.*;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.*;
import java.util.*;
/*Aplicacion para generar resumenes hash de un archivo
 * @marxs7 Less is better
 * http://marxs7.blogspot.com
 */
public class HashArchivo
{
    private static String hash;
   public static String generaHash(String rutaArchivo,String algoritmo)
   {
   
    //declarar funcion de resumen
      try{
      MessageDigest messageDigest = MessageDigest.getInstance(algoritmo); // Inicializa con algoritmo seleccionado
     
      //leer fichero byte a byte 
         try{
            InputStream archivo = new FileInputStream( rutaArchivo );
            byte[] buffer = new byte[1];
            int fin_archivo = -1;
            int caracter;
       
            caracter = archivo.read(buffer);
       
            while( caracter != fin_archivo ) {
         
               messageDigest.update(buffer); // Pasa texto claro a la función resumen
               caracter = archivo.read(buffer);
            }   
       
            archivo.close();//cerramos el archivo
            byte[] resumen = messageDigest.digest(); // Genera el resumen 
            
            //Pasar los resumenes a hexadecimal
            hash = "";
            for (int i = 0; i < resumen.length; i++)
            {
               hash += Integer.toHexString((resumen[i] >> 4) & 0xf);
               hash += Integer.toHexString(resumen[i] & 0xf);
            }
          //  System.out.println("Resumen "+algoritmo+" " + hash);
         }
         //lectura de los datos del fichero
         catch(java.io.FileNotFoundException fnfe) {
         //manejar excepcion archivo no encontrado
         }
         catch(java.io.IOException ioe) {
         //manejar excepcion archivo
         }
      
      }   
      //declarar funciones resumen
      catch(java.security.NoSuchAlgorithmException nsae) {
      //manejar excepcion algorito seleccionado erroneo
      }
        return hash;//regresamos el resumen
      
   }

}


A partir de este código podemos generar una interfaz gráfica que nos permita fácilmente  obtener el valor MD5 o SHA de un archivo en formato hexadecimal.

En mi caso la interfaz es la siguiente.




Descarga











domingo, 7 de julio de 2013

Funciones de Resumen MD5 y SHA en JAVA


A las funciones hash  también se les llama funciones picadillofunciones resumen o funciones de digest. Los hash o funciones de resumen son algoritmos que consiguen crear a partir de una entrada (ya sea un texto, una contraseña o un archivo, por ejemplo) una salida alfanumérica de longitud normalmente fija que representa un resumen de toda la información que se le ha dado (es decir, a partir de los datos de la entrada crea una cadena que solo puede volverse a crear con esos mismos datos).

Las funciones hash son útiles para almacenar passwords  en bases de datos, verificar la integridad de ficheros y también se aplican en procesos de firma digital.

Para generar estas cadenas de resumen utilizaremos la clase MessageDigest de Java.

Los algoritmos que implementaremos son los siguientes:
*MD2
*MD5
*SHA-1
*SHA-256
*SHA-384
*SHA-512

En el código a continuación se  observa que se crea un arreglo con los diferentes algoritmos. El método generador de hashes es estático y recibe como parámetro la cadena que se va a resumir y un entero que corresponde al indice del arreglo de algoritmos.


import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
 * @author marxs7 Less is better
 */
public class Hash{
    //algoritmos
    public static String[] algoritmos={"MD2","MD5","SHA-1","SHA-256","SHA-384","SHA-512"};

    /***
     * Convierte un arreglo de bytes a String usando valores hexadecimales
     * @param digest arreglo de bytes a convertir
     * @return String creado a partir de digest
     */
    private static String toHexadecimal(byte[] digest){
        String hash = "";
        for(byte aux : digest) {
            int b = aux & 0xff;
            if (Integer.toHexString(b).length() == 1) hash += "0";
            hash += Integer.toHexString(b);
        }
        return hash;
    }

    /***
     * Encripta una cadena mediante algoritmo de resumen de mensaje.
     * @param cadena texto a encriptar
     * @param algoritmo algoritmo de encriptacion, puede ser: MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512
     * @return mensaje encriptado
     */
    public static String getHash(String cadena, int tipoAlgoritmo){
        byte[] digest = null;
        byte[] buffer = cadena.getBytes();
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(algoritmos[tipoAlgoritmo]);
            messageDigest.reset();
            messageDigest.update(buffer);
            digest = messageDigest.digest();
        } catch (NoSuchAlgorithmException ex) {
            System.out.println("Error creando Hash");
        }
        return toHexadecimal(digest);
    }
    //El codigo comentado es solo para probar la funcionalidad.
     /* public static void main(String[] args){
          System.out.println("hola"+ " MD2 "+ getHash("hola",0));
          System.out.println("hola"+ " MD5 "+ getHash("hola",1));
          System.out.println("hola"+ " SHA-1 "+ getHash("hola",2));
          System.out.println("hola"+ " SHA-256 "+ getHash("hola",3));
          System.out.println("hola"+ " SHA-384 "+ getHash("hola",4));
          System.out.println("hola"+ " SHA-512 "+ getHash("hola",5));
      }*/
}

A partir de esta clase podemos crear una interfaz para hacer más fácil el uso de esta funcionalidad. En mi caso la aplicación recibe una cadena y al seleccionar algún algoritmo en el combo, muestra la cadena resultante. 

Descargar Aplicación. 18Kb
Descargar Código Fuente. Proyecto NetBeans 37 Kb









jueves, 13 de junio de 2013

Comprimir y Descomprimir archivos en formato ZIP [JAVA]


Antes de empezar es bueno incluir un poco de información acerca del formato ZIP:

En informáticaZIP o zip es un formato de almacenamiento sin pérdida, muy utilizado para la compresión de datos como documentos, imágenes o programas.Para este tipo de archivos se utiliza generalmente la extensión ".zip".Muchos programas, tanto comerciales como libres, lo utilizan y permiten su uso más habitual.

Considero que junto a el formato rar, son los formatos de compresión de archivos más utilizados. La máquina virtual de Java nos permite el manejo de este tipo de archivos. Con una clase que contenga los métodos de compresión / descompresión  podemos realizar fácilmente una aplicación portable y ligera que realice la compresión y descompresión de archivos desde nuestra memoria USB.

A continuación podemos ver el código para manejar archivos .ZIP

//Primero importar librerias para manejo de archivos y archivos zip
import java.util.zip.*;

import java.io.*;

public class ZIP {

private static final int BUFFER_SIZE = 1024;

        public void Comprimir(String archivoOriginal, String archivoZIP) throws Exception {
// bjetos en memoria
FileInputStream archivoEntrada = null;
FileOutputStream archivoSalida = null;
ZipOutputStream zipos = null;

// buffer
byte[] buffer = new byte[BUFFER_SIZE];
try {
// fichero entrada
archivoEntrada = new FileInputStream(archivoOriginal);
archivoSalida = new FileOutputStream(archivoZIP);
// fichero comprimido
zipos = new ZipOutputStream( archivoSalida);
ZipEntry zipEntry = new ZipEntry(archivoOriginal);
zipos.putNextEntry(zipEntry);
int len = 0;
// zippear
while ((len = archivoEntrada.read(buffer, 0, BUFFER_SIZE)) != -1)
zipos.write(buffer, 0, len);
// volcar la memoria al disco
zipos.flush();
} catch (Exception e) {
throw e;
} finally {
// cerramos los archivos
zipos.close();
archivoEntrada.close();
archivoSalida.close();
} // cerramos try.
} // cerramos Comprimir

public void Descomprimir(String archivoZIP, String archivoDescomprimido) throws Exception {
BufferedOutputStream bos = null;
FileInputStream fis = null;
ZipInputStream zipis = null;
FileOutputStream fos = null;

try {
fis = new FileInputStream(archivoZIP);
zipis = new ZipInputStream(new BufferedInputStream(fis));
if (zipis.getNextEntry() != null) {
int len = 0;
byte[] buffer = new byte[BUFFER_SIZE];
fos = new FileOutputStream(archivoDescomprimido);
bos = new BufferedOutputStream(fos, BUFFER_SIZE);

while  ((len = zipis.read(buffer, 0, BUFFER_SIZE)) != -1)
bos.write(buffer, 0, len);
bos.flush();
} else {
throw new Exception("Zip Vacio");
} // cierra if
} catch (Exception e) {
throw e;
} finally {
bos.close();
zipis.close();
fos.close();
fis.close();
} // cierra try

} // cierra descomprimir

Debemos entender que al comprimir ingresamos la ruta del archivo a comprimir como primer parámetro y la ruta del fichero resultante como segundo parámetro. En descomprimir es el orden contrario. Espero haber escrito las variables de manera entendible.

Para probar el código podemos crear una nueva Main Class o agregar esto al final.

                        ZIP archivo = new ZIP();
                        String archivoEntrada="imagen.jpg";//ruta del fichero original 
                        String archivoSalida="imagen.zip";//ruta del fichero generado
archivo.Comprimir(archivoEntrada, archivoSalida);
System.out.println("Comprimido en zip!");
                        archivoEntrada="imagen.zip";//ruta del fichero original 
                        archivoSalida="imagen2.jpg";//ruta del fichero generado
archivo.Descomprimir(archivoEntrada, archivoSalida);
System.out.println("ZIP Descomprimido!");

El texto resaltado corresponde a las rutas usadas para probar el programa. Debes colocar una imagen.jpg en tu proyecto al mismo nivel que la carpeta src o simplemente prueba con cualquier otra ruta.

Próximamente actualizaré la publicación compartiendo una aplicación gráfica que comprima y descomprima los archivos ZIP.

martes, 11 de junio de 2013

Aplicación Java para realizar Capturas de Pantalla


El día de hoy se me ocurrió realizar una aplicación que realizara capturas de pantalla, o impresiones de pantalla y que las exportara a un archivo de imagen jpg, png, gif, bmp, etc

Investigando un poco encontré información acerca de la clase Robot y entre otras cosas  la clase nos permite realizar capturas de nuestra pantalla con gran nitidez(también depende del tipo de imagen generado).



No me extenderé tratando de explicar cada formato de imagen porque no es el objetivo de mi publicación. Pueden jugar con el código y experimentar, para así sacar sus propias conclusiones.

Este es el ejemplo más sencillo para hacer una captura de la pantalla completa.

import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;

class CapturarPantalla {
  public static void main(String args[])
        throws AWTException, IOException {
     // captura la pantalla completa
     BufferedImage pantalla = new Robot().createScreenCapture(
     new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );//se obtiene el tamaño de la pantalla
     
     // Lo guarda como un png, podemos modificarlo y guardarlo como jpg,gif,bmp
     File file = new File("pantalla.png");//creamos el archivo
     ImageIO.write(pantalla, "png", file);//escribimos la imagen en archivo   
   }
}


Como podrán observar el código es muy simple. La linea resaltada en rojo corresponde el lugar donde se guardara el archivo. En este caso se crea en la carpeta principal del proyecto. Es posible escribir cualquier ubicación válida, por ejemplo "d:/pantalla.png", "c:/capturas/pantalla.png", etc.

Si deseamos conocer los formatos de imagen disponibles podemos mostrarlos con el siguiente código.
String writerNames[] = ImageIO.getWriterFormatNames();
     for(String aux:writerNames){
         System.out.println(aux);
     }

Parece una forma muy simple de realizar capturas de pantalla. Pero lo más útil sería que fuera una interfaz gráfica la que te ayudara a realizar esta función. Todo depende de la creatividad e imaginación del programador.

Mi aplicación.
En mi caso las interfaces gráficas no son lo mio, realice una aplicación sencilla que nos permite fácilmente capturar la pantalla o parte de ella y almacenarla en un archivo en múltiples formatos. El único formato que al parecer no me funciono fue wbmp,WBMP

La app tiene un tamaño de 83.4 kb y puedes guardarla en tu memoria usb.

Al posicionar el cursor sobre los elementos de la aplicación podemos obtener la descripción de sus funciones.

¿Como funciona?
1.-El funcionamiento es muy sencillo, el botón con el icono realiza la captura de pantalla.
2.-Puedes elegir 2 tipos de capturas:
    a)Pantalla completa: Como su nombre lo dice captura toda la pantalla.
    b)Seleccionado: Captura el área seleccionada. ¿Como seleccionar? Cuando se elige "Seleccionado" la ventana permite ser re dimensionada y sirve para capturar el área cubierta por la ventana de la aplicación.

3.-Tipo de Imagen: Selecciona el formato para exportar la imagen. Puede ser jpg, jpeg,gif,png . La opción predeterminada es png ya que genera imágenes más claras.

4.- Delay(segundos):  Es el tiempo que debe pasar entre ocultar la ventana de aplicación y realizar la captura. Evita que se incluya la ventana de aplicación en la captura. En caso de que aparezcan restos de la ventana se debe aumentar el valor. Si quiere incluir la ventana de la aplicación en la imagen seleccione 0.

5.-Guardar en: Su función es elegir la carpeta donde se guarda la imagen. Si no lo define se mostrará Ubicación de la aplicación. Esto quiere decir que la captura se almacenara en la carpeta donde se ubica la aplicación y se nombrara como captura_11062013_22-58-27.png  donde los números significan día,mes, año_hora-minuto-segundo

6.-Abrir imagen creada. Esta opción permite que después de generado el archivo se muestre con el visor de imágenes. Si marca la opción se mostrará la imagen, de lo contrario no.



Si deseas probar la aplicación puedes descargarla .

MEGA Screen.rar (54 KB)
DropBox Screen.rar(54 KB)
Box Screen.rar(54 KB)




martes, 4 de junio de 2013

Java Mail (Parte4) Obtener mensajes no leídos de GMail y Yahoo Mail [IMAP]

El envío de mensajes a través de JavaMail es un proceso de baja complejidad comparado con la lectura de los mensajes de nuestra bandeja de entrada.
La complejidad es causada porque cuando nosotros enviamos en mensaje especificamos que elementos contiene el cuerpo del mensaje, cuando intentamos leer los mensajes esto es un problema. No sabemos con certeza si el mensaje solo contiene texto, si esta en formato HTML, si contiene uno o mas adjuntos y que tipo de archivos están adjuntados(imágenes, documentos, archivos comprimidos, audio,video,etc)

A continuación presento en código fuente de una clase Java que obtiene los mensajes sin leer de nuestra cuenta de GMail ó Yahoo. Sólo se muestra el texto de los mensajes, en caso de que el mensaje contenga adjuntos no mostrará nada.

Este código es una modificación del que se encuentra en aqui. Para que la aplicación funcione correctamente es necesario importar las librerías  disponibles en este post

Aclaro que este ejemplo solo muestra los mensajes de tipo texto, si contiene imágenes o archivos adjuntos no se mostrará.

import java.util.Properties;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.search.FlagTerm;

public class EmailReader {

    public static void main(String args[]) {
        Properties props = System.getProperties();
        props.setProperty("mail.store.protocol", "imaps");
        try {
                Session session = Session.getDefaultInstance(props, null);
                Store store = session.getStore("imaps");

                // servidor IMAP para gmail. 
                // remplazar <usuario> con su usuario de Gmail.
                // remplazar <password> con el password correspondiente al usuario especificado.

                store.connect("imap.gmail.com", "usuario@gmail.com", "password");

                // Servidor IMAP para yahoo.
                //store.connect("imap.mail.yahoo.com", "<username>", "<password>");

                System.out.println(store);

                Folder inbox = store.getFolder("Inbox");
                inbox.open(Folder.READ_ONLY);
                mostrarCorreosNoLeidos(inbox);//indicamos que lee los mails no leidos
                   
                
        } catch (NoSuchProviderException e) {
            System.out.println(e.toString());
            System.exit(1);
        } catch (MessagingException e) {
            System.out.println(e.toString());
            System.exit(2);
        }

    }
    
    static public void mostrarCorreosNoLeidos(Folder inbox){        
        try {
            FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
            Message msg[] = inbox.search(ft);
            System.out.println("Correos sin leer: "+msg.length);
            for(Message message:msg) {
                try {
                    System.out.println("Fecha: "+message.getSentDate().toString());
                    System.out.println("De: "+message.getFrom()[0].toString());            
                    System.out.println("Asunto: "+message.getSubject().toString());
                    System.out.println("Contenido: "+message.getContent().toString());
                    System.out.println("******************************************");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    System.out.println("Sin Información");
                }
            }
        } catch (MessagingException e) {
            System.out.println(e.toString());
        }
    }
}


------------------------------------------------------------------------------------------------------------
Por el momento sigo tratando de entender la estructura de los mensajes para poder leer mensajes complejos en formato HTML y con Archivos adjuntos, espero publicar una entrada en la que explique como realizar la lectura de mensajes complejos.

sábado, 25 de mayo de 2013

JavaMail(Parte 3) Enviar un correo con múltiples destinatarios y múltiples adjuntos.


----------------------------------------------------------------------------------------------------
Links de descarga Simple Mail
SimpleMail.rar (7.5 MB)
SimpleMailMini.rar (1.7 MB)
SimpleMailMicroP.rar (861 KB)
SimpleMailMicroA.rar (860 KB)

Información del proyecto en Taringa!
 ----------------------------------------------------------------------------------------------------
En las dos entradas anteriores mostré la forma de enviar un mail y enviar un mail con un archivo adjunto. Los  datos a utilizar estaban definidos de forma estática y era simplemente para demostración. En esta ocasión dejo el código que ya he modificado para volverlo más general y se puedan usar variables y parámetros para utilizarlo en una interfaz gráfica.

A continuación dejo en código.


/* @author marxs7
 * basado en código de Chuidiang
 * En este ejemplo se usa Gmail pero pueden utilizar cualquier servidor
 * solo remplacen los valores asignados a servidorSMTP Y puertoEnvio.
 */
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class EnviarCorreoMejorado
{   String miCorreo;
    String miPassword;
    String servidorSMTP="smtp.gmail.com";
    String puertoEnvio="587";// puertoEnvio="587";//465 para mensajes normales y 587 con adjuntos
    String[] destinatarios;
    String asunto;
    String cuerpo = null;//cuerpo del mensaje
    String[] archivoAdjunto;
    
  public EnviarCorreoMejorado(String usuario,String pass,String[] dest,String asun,String mens,String[] archivo){
        destinatarios=dest;
        asunto=asun;
        cuerpo=mens;
        archivoAdjunto=archivo;  
        miCorreo=usuario;
        miPassword=pass;
     }
    
    public void Enviar() throws MessagingException
    {
            Properties props=null;
            props = new Properties();
            props.put("mail.smtp.host", servidorSMTP);
            props.setProperty("mail.smtp.starttls.enable", "true");//si usa Yahoo comentar esta linea         
            props.setProperty("mail.smtp.port", "587");
            props.setProperty("mail.smtp.user", miCorreo);
            props.setProperty("mail.smtp.auth", "true");
            SecurityManager security = System.getSecurityManager();
     
            Authenticator auth = new EnviarCorreoMejorado.autentificadorSMTP();
            Session session = Session.getInstance(props, auth);
           // session.setDebug(true); //Descomentar para ver el proceso de envio detalladamente
            
            // Se compone la parte del texto
            BodyPart texto = new MimeBodyPart();
            texto.setText(cuerpo);
            
            // Se compone el adjunto 
            BodyPart[] adjunto=new BodyPart[archivoAdjunto.length];
            for(int j=0;j<archivoAdjunto.length;j++){
            adjunto[j]=new MimeBodyPart();
            adjunto[j].setDataHandler(
                new DataHandler(new FileDataSource(archivoAdjunto[j])));
            
            String[] rutaArchivo = archivoAdjunto[j].split("/");//separamos las palabras que forman la url y las                 ponemos en arreglo  de cadenas
            int nombre=rutaArchivo.length-1;//del array buscamos la ultima posicion
            adjunto[j].setFileName(rutaArchivo[nombre]);//la ultima posicion debe tener el nombre del archivo
            }
            

            // Una MultiParte para agrupar texto e imagen.
            MimeMultipart multiParte = new MimeMultipart();
            multiParte.addBodyPart(texto);
            for(BodyPart aux:adjunto){
                multiParte.addBodyPart(aux);
            }
            

            // Se compone el correo, dando to, from, subject y el
            // contenido.
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(miCorreo));
            Address []destinos = new Address[destinatarios.length];//Aqui usamos el arreglo de destinatarios
            for(int i=0;i<destinos.length;i++){
                destinos[i]=new InternetAddress(destinatarios[i]);
            }
            message.addRecipients(Message.RecipientType.TO, destinos);//agregamos los destinatarios
            message.setSubject(asunto);
            message.setContent(multiParte);

            // Se envia el correo.
            Transport t = session.getTransport("smtp");
            t.connect(miCorreo, miPassword);
            t.sendMessage(message, message.getAllRecipients());
            System.out.println("Correo Enviado exitosamente!"); 
            t.close();    
        }
     private class autentificadorSMTP extends javax.mail.Authenticator {
        public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(miCorreo, miPassword);
        }
    }
        
    }


Cualquier duda o pregunta déjenla en los comentarios. Si necesitan las librerías o servidores y puertos SMTP pueden encontrarlos en la Primer entrada acerca de Java Mail.

En la próxima publicación se implementará un parámetro extra para poder definir el servidor de correo dinámicamente.

miércoles, 15 de mayo de 2013

 JavaMail(Parte 2) Enviar un correo con un dato adjunto.


En la publicación anterior realice el envío de un correo electrónico lo mas simple posible. Ahora adaptaremos el código para enviar un correo electrónico con un dato adjunto.

Recomiendo que visiten el post anterior para descargar las librerías y leer la explicación acerca del envío de correos electrónicos con JavaMail. Ir a entrada anterior.



import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
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.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
/**
 * Ejemplo de envio de un correo de texto con una imagen adjunta con javamail
 * @author marxs7
  */
public class EnviarCorreoConAdjunto
{   String miCorreo="miCorreo@gmail.com";
    String miPassword="miPassword";
    String servidorSMTP="smtp.gmail.com";
    String puertoEnvio="587";
    String destinatario="destinatario@gmail.com";
    String asunto="Correo con adjunto";
    String mensaje = "mensaje con adjunto desde JAVA";//cuerpo del mensaje
    String archivoAdjunto=null;
    String nombreArchivo;
   
   
    public EnviarCorreoConAdjunto(String archivo,String nombre){
        archivoAdjunto=archivo;
        nombreArchivo=nombre;
    }    
    public void Enviar() throws MessagingException
    {
         
            Properties props=null;
            props = new Properties();
            props.put("mail.smtp.host", servidorSMTP);
           //si usan yahoo comentar la linea siguiente
                 props.setProperty("mail.smtp.starttls.enable", "true");
            props.setProperty("mail.smtp.port", "587");
            props.setProperty("mail.smtp.user", miCorreo);
            props.setProperty("mail.smtp.auth", "true");

            SecurityManager security = System.getSecurityManager();

     
            Authenticator auth = new EnviarCorreoConAdjunto.autentificadorSMTP();
            Session session = Session.getInstance(props, auth);
           // session.setDebug(true);//Descomentar si quieren ver en consola el proceso detallado
           

            // Se compone la parte del texto
            BodyPart texto = new MimeBodyPart();
            texto.setText(mensaje);
            BodyPart adjunto = new MimeBodyPart();
           adjunto.setDataHandler(new DataHandler(new FileDataSource(archivoAdjunto)));
           adjunto.setFileName(nombreArchivo);//es para que al descargar el archivo se
                                            //descargue con el formato correcto
           
           
            // Una MultiParte para agrupar texto e imagen.
            MimeMultipart multiParte = new MimeMultipart();
            multiParte.addBodyPart(texto);
            multiParte.addBodyPart(adjunto);
         
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(miCorreo));//quien lo envia
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(destinatario));//destinatario
            message.setSubject(asunto);//asunto
            message.setContent(multiParte);//asignamos los datos al mensaje

            // Se envia el correo.
            Transport t = session.getTransport("smtp");
            t.connect(miCorreo, miPassword);
            t.sendMessage(message, message.getAllRecipients());
            //System.out.println("Correo Enviado exitosamente!");
            t.close();
           
           
        }
     private class autentificadorSMTP extends javax.mail.Authenticator {
        public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(miCorreo, miPassword);
        }
     }
       
     public static void main(String[] args) throws MessagingException {
        // TODO Auto-generated method stub
        EnviarCorreoConAdjunto EnviarAdjunto = new EnviarCorreoConAdjunto("c:/imagen.gif",
                "imagen.gif");
        EnviarAdjunto.Enviar();
       
        System.out.println("Mensaje Enviado");
    }
    }

Esta en la base para el envío de correos electrónicos con datos adjuntos. Podemos adecuar el código expuesto de acuerdo a nuestras necesidades. Este ejemplo es demasiado sencillo solo es para comprender mejor la estructura. Cada persona puede predefinir los parámetros que le convenga.
Si desean crear una interfaz gráfica solo modifiquen el constructor para que acepte los parámetros que consideren necesarios.

En la próxima entrada explicaré la forma de enviar un correo electrónico con múltiples datos adjuntos a múltiples destinatarios.