Hoy vamos a ver un ejemplo de JavaMail para enviar correos electrónicos en programas Java. El envío de correos electrónicos es una de las tareas comunes en las aplicaciones de la vida real y por eso Java proporciona una sólida API de JavaMail que podemos usar para enviar correos electrónicos utilizando un servidor SMTP. La API de JavaMail admite tanto la autenticación TLS como SSL para enviar correos electrónicos.
Ejemplo de JavaMail
Hoy aprenderemos cómo usar la API de JavaMail para enviar correos electrónicos utilizando un servidor SMTP sin autenticación, con autenticación TLS y SSL, y cómo enviar archivos adjuntos y adjuntar y usar imágenes en el cuerpo del correo electrónico. Para la autenticación TLS y SSL, estoy utilizando el servidor SMTP de GMail porque admite ambos. También puedes optar por utilizar un servidor de correo Java según las necesidades de tu proyecto. La API de JavaMail no es parte del JDK estándar, así que tendrás que descargarla desde su sitio web oficial, es decir, Página de inicio de JavaMail. Descarga la última versión de la implementación de referencia de JavaMail e inclúyela en la ruta de compilación de tu proyecto. El nombre del archivo jar será javax.mail.jar. Si estás utilizando un proyecto basado en Maven, simplemente agrega la siguiente dependencia en tu proyecto.
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.5</version>
</dependency>
El programa Java para enviar correos electrónicos contiene los siguientes pasos:
- Creando el objeto
javax.mail.Session
- Creando el objeto
javax.mail.internet.MimeMessage
, debemos establecer diferentes propiedades en este objeto, como la dirección de correo electrónico del destinatario, el asunto del correo electrónico, el correo electrónico de respuesta, el cuerpo del correo electrónico, adjuntos, etc. - Utilizando
javax.mail.Transport
para enviar el mensaje de correo electrónico.
La lógica para crear la sesión difiere según el tipo de servidor SMTP, por ejemplo, si el servidor SMTP no requiere autenticación, podemos crear el objeto Session con algunas propiedades simples, mientras que si requiere autenticación TLS o SSL, entonces la lógica para crear será diferente. Por lo tanto, crearé una clase de utilidad con algunos métodos de utilidad para enviar correos electrónicos y luego usaré este método de utilidad con diferentes servidores SMTP.
Ejemplo de Programa JavaMail
Nuestra clase EmailUtil que tiene un único método para enviar correos electrónicos se ve así a continuación, requiere javax.mail.Session y algunos otros campos requeridos como argumentos. Para mantenerlo simple, algunos de los argumentos están codificados directamente, pero puedes extender este método para pasarlos o leerlos desde algún archivo de configuración.
package com.journaldev.mail;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
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;
public class EmailUtil {
/**
* Utility method to send simple HTML email
* @param session
* @param toEmail
* @param subject
* @param body
*/
public static void sendEmail(Session session, String toEmail, String subject, String body){
try
{
MimeMessage msg = new MimeMessage(session);
// Establecer encabezados del mensaje
msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
msg.addHeader("format", "flowed");
msg.addHeader("Content-Transfer-Encoding", "8bit");
msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));
msg.setReplyTo(InternetAddress.parse("[email protected]", false));
msg.setSubject(subject, "UTF-8");
msg.setText(body, "UTF-8");
msg.setSentDate(new Date());
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
System.out.println("Message is ready");
Transport.send(msg);
System.out.println("EMail Sent Successfully!!");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Observa que estoy configurando algunas propiedades de encabezado en el MimeMessage, estas son utilizadas por los clientes de correo electrónico para renderizar y mostrar adecuadamente el mensaje de correo electrónico. El resto del programa es simple y se entiende por sí mismo. Ahora creemos nuestro programa para enviar correo electrónico sin autenticación.
Enviar correo electrónico en Java usando SMTP sin autenticación
package com.journaldev.mail;
import java.util.Properties;
import javax.mail.Session;
public class SimpleEmail {
public static void main(String[] args) {
System.out.println("SimpleEmail Start");
String smtpHostServer = "smtp.example.com";
String emailID = "[email protected]";
Properties props = System.getProperties();
props.put("mail.smtp.host", smtpHostServer);
Session session = Session.getInstance(props, null);
EmailUtil.sendEmail(session, emailID,"SimpleEmail Testing Subject", "SimpleEmail Testing Body");
}
}
Observe que estoy utilizando Session.getInstance() para obtener el objeto de sesión pasando el objeto Properties. Necesitamos establecer la propiedad mail.smtp.host con el host del servidor SMTP. Si el servidor SMTP no está en el puerto predeterminado (25), entonces también deberá establecer la propiedad mail.smtp.port. Simplemente ejecute este programa con su servidor SMTP sin autenticación y configurando la dirección de correo electrónico del destinatario como su propia dirección de correo electrónico y recibirá el correo electrónico en poco tiempo. El programa es fácil de entender y funciona bien, pero en la vida real la mayoría de los servidores SMTP utilizan algún tipo de autenticación como autenticación TLS o SSL. Así que ahora veremos cómo crear un objeto de sesión para estos protocolos de autenticación.
Enviar correo electrónico en Java SMTP con autenticación TLS
package com.journaldev.mail;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
public class TLSEmail {
/**
Outgoing Mail (SMTP) Server
requires TLS or SSL: smtp.gmail.com (use authentication)
Use Authentication: Yes
Port for TLS/STARTTLS: 587
*/
public static void main(String[] args) {
final String fromEmail = "[email protected]"; //requires valid gmail id
final String password = "mypassword"; // correct password for gmail id
final String toEmail = "[email protected]"; // can be any email id
System.out.println("TLSEmail Start");
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host
props.put("mail.smtp.port", "587"); //TLS Port
props.put("mail.smtp.auth", "true"); //enable authentication
props.put("mail.smtp.starttls.enable", "true"); //enable STARTTLS
//crear objeto Authenticator para pasar como argumento en Session.getInstance
Authenticator auth = new Authenticator() {
//sobrescribir el método getPasswordAuthentication
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(fromEmail, password);
}
};
Session session = Session.getInstance(props, auth);
EmailUtil.sendEmail(session, toEmail,"TLSEmail Testing Subject", "TLSEmail Testing Body");
}
}
Dado que estoy utilizando el servidor SMTP de Gmail que está accesible para todos, puedes establecer las variables correctas en el programa anterior y ejecutarlo por ti mismo. ¡Créeme, funciona! 🙂
Ejemplo de Java SMTP con autenticación SSL
package com.journaldev.mail;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
public class SSLEmail {
/**
Outgoing Mail (SMTP) Server
requires TLS or SSL: smtp.gmail.com (use authentication)
Use Authentication: Yes
Port for SSL: 465
*/
public static void main(String[] args) {
final String fromEmail = "[email protected]"; //requires valid gmail id
final String password = "mypassword"; // correct password for gmail id
final String toEmail = "[email protected]"; // can be any email id
System.out.println("SSLEmail Start");
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host
props.put("mail.smtp.socketFactory.port", "465"); //SSL Port
props.put("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory"); //SSL Factory Class
props.put("mail.smtp.auth", "true"); //Enabling SMTP Authentication
props.put("mail.smtp.port", "465"); //SMTP Port
Authenticator auth = new Authenticator() {
//anular el método getPasswordAuthentication
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(fromEmail, password);
}
};
Session session = Session.getDefaultInstance(props, auth);
System.out.println("Session created");
EmailUtil.sendEmail(session, toEmail,"SSLEmail Testing Subject", "SSLEmail Testing Body");
EmailUtil.sendAttachmentEmail(session, toEmail,"SSLEmail Testing Subject with Attachment", "SSLEmail Testing Body with Attachment");
EmailUtil.sendImageEmail(session, toEmail,"SSLEmail Testing Subject with Image", "SSLEmail Testing Body with Image");
}
}
El programa es casi igual que la autenticación TLS, solo algunas propiedades son diferentes. Como puedes ver, estoy llamando a algunos otros métodos de la clase EmailUtil para enviar adjuntos e imágenes por correo electrónico, pero aún no los he definido. De hecho, los mantuve para mostrarlos más tarde y mantenerlo simple al inicio del tutorial.
Ejemplo de JavaMail – enviar correo en Java con adjunto
Para enviar un archivo como adjunto, necesitamos crear un objeto de javax.mail.internet.MimeBodyPart
y javax.mail.internet.MimeMultipart
. Primero agregue la parte del cuerpo para el mensaje de texto en el correo electrónico y luego use FileDataSource para adjuntar el archivo en la segunda parte del cuerpo multiparte. El método se ve así.
/**
* Utility method to send email with attachment
* @param session
* @param toEmail
* @param subject
* @param body
*/
public static void sendAttachmentEmail(Session session, String toEmail, String subject, String body){
try{
MimeMessage msg = new MimeMessage(session);
msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
msg.addHeader("format", "flowed");
msg.addHeader("Content-Transfer-Encoding", "8bit");
msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));
msg.setReplyTo(InternetAddress.parse("[email protected]", false));
msg.setSubject(subject, "UTF-8");
msg.setSentDate(new Date());
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
// Crear la parte del cuerpo del mensaje
BodyPart messageBodyPart = new MimeBodyPart();
// Llenar el mensaje
messageBodyPart.setText(body);
// Crear un mensaje multiparte para el adjunto
Multipart multipart = new MimeMultipart();
// Establecer parte del mensaje de texto
multipart.addBodyPart(messageBodyPart);
// La segunda parte es el adjunto
messageBodyPart = new MimeBodyPart();
String filename = "abc.txt";
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
// Enviar las partes completas del mensaje
msg.setContent(multipart);
// Enviar mensaje
Transport.send(msg);
System.out.println("EMail Sent Successfully with attachment!!");
}catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
El programa puede parecer complejo a primera vista, pero es simple. Simplemente crea una parte del cuerpo para el mensaje de texto y otra parte del cuerpo para el archivo adjunto, y luego agrégalas al multipart. También puedes extender este método para adjuntar varios archivos.
Ejemplo de JavaMail: enviar correo en Java con imagen
Dado que podemos crear un cuerpo de mensaje HTML, si el archivo de imagen está ubicado en alguna ubicación del servidor, podemos usar el elemento img para mostrarlo en el mensaje. Pero a veces queremos adjuntar la imagen en el correo electrónico y luego usarla en el cuerpo del correo electrónico en sí. Seguramente has visto muchos correos electrónicos que tienen archivos de imagen adjuntos y también se usan en el mensaje de correo electrónico. El truco es adjuntar el archivo de imagen como cualquier otro archivo adjunto y luego establecer el encabezado Content-ID para el archivo de imagen y luego usar el mismo ID de contenido en el cuerpo del mensaje de correo electrónico con <img src='cid:image_id'>
.
/**
* Utility method to send image in email body
* @param session
* @param toEmail
* @param subject
* @param body
*/
public static void sendImageEmail(Session session, String toEmail, String subject, String body){
try{
MimeMessage msg = new MimeMessage(session);
msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
msg.addHeader("format", "flowed");
msg.addHeader("Content-Transfer-Encoding", "8bit");
msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));
msg.setReplyTo(InternetAddress.parse("[email protected]", false));
msg.setSubject(subject, "UTF-8");
msg.setSentDate(new Date());
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
// Crear la parte del cuerpo del mensaje
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(body);
// Crear un mensaje multipart para el archivo adjunto
Multipart multipart = new MimeMultipart();
// Establecer la parte del mensaje de texto
multipart.addBodyPart(messageBodyPart);
// La segunda parte es el archivo adjunto de imagen
messageBodyPart = new MimeBodyPart();
String filename = "image.png";
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
// El truco es agregar aquí el encabezado de identificación de contenido
messageBodyPart.setHeader("Content-ID", "image_id");
multipart.addBodyPart(messageBodyPart);
// Tercera parte para mostrar la imagen en el cuerpo del correo electrónico
messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent("Attached Image
" +
"
", "text/html");
multipart.addBodyPart(messageBodyPart);
// Establecer el mensaje multipart en el mensaje de correo electrónico
msg.setContent(multipart);
// Enviar mensaje
Transport.send(msg);
System.out.println("EMail Sent Successfully with image!!");
}catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
Consejos para solucionar problemas de la API JavaMail
-
java.net.UnknownHostException
ocurre cuando su sistema no puede resolver la dirección IP del servidor SMTP, puede estar incorrecta o no accesible desde su red. Por ejemplo, el servidor SMTP de GMail es smtp.gmail.com y si uso smtp.google.com, obtendré esta excepción. Si el nombre de host es correcto, intente hacer ping al servidor a través de la línea de comandos para asegurarse de que sea accesible desde su sistema.pankaj@Pankaj:~/CODE$ ping smtp.gmail.com PING gmail-smtp-msa.l.google.com (74.125.129.108): 56 datos bytes 64 bytes desde 74.125.129.108: icmp_seq=0 ttl=46 tiempo=38.308 ms 64 bytes desde 74.125.129.108: icmp_seq=1 ttl=46 tiempo=42.247 ms 64 bytes desde 74.125.129.108: icmp_seq=2 ttl=46 tiempo=38.164 ms 64 bytes desde 74.125.129.108: icmp_seq=3 ttl=46 tiempo=53.153 ms
-
Si tu programa está atascado en la llamada al método send() de Transport, verifica que el puerto SMTP sea correcto. Si es correcto, utiliza telnet para verificar que sea accesible desde tu máquina, obtendrás una salida como la siguiente.
pankaj@Pankaj:~/CODE$ telnet smtp.gmail.com 587 Trying 2607:f8b0:400e:c02::6d... Connected to gmail-smtp-msa.l.google.com. Escape character is '^]'. 220 mx.google.com ESMTP sx8sm78485186pab.5 - gsmtp HELO 250 mx.google.com at your service
Eso es todo para el ejemplo de JavaMail para enviar correos electrónicos en Java usando un servidor SMTP con diferentes protocolos de autenticación, adjuntos e imágenes. Espero que esto resuelva todas tus necesidades para enviar correos electrónicos en programas Java.
Source:
https://www.digitalocean.com/community/tutorials/javamail-example-send-mail-in-java-smtp