Tutorial para enviar correo desde Java. JavaMail.
Tabla De Contenidos
1. Descargar la API JavaMail.
2. Creación del proyecto Java para enviar correos.
3. Enviar correo con mensaje básico (Varios Destinatarios).
4. Enviar correo con mensaje básico y un archivo adjunto.
5. Enviar correo con formato HTML (Tipo Notificación).
1. Descargar la API JavaMail.
Para enviar correo desde java tenemos que descargar la API JavaMail desde su pagina oficial, para añadirla a nuestro proyecto, vamos hacer este tutorial con la versión javax.mail-1.5.4.jar de JavaMail.
2. Creación del proyecto Java para enviar correos.
Para comenzar vamos a crear un proyecto nuevo en nuestro IDE (En este caso utilizo JBoss Developer Studio, eclipse) y le pondremos el nombre de
CorreosDatoJava
, creamos un paquete nuevo llamado correosDJ
, y vamos a importar a el build path del proyecto la librería que descargamos javax.mail-1.5.4.jar. Hasta ahora la estructura del proyecto debería verse así:
3. Enviar correo con mensaje básico (Varios Destinatarios).
En este primer ejemplo vamos a crear una clase en el paquete
correosDJ
en la cual vamos a implementar la funcionalidad para enviar un correo basico, al decir basico, me refiero a que tendrá como contenido un texto simple y será enviado a varios destinatarios. La clase lleva por nombre DJCorreoTexto
y tiene su metodo static void main(String[] args)
. Este es el código:
DJCorreoTexto.java
package correosDJ; import java.util.Properties; import javax.mail.Message; import javax.mail.Multipart; 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; /** * @author datojava.blogspot.com */ public class DJCorreoTexto { public void mandarCorreo() { // El correo gmail de envío String correoEnvia = "tuCorreo@gmail.com"; String claveCorreo = "tu clave"; // La configuración para enviar correo Properties properties = new Properties(); properties.put("mail.smtp.host", "smtp.gmail.com"); properties.put("mail.smtp.starttls.enable", "true"); properties.put("mail.smtp.port", "587"); properties.put("mail.smtp.auth", "true"); properties.put("mail.user", correoEnvia); properties.put("mail.password", claveCorreo); // Obtener la sesion Session session = Session.getInstance(properties, null); try { // Crear el cuerpo del mensaje MimeMessage mimeMessage = new MimeMessage(session); // Agregar quien envía el correo mimeMessage.setFrom(new InternetAddress(correoEnvia, "Dato Java")); // Los destinatarios InternetAddress[] internetAddresses = { new InternetAddress("correo1@gmail.com"), new InternetAddress("correo2@gmail.com"), new InternetAddress("correo3@gmail.com") }; // Agregar los destinatarios al mensaje mimeMessage.setRecipients(Message.RecipientType.TO, internetAddresses); // Agregar el asunto al correo mimeMessage.setSubject("Dato Java Enviando Correo."); // Creo la parte del mensaje MimeBodyPart mimeBodyPart = new MimeBodyPart(); mimeBodyPart.setText("Siguiendo el Tutorial de datojava.blogspot.com envío el correo."); // Crear el multipart para agregar la parte del mensaje anterior Multipart multipart = new MimeMultipart(); multipart.addBodyPart(mimeBodyPart); // Agregar el multipart al cuerpo del mensaje mimeMessage.setContent(multipart); // Enviar el mensaje Transport transport = session.getTransport("smtp"); transport.connect(correoEnvia, claveCorreo); transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients()); transport.close(); } catch (Exception ex) { ex.printStackTrace(); } System.out.println("Correo enviado"); } public static void main(String[] args) { DJCorreoTexto correoTexto = new DJCorreoTexto(); correoTexto.mandarCorreo(); } }Viendo el código apreciamos que no es nada de otro mundo enviar correos utilizando la API de JavaMail, primero establecemos en variables desde donde vamos a enviar los correos (21,22), después configuramos los parámetros para el envió de correos, la misma configuración la hacemos utilizando java.util.Properties (25..31), obtenemos la sesión de JavaMail pasando como parámetro la configuración anterior (34), creamos el objeto MimeMessage, que básicamente es toda la información que comprende el mensaje enviado, quien envía el correo, el(los) destinatarios, el asunto... (38..54), después creamos el objeto MimeBodyPart, la parte que tiene el mensaje a enviar (57,58), creamos el objeto Multipart en el cual vamos agregar las partes (MimeBodyPart) del mensaje para posteriormente agregar dicho objeto al MimeMessage (61..65), enviamos el correo con el objeto Transport (68..71).
Para entender un poco más acerca del funcionamiento de JavaMail, puedes ver este grafico.
534-5.7.14 Learn more at
34 5.7.14 https://support.google.com/mail/answer/78754
... En fin lo que quiere decir este error es que no está permitido que las aplicaciones menos seguras (nuestra aplicación) accedan a tu cuenta, para arreglar eso tenemos que habilitar esa opción en este link y listo.34 5.7.14 https://support.google.com/mail/answer/78754
Si todo va bien en la consola debería mostrarte "Correo enviado" y los destinatarios recibirán el correo en la bandeja de entrada de esta forma.
4. Enviar correo con mensaje básico y un archivo adjunto.
Básicamente es el mismo código anterior, solo que para agregar el archivo adjunto tenemos que crear otro objeto MimeBodyPart, al mismo le adjuntamos el archivo con el metodo
attachFile(String File)
, no importa si es un archivo .pdf, .xlsx, .txt, .jpg, .docx... Es indiferente solo hay que pasarle como parámetro a ese método la url del archivo. Esta porción de código hay que añadirla al ejemplo anterior:
MimeBodyPart mimeBodyPartAdjunto = new MimeBodyPart(); mimeBodyPartAdjunto.attachFile("C:/Users/datojava/DatoJava.docx"); // Resto del codigo... // // // Agregarlo al MultiPart multipart.addBodyPart(mimeBodyPartAdjunto);Si no hay errores así se vería en la bandeja de entrada:
5. Enviar correo con formato HTML (Tipo Notificación).
Aquí si hay un poco de diferencia al código anterior, en realidad la configuración del correo siempre será la misma (por lo menos en este ejemplo), lo que cambia ahora es que queremos mandar dentro del correo, un mensaje hecho en html, no vamos a crear un simple "Hola Mundo", vamos hacer algo chévere y sencillo con imágenes para que no quede duda de cómo se implementa. Vamos a mostrar el código por partes para ir explicando poco a poco.
Primero vamos a crear un archivo en nuestro IDE, new> other> File, que llevará por nombre
PlantillaDJ
, en esta plantilla hacemos el código html para posteriormente pintarlo en el mensaje. Vamos hacer un mensaje de notificación para un cliente que acaba de comprar un producto en nuestra tienda, así se verá el mensaje HTML en el cuerpo del correo:
PlantillaDJ
<html> <body>Estimado Cliente, le informamos que su compra</body> </html>
se realizo con éxito.
Puede retirar su compra de lunes a viernes
en horario corrido de 9:00am a 7:00pm.
<img src="cid:datojava.png"
para agregar la imagen al código la obtenemos del Content-ID
(cid) que vamos a crear en la clase DJCorreoHTML
que implementa esta plantilla.Ahora vamos a implementar la clase que se encarga de enviar el correo con un mensaje HTML, la vamos a llamar
DJCorreoHTML
y seguimos con la misma configuración de Gmail, lo que tenemos que hacer ahora es leer la plantilla que hemos creado previamente e ir almacenándola en un StringBuffer
para luego enviar el correo, este es el código completo de la clase:
DJCorreoHTML
package correosDJ; import java.io.BufferedReader; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Properties; import javax.mail.Message; import javax.mail.Multipart; 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; /** * @author datojava.blogspot.com */ public class DJCorreoHTML { public void mandarCorreo() { // El correo gmail de envío String correoEnvia = "tuCorreo@gmail.com"; String claveCorreo = "tuClave"; // La configuración para enviar correo Properties properties = new Properties(); properties.put("mail.smtp.host", "smtp.gmail.com"); properties.put("mail.smtp.starttls.enable", "true"); properties.put("mail.smtp.port", "587"); properties.put("mail.smtp.auth", "true"); properties.put("mail.user", correoEnvia); properties.put("mail.password", claveCorreo); // Obtener la sesion Session session = Session.getInstance(properties, null); try { // Crear el cuerpo del mensaje MimeMessage mimeMessage = new MimeMessage(session); // Agregar quien envía el correo mimeMessage.setFrom(new InternetAddress(correoEnvia, "Dato Java")); // Los destinatarios InternetAddress[] internetAddresses = { new InternetAddress( "correo1@gmail.com") }; // Agregar los destinatarios al mensaje mimeMessage.setRecipients(Message.RecipientType.TO, internetAddresses); // Agregar el asunto al correo mimeMessage.setSubject("Dato Java Enviando Correo HTML."); // Crear el multipart para agregar la parte del mensaje anterior Multipart multipart = new MimeMultipart(); // Leer la plantilla InputStream inputStream = getClass().getResourceAsStream( "PlantillaDJ"); BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream)); // Almacenar el contenido de la plantilla en un StringBuffer String strLine; StringBuffer msjHTML = new StringBuffer(); while ((strLine = bufferedReader.readLine()) != null) { msjHTML.append(strLine); } // Url del directorio donde estan las imagenes String urlImagenes = "url del directorio donde estan las imagenes"; File directorio = new File(urlImagenes); // Obtener los nombres de las imagenes en el directorio String[] imagenesDirectorio = directorio.list(); // Creo la parte del mensaje HTML MimeBodyPart mimeBodyPart = new MimeBodyPart(); mimeBodyPart.setContent(msjHTML.toString(), "text/html"); // Validar que el directorio si tenga las imagenes if (imagenesDirectorio != null) { for (int count = 0; count < imagenesDirectorio.length; count++) { MimeBodyPart imagePart = new MimeBodyPart(); imagePart.setHeader("Content-ID", "<" + imagenesDirectorio[count] + ">"); imagePart.setDisposition(MimeBodyPart.INLINE); imagePart.attachFile(urlImagenes + imagenesDirectorio[count]); multipart.addBodyPart(imagePart); } } else { System.out.println("No hay imagenes en el directorio"); } // Agregar la parte del mensaje HTML al multiPart multipart.addBodyPart(mimeBodyPart); // Agregar el multipart al cuerpo del mensaje mimeMessage.setContent(multipart); // Enviar el mensaje Transport transport = session.getTransport("smtp"); transport.connect(correoEnvia, claveCorreo); transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients()); transport.close(); } catch (Exception ex) { ex.printStackTrace(); } System.out.println("Correo enviado"); } public static void main(String[] args) { DJCorreoHTML correoHTML = new DJCorreoHTML(); correoHTML.mandarCorreo(); } }El código comienza a cambiar desde la línea 61, en la cual comenzamos a leer y almacenar el contenido de la plantilla en un
StringBuffer
(62..72), como el mensaje del correo posee algunas imágenes, la mejor manera es colocar las imágenes que vamos a utilizar en un mismo directorio, y así en Java indicamos el directorio donde están las imágenes y obtenemos sus nombres (74..79), después creamos el MimeBodyPart en el cual establecemos que es de tipo HTML y también agregamos el contenido de la plantilla almacenada en el StringBuffer
(82,83), validamos que el directorio no este vacío, si todo va bien vamos a crear un MimeBodyPart por cada imagen encontrada, en el header establecemos el Content-ID
con el nombre de cada imagen encontrada y así podemos añadirla al codigo HTML, sucesivamente cada imagen la agregamos al Multipart (86..99), el resto se mantiene igual a los ejemplos anteriores.
Si todo está bien el correo deberíamos recibirlo de esta manera
Hola qué tal!
ResponderEliminarExcelente aporte, aunque tengo una pequeña duda, ¿es posible agregar variables a la platilla?
De ser así cómo se definirían las mismas para que el correo pueda ser un poco más "personalizado".
De antemano gracias!
Amigo Krlos, creo que una manera sencilla de hacer eso seria aplicándole un "replace" al String de toda la plantilla (msjHTML), por ejemplo:
EliminarCada vez que quieras agregar una variable a la plantilla puedes utilizar una secuencia de caracteres para así identificarla, por decir algo "$$nombre", buscas esa secuencia y le aplicas el replace:
msjHTML = msjHTML.replace("$$nombre", variable).
Con eso basta para personalizar un poco mas la plantilla.
Suerte, gracias por comentar.
Excelente aporte podrías explicar mas detallado el replace
EliminarmsjHTML = msjHTML.replace("$$nombre", variable).
Hola Amigo,
EliminarExplico un poco más, la clase String tiene un método que se llama "replace", este método tiene varias implementaciones, como en este tutorial la variable "msjHTML" es de la clase StringBuffer tenemos que utilizar el método "toString" de esa clase para convertirlo a String y así poder aplicar el replace como mencione anteriormente.
Supongamos que tenemos una lista de personas a las que vamos a enviarle el correo, poseemos los nombres de la personas y queremos agregar el nombre de la persona en el correo que vamos a enviarle, hacemos algo como esto:
// El nombre de la persona
String nombrePersona = "DatoJava";
// Nueva variable para obtener el msjHTML en String
String mensajeEnviar = msjHTML.toString();
// Aplicar el replace a la variable, suponiendo que en la plantilla
// esta esa secuencia de caracteres “$$nombre”
mensajeEnviar = mensajeEnviar.replace("$$nombre", nombrePersona);
// ...
// ...
// Enviamos el correo
mimeBodyPart.setContent(mensajeEnviar, "text/html");
Así aplicamos el replace y hacemos que nuestra plantilla sea más dinámica, cualquier duda puedes preguntar, espero haberme explicado bien.
Suerte!!
Gracias por responder esto seria donde almacenas el contenido de la plantilla o donde creas la parte del mensaje. ademas la cadena $$nombre tiene que estar definida en la plantilla o como !!! jaja gracias
Eliminargracias por contestar. Mira tengo un JFileChooser en el cual busco las rutas de las imágenes para agregarlas al HTML pero como aplicara remplace con este ejemplo.
EliminarLA ruta File directorio = new File(urlImagenes); yo la defino desde código porque no cambia
pero la parte de src="cid:gplus.png" si por que esta parte "cid:gplus.png" puede ser variable para remplazarla con la ruta que me retorno el filechooser como lo podría aplicar gracias saludos
Cuando almacenamos el contenido de la plantilla en la variable StringBuffer comienzas aplicar lo que te explique anteriormente, y claro esa cadena de caracteres $$nombre tiene que estar definida en la plantilla para que justo antes de enviar el mensaje puedas hacer el replace por la variable que quieras agregar al mensaje final.
EliminarSuerte!!
Hola¡ Excelente tutorial me funciona de mil maravillas. Pero me gustaría saber como puedo mandar el correo electrónico a cierta hora o cierto día?.
ResponderEliminarUn abrazo
Hola Sergio, hay varias maneras de hacer lo que dices, te recomiendo que utilices el framework Quartz, es excelente para ese tipo de tareas.
EliminarGracias por comentar, Suerte
Como hago para hacer esto mismo, pero sin que el las imágenes que envío en el HTML no se vean adjuntas en en correo. Es que en mi HTML tengo 6 imágenes, y llegan adjuntas en el correo, lo cual se ve algo desagradable. Hay modo de que esto no suceda?
ResponderEliminarHola amigo, gracias por compatir este material, pero tengo errores a la hora de ejecutarlo:
ResponderEliminarCorreo enviado
java.lang.NullPointerException
at java.io.Reader.(Reader.java:78)
at java.io.InputStreamReader.(InputStreamReader.java:72)
at correos.CorreoHTML.mandarCorreo(CorreoHTML.java:63)
at correos.CorreoHTML.main(CorreoHTML.java:119)
Alguna idea para solucionarlo?
Estimado(a),
EliminarEse error parece ser con la plantilla, quiere decir que la plantilla no esta en la ruta indicada y por lo tanto explota con un NullPointerException, puede que sea eso, no estoy seguro porque no escribiste todo el error completo.
Revisa eso, sería mejor que mandes todo el StackTrace del error.
Suerte!!
Hola, como siempre, excelente explicación pero tengo el siguiente error:
ResponderEliminarCorreo enviado
javax.mail.MessagingException: IOException while sending message;
nested exception is:
java.io.FileNotFoundException: url del archivo que vas adjuntar (El sistema no puede encontrar el archivo especificado)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1290)
at correosDJ.DJCorreoTexto.enviarCorreo(DJCorreoTexto.java:74)
at correosDJ.DJCorreoTexto.main(DJCorreoTexto.java:85)
Caused by: java.io.FileNotFoundException: url del archivo que vas adjuntar (El sistema no puede encontrar el archivo especificado)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.(FileInputStream.java:138)
at javax.activation.FileDataSource.getInputStream(FileDataSource.java:97)
at javax.activation.DataHandler.writeTo(DataHandler.java:305)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1645)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:961)
at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:553)
at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:81)
at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:889)
at javax.activation.DataHandler.writeTo(DataHandler.java:317)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1645)
at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1850)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1241)
... 2 more
BUILD SUCCESSFUL (total time: 16 seconds)
PD: El IDE que utilizo es NetBeans 8.0.1 y ya habilite mi cuenta de correo para aplicaciones no seguras
Estimado Esteban, viendo el error si te fijas en esta línea:
EliminarCaused by: java.io.FileNotFoundException: url del archivo que vas adjuntar (El sistema no puede encontrar el archivo especificado)
Java te está diciendo que el error es porque no encuentra el archivo que estas adjuntando, me imagino que debe ser que la ruta de la carpeta donde están las imágenes es incorrecta, y por eso lanza la "FileNotFoundException", verifica que la ruta de la carpeta donde tú tienes las imágenes este correcta y vuelve a intentarlo.
Saludos y Suerte!!
Como podría hacerle una interfaz ????
ResponderEliminarUna interfaz donde en ella se escriba el mensaje y el destinatario.. etc ???
ResponderEliminarHOLA Ivan, no sé si ya eres desarrollador o no tienes ni idea de cómo programar, en todo caso voy asumir que sabes programar, te recomiendo que veas este tutorial:
Eliminarhttp://datojava.blogspot.com/2015/06/tutorialAplicacionJavaSwingEjemplo.html
y apliques los conocimientos adquiridos en esta entrada y lo adaptes a tus necesidades.
Suerte!!
Hola buen día, implementé el ejemplo del envio html pero tengo dudas donde explicas crear la plantilla (Primero vamos a crear un archivo en nuestro IDE, new> other> File, que llevará por nombre PlantillaDJ). Te refieres a que debemos cerar un archivo html con ese contenido?..
ResponderEliminarEstimado Anonimo,
EliminarMe refiero a que vamos a crear un file (new> other> File), eso es una plantilla en la que vamos a tener el código de HTML que se va mostrar en el correo, si te fijas después en el código lo que hacemos es leer la plantilla e ir almacenando su contenido en un StringBuffer. No es crear un archivo HTML, es crear un simple FILE en el proyecto para que sea un poco más fácil de entender y de esa manera mantener las cosas separadas! Ahora si tu quieres podrías hacerlo directamente en el código, cosa que no recomiendo pero igual funcionaría...
Suerte!!
perezus
Eliminarcomo puedo incluir varios destinatarios en una variable con datos extraidos de una bdd?..
ResponderEliminarEstimado Anonimo,
EliminarEsta fácil, haces tu query para obtener los destinatarios, recorres el ResultSet con un bucle (for, while...), vas agregando los destinatarios a una lista (array, ArrayList...), una vez que ya tienes todos tus destinatarios haces lo siguiente:
ArrayList destinatarios = new ArrayList();
InternetAddress[] internetAddresses = new InternetAddress[destinatarios.size()];
for (int i = 0; i < destinatarios.size(); i++) {
internetAddresses[i] = new InternetAddress(destinatarios.get(i));
}
Suerte, espero te sirva
Buen blog, explicas muy bien el código y sobretodo veo que respondes la gran mayoría de preguntas. Gracias por tu gran trabajo amigo.
EliminarGracias Julio Mejía, que bueno que la entrada fue útil para ti, mucha suerte!
EliminarBuenas Tardes,
ResponderEliminarMuchas Gracias por el ejemplo me ha servido demasiado, ahora tengo una consulta, si deseo poner esa imagen como fondo en un div, como la llamo?
he puesto
< class="banner" background="cid:1.jpg">
< class="banner" style="background: url(\"cid:1.jpg\");">
y ninguna sirve
Agradezco la colaboración.
Excelente ayuda, muy buen trabajo, fácil sin complicaciones
ResponderEliminarMuchas Gracias, Bertha, se agradece el comentario!
EliminarSuerte!!
Buenas
ResponderEliminarGran post he de decir, me ha ayudado mucho ya que la información suele estar muy dispersa.
Tengo un pequeño problema y es que he probado de varias formas y ninguna me funciona para adjuntar archivos, no se si es problema mio o directamente me falta algo. Te dejo un ejemplo:
mimeBPArchivos.setDataHandler(new DataHandler(new FileDataSource("C:/Users/Desktop/ArchivosAdj/" + nomArchivo + ".png")));
o también
mimeBPArchivos.attachFile(new File("C:/Users/jjale/Desktop/ArchivosAdj/" + nomArchivo + ".png"));
Gracias por la ayuda
Hola, primero te recomiendo que te bajes todo el proyecto y hagas las pruebas necesarias, en el punto 4 explico cómo adjuntar una imagen o archivo, si no te funciona puede que esté explotando por algún lugar, sería bueno que te fijes en la consola y en ese caso mándame el log del error para ayudarte!
EliminarSaludos!
hola buenas tardes el código como se implementaría en un formulario, soy principiante
ResponderEliminarExcelente Blog... Me ayudo bastante... pero tengo una duda... deseo mandar un correo por cada usuario de mi base de datos... he pensado en un for al principio de todo, pero no se si exista una mejor manera, agradecería una idea (Puedo mandar personalizada la plantilla y logro hacer que se adjunten varios usuarios a uno solo correo... ahora deseo mandar un correo por cada usuario en individual).
ResponderEliminarHola Erick, si puedes mandar el correo a varias personas, también puedes hacerlo con plantillas personalizadas, por ejemplo, el for va iterar sobre la lista de correos, no al principio, al momento de enviar el email, aparte de eso, dependiendo del cliente podrías elegir (if-else..) diferentes plantillas/imágenes. Esta fácil, solo analízalo bien y verifica que funcione de la manera que quieres.
EliminarSuerte!
Muchas gracias por el tutorial. Felicitaciones por gran trabajo.
ResponderEliminarSaludos
Muchas Gracias Estimado, Suerte!
EliminarB R A V O !
ResponderEliminarGracias mi amigo. Suerte
Eliminar