Hola a todos, a muchos desarrolladores se nos hace indispensable poder implementar un módulo de envío de mail en los sistemas que desarrollamos. Dependiendo del lenguaje está la complejidad o simplicidad de la codificación de éste y como muchos sabemos, Java no siempre es un precursor de lo simple.

Es por esto que quiero publicar y facilitarles a todos una clase Mail.java que permite realizar envío de correos a través de Google Apps y mediante un servidor de correos común y corriente.

El código funciona implementando la API de SUN JavaMail (así que descarguen el JAR con la API sino nunca podrán enviar correos) y proporciona 2 métodos. Uno llamado 'enviaGoogleApp' que permite enviar el correo a través de una cuenta de Google Apps y otro llamado 'envia' que envía correos a través de un servidor de correo definido.

El código de ambos métodos es idéntico, sólo cambia la forma de autenticarse en el servidor.

Los métodos de la clase Mail sólo requieren los siguientes datos:
1) Emisor del mensaje.
2) Asunto del correo.
3) Receptor(es) del correo.
4) mensaje del correo (en formato HTML o ASCII)
5) Archivos adjuntos.

Con una leve modificación y añadiendo 2 parámetros más se pueden añadir:
1) Receptores a quienes se copia el correo.
2) Receptores a quienes se les envía copia oculta.

El código es el siguiente:


package util.mail;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.Multipart;
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;

public class Mail {
 
 private class SMTPAuthenticator extends Authenticator {
  private String dEmail;
  private String dPassword;
  
  public SMTPAuthenticator(String email, String password){
   dEmail = email;
   dPassword = password;
  }
  
  public PasswordAuthentication getPasswordAuthentication(){
   return new PasswordAuthentication(dEmail, dPassword);
  }
 }
 
 /**
  * Función que permite enviar un correo electrónico con archivos adjunto.
  * <br>El contenido del correo puede estar en formato HTML.
  * @param emisor Correo de quién emite el correo
  * @param asunto Asunto del e-mail
  * @param receptores Correos de los receptores del e-mail
  * @param mensaje Mensaje del e-mail
  * @param adjuntos Ruta de archivos adjuntos en el e-mail
  * @return TRUE si el mail fue enviado con éxito, FALSE en caso contrario
  */
 public boolean enviaGoogleApp(String emisor, String asunto, List<String> receptores, String mensaje, List<String> adjuntos){
  boolean envioExitoso = true;
  String emailGetCursos = "cuenta.googleapps@algo.cl";
  String password = "password.de.cuenta.googleapps";
  Properties props = new Properties();
  props.put("mail.smtp.user", emisor);
  props.put("mail.smtp.host", "smtp.gmail.com");
  props.put("mail.smtp.port", "465");
  props.put("mail.smtp.starttls.enable", "true");
  props.put("mail.smtp.auth", "true");
  props.put("mail.smtp.socketFactory.port", "465");
  props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
  props.put("mail.smtp.socketFactory.fallback", "false");
  
  try{
   
   Authenticator auth = new SMTPAuthenticator(emailGetCursos, password);
   Session session = Session.getInstance(props, auth);

   MimeMessage message = new MimeMessage(session);
   InternetAddress[] dest = new InternetAddress[receptores.size()];
   for (int i=0;i<dest.length;i++){
    dest[i] = new InternetAddress( receptores.get(i) );
   }
   
   //Se define quién es el emisor del e-mail
      message.setFrom(new InternetAddress(emisor));
      InternetAddress[] replyTo = new InternetAddress[1];
      replyTo[0] = new InternetAddress( emisor );
      message.setReplyTo( replyTo );
   //Se definen el o los destinatarios
   message.addRecipients(Message.RecipientType.TO, dest);
   //message.addRecipients(Message.RecipientType.CC, dest);
   //message.addRecipients(Message.RecipientType.BCC, dest);

      
   //Se defina el asunto del e-mail
      message.setSubject(asunto);
 
      //Se seteo el mensaje del e-mail
      MimeBodyPart messageBodyPart = new MimeBodyPart();
      messageBodyPart.setContent(message,"text/html");
            
      Multipart multipart = new MimeMultipart();
      multipart.addBodyPart(messageBodyPart);
            
      //Se adjuntan los archivos al correo
      if( adjuntos!=null && adjuntos.size()>0 ){
         for( String rutaAdjunto : adjuntos ){
             messageBodyPart = new MimeBodyPart();
             File f = new File(rutaAdjunto);
             if( f.exists() ){
                DataSource source = new FileDataSource( rutaAdjunto );
                messageBodyPart.setDataHandler( new DataHandler(source) );
                messageBodyPart.setFileName( f.getName() );
                multipart.addBodyPart(messageBodyPart);
             }
         }
      }
      
      //Se junta el mensaje y los archivos adjuntos
      message.setContent(multipart);
      
      //Se envía el e-mail
      Transport.send( message );
  }
  catch (Exception e) {
   envioExitoso = false;
  }
  finally{
   //Se eliminan del servidor los archivos adjuntos
   if( adjuntos!=null && adjuntos.size()>0 ){
    for( String rutaAdjunto : adjuntos ){
     try{
      File arch = new File(rutaAdjunto);
         arch.delete();
     }
     catch (Exception e) {}
    }
   }
  }
  return envioExitoso;
 }
 
 /**
  * Función que permite enviar un correo electrónico con archivos adjunto.
  * <br>El contenido del correo puede estar en formato HTML.
  * @param emisor Correo de quién emite el correo
  * @param asunto Asunto del e-mail
  * @param receptores Correos de los receptores del e-mail
  * @param mensaje Mensaje del e-mail
  * @param adjuntos Ruta de archivos adjuntos en el e-mail
  * @return TRUE si el mail fue enviado con éxito, FALSE en caso contrario
  */
 public boolean envia(String emisor, String asunto, List<String> receptores, String mensaje, List<String> adjuntos){
  boolean envioExitoso = true;
  try{
      Properties props = System.getProperties();
 
      //Se define el servidor de correos
      props.put("mail.smtp.host", "ip.servidor.de.correos");
   props.put("mail.smtp.port", "puerto.servidor.de.correo (por defecto 25)");
 
      //Se obtiene sesión desde el servidor de correos
      Session session = Session.getInstance(props, null);
   session.setDebug(true);
   
      MimeMessage message = new MimeMessage(session);
   InternetAddress[] dest = new InternetAddress[receptores.size()];
   for (int i=0;i<dest.length;i++){
    dest[i] = new InternetAddress( receptores.get(i) );
   }
   
   //Se define quién es el emisor del e-mail
      message.setFrom(new InternetAddress(emisor));
      InternetAddress[] replyTo = new InternetAddress[1];
      replyTo[0] = new InternetAddress( emisor );
      message.setReplyTo( replyTo );
   //Se definen el o los destinatarios
   message.addRecipients(Message.RecipientType.TO, dest);
   //message.addRecipients(Message.RecipientType.CC, dest);
   //message.addRecipients(Message.RecipientType.BCC, dest);
      
   //Se defina el asunto del e-mail
      message.setSubject(asunto);
 
      //Se seteo el mensaje del e-mail
      MimeBodyPart messageBodyPart = new MimeBodyPart();
      messageBodyPart.setContent(message,"text/html");
            
      Multipart multipart = new MimeMultipart();
      multipart.addBodyPart(messageBodyPart);
            
      //Se adjuntan los archivos al correo
      if( adjuntos!=null && adjuntos.size()>0 ){
         for( String rutaAdjunto : adjuntos ){
             messageBodyPart = new MimeBodyPart();
             File f = new File(rutaAdjunto);
             if( f.exists() ){
                DataSource source = new FileDataSource( rutaAdjunto );
                messageBodyPart.setDataHandler( new DataHandler(source) );
                messageBodyPart.setFileName( f.getName() );
                multipart.addBodyPart(messageBodyPart);
             }
         }
      }
      
      //Se junta el mensaje y los archivos adjuntos
      message.setContent(multipart);
      
      //Se envía el e-mail
      Transport.send( message );
  }
  catch (Exception e) {
   envioExitoso = false;
  }
  finally{
   //Se eliminan del servidor los archivos adjuntos
   if( adjuntos!=null && adjuntos.size()>0 ){
    for( String rutaAdjunto : adjuntos ){
     try{
      File arch = new File(rutaAdjunto);
         arch.delete();
     }
     catch (Exception e) {}
    }
   }
  }
  return envioExitoso;
 }
 
 public static void main(String[] args) {
  List<String> receptores = new ArrayList<String>();
  receptores.add("mail.de.alguien@gmail.com");
  String emisor = "test@test.cl";
  String asunto = "Correo de prueba";
  String mensaje = "Este es un correo de <font color='red'><b>PRUEBA</b></font>";
  List<String> archivos = new ArrayList<String>();
  Mail m = new Mail();
  //m.envia(emisor, asunto, receptor, mensaje, null);
  m.enviaGoogleApp( emisor, asunto, receptores, mensaje, archivos);
 }
 
}

14 comentarios:

Anónimo dijo...

Hola, una consulta, como puedo hacer para que cuando mando un mail, via este metodo, me aparezca un nombre y no la direccion de mail, del quien emite el correo?
en resumen, mando un mail y el emisor me aparece con la dir de mail. necesito que aparezca quien envio el mail sea mi nombre.
Me explico?

egacl dijo...

Hola.
Si entiendo tu consulta. Es facil!
Al objeto javax.mail.internet.InternetAddress se le pueden setear la direccion de correo y el nombre personal. Puedes usar el método setPersonal(String).

Aca te dejo el link con la javadoc de la clase. http://download.oracle.com/javaee/5/api/javax/mail/internet/InternetAddress.html

Saludos

Anónimo dijo...

Perfecto. Gracias !!

10 puntos.

Anónimo dijo...

hola, te hago otra consulta, soy el mismo que te consulto, por el nombre del emisor..

cuando llamo a la aplicacion que envia el mail, le quiero pasar el texto del mensaje.

se lo mando como texto desde una variable String. pero al leer el mensaje, no me respeta los espacios, enter, etc...

de que manera le mando el texto para que se respete todo eso?

Vos lo mandas como String

public boolean enviaGoogleApp(String emisor, String asunto, List<String> receptores, String mensaje, List<String> adjuntos){

el String mansaje

egacl dijo...

Hola.

Lo que pasa es que en el ejemplo se setea el contenido del mail de la siguiente manera:

messageBodyPart.setContent(message,"text/html");

Por lo tanto, el contenido se interpretará como html y los saltos de linea son br. HTML escribe solo un espacio, si tienes mas de uno debería escribirse como nbsp.

Creo que si utilizas el método messageBodyPart.setContent(message), el contenido se interpretará como texto plano.

Saludos.

Anónimo dijo...

//Se seteo el mensaje del e-mail
088. MimeBodyPart messageBodyPart = new MimeBodyPart();
089. messageBodyPart.setContent(message,"text/html");
090.
091. Multipart multipart = new MimeMultipart();
092. multipart.addBodyPart(messageBodyPart);


aca es donde se deberia hacer el cambio ?

egacl dijo...

Este es el cambio que debes hacer:

//Se seteo el mensaje del e-mail
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(message,"text/plain");

Anónimo dijo...

perfecto otra vez, era eso.

desde ya gracias

saludos

Hernan Mara dijo...

Como hago para pasarle la rutaAdjunto desde la pc cliente?? siempre busca la ruta en donde se este corriendo la aplicación.

egacl dijo...

Hola Hernan, lo que pasa es que siempre antes de enviar el correo con el o los archivos adjuntos, estos deben ser subidos al servidor, ya que es aquí donde las aplicaciones web tienen privilegios para manipular dichos archivos. De otra manera no se puede. Espero te sirva.

Anónimo dijo...

Cuando escribo mi archivo adjunto se borra el archivo, desaparece, y nunca mas puedo volverlo a enviar como hago para que no se borre, exactamente se borra en File f=new File(rutaArchivo) se envia por correo si, pero como hago para que no se borre ?

Escolaris dijo...

Muchas Gracias, me es de gran utilidad.

j0zz dijo...

que version de libreria jar utilizas no me envia =(

egacl dijo...

Este es el link de la API JavaMail -> http://www.oracle.com/technetwork/java/javamail/index.html

Publicar un comentario en la entrada

top