Envío de Correos Electrónicos con Spring Boot y SMTP

Spring Boot simplifica la integración del envío de correos electrónicos en aplicaciones Java a través de su módulo spring-boot-starter-mail. Esta guía detalla cómo configurar y utilizar esta funcionalidad para enviar mensajes de correo electrónico, tanto en texto plano como con formato HTML, utilizando un servidor SMTP genérico como ejemplo, con énfasis en la configuración específica para servicios como QQ Mail.

1. Incorporación de Dependencias

El primer paso es añadir la dependencia de Spring Boot Mail a su archivo de configuración de proyecto, pom.xml, si utiliza Maven. Esta dependencia provee la integración necesaria con la API de JavaMail.

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

2. Configuración del Servidor SMTP

Para permitir que su aplicación envíe correos electrónicos, debe configurar los parámetros del servidor SMTP en su archivo application.properties o application.yml. Es fundamental que el servicio de correo que utilice, por ejemplo, QQ Mail, tenga habilitado el protocolo POP3/SMTP. En el caso de QQ Mail, esto suele implicar visitar la configuración de su cuenta para generar una "clave de autorización" (o "código de cliente") específica para aplicaciones de terceros, la cual se utilizará en lugar de su contraseña de cuenta principal.

A continuación, se muestra un ejemplo de configuración en application.properties:

# Configuración para el servicio de correo electrónico
spring.mail.host=smtp.qq.com
spring.mail.port=587 # Puerto común para TLS; use 465 para SSL
spring.mail.username=su.correo@qq.com # La dirección de correo del remitente
spring.mail.password=su_clave_autorizacion_smtp # La clave generada para aplicaciones
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.default-encoding=UTF-8

  • spring.mail.host: La dirección del servidor SMTP utilizado para el envío de correos.
  • spring.mail.port: El puerto del servidor SMTP. Los puertos comunes son 587 (para TLS) o 465 (para SSL).
  • spring.mail.username: La dirección de correo electrónico que se identificará como el remitente.
  • spring.mail.password: La clave de autorización o contraseña de la aplicación generada por el proveedor de correo, no la contraseña de su cuenta principal.
  • spring.mail.properties.mail.smtp.auth: Indica si la autentiacción SMTP es obligatoria.
  • spring.mail.properties.mail.smtp.starttls.enable y spring.mail.properties.mail.smtp.starttls.required: Configuran la conexión para usar la seguridad TLS.
  • spring.mail.default-encoding: Establece la codificación predeterminada para los mensajes de correo.

3. Creación del Servicio de Envío de Correo

Una vez configurado el entorno, podemos crear un servicio que encapsule la lógica de envío de correos. Spring Boot inyecta automáticamente una instancia de JavaMailSender, la interfaz principle para interactuar con el sistema de correo.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

@Service
public class ServicioEnvioCorreo {

   private final JavaMailSender gestorCorreo;

   @Autowired
   public ServicioEnvioCorreo(JavaMailSender gestorCorreo) {
       this.gestorCorreo = gestorCorreo;
   }

   /**
    * Envía un correo electrónico en formato de texto plano.
    * @param direccionReceptor La dirección de correo electrónico a la que se enviará el mensaje.
    * @param asuntoMensaje El título o asunto del correo.
    * @param contenidoMensaje El cuerpo del correo en texto plano.
    */
   public void enviarTextoSimple(String direccionReceptor, String asuntoMensaje, String contenidoMensaje) {
       SimpleMailMessage mensajeSimple = new SimpleMailMessage();
       mensajeSimple.setFrom("su.correo@qq.com"); // Debe coincidir con spring.mail.username
       mensajeSimple.setTo(direccionReceptor);
       mensajeSimple.setSubject(asuntoMensaje);
       mensajeSimple.setText(contenidoMensaje);
       gestorCorreo.send(mensajeSimple);
       System.out.println("Correo de texto simple enviado a: " + direccionReceptor);
   }

   /**
    * Envía un correo electrónico con contenido HTML.
    * @param direccionReceptor La dirección de correo electrónico del destinatario.
    * @param asuntoMensaje El asunto del correo.
    * @param contenidoHtml El cuerpo del mensaje en formato HTML.
    */
   public void enviarHtml(String direccionReceptor, String asuntoMensaje, String contenidoHtml) {
       try {
           MimeMessage mensajeMime = gestorCorreo.createMimeMessage();
           MimeMessageHelper ayudanteMime = new MimeMessageHelper(mensajeMime, true, "UTF-8");

           ayudanteMime.setFrom("su.correo@qq.com"); // Debe coincidir con spring.mail.username
           ayudanteMime.setTo(direccionReceptor);
           ayudanteMime.setSubject(asuntoMensaje);
           ayudanteMime.setText(contenidoHtml, true); // El segundo 'true' indica que el contenido es HTML

           gestorCorreo.send(mensajeMime);
           System.out.println("Correo HTML enviado a: " + direccionReceptor);
       } catch (MessagingException e) {
           System.err.println("Error al enviar correo HTML a " + direccionReceptor + ": " + e.getMessage());
           // Considerar lanzar una excepción personalizada o usar un logger
       }
   }
}

3.1. Ejemplo de uso del servicio desde un componente Spring

Para invocar los métodos del servicio de correo, simplemente inyecte ServicioEnvioCorreo en cualquier controlador, componente o servicio de Spring:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ControladorPruebasCorreo {

   private final ServicioEnvioCorreo servicioCorreo;

   @Autowired
   public ControladorPruebasCorreo(ServicioEnvioCorreo servicioCorreo) {
       this.servicioCorreo = servicioCorreo;
   }

   @GetMapping("/prueba-simple")
   public String dispararEnvioSimple() {
       String receptor = "otro.correo@ejemplo.com"; // Reemplazar con una dirección de correo real
       String tema = "Notificación de Prueba de Spring Boot";
       String cuerpo = "Hola,\n\nEste es un mensaje de correo electrónico de prueba enviado con Spring Boot.\nSaludos.";
       servicioCorreo.enviarTextoSimple(receptor, tema, cuerpo);
       return "Solicitud de envío de correo simple procesada.";
   }

   @GetMapping("/prueba-html")
   public String dispararEnvioHtml() {
       String receptor = "otro.correo@ejemplo.com"; // Reemplazar con una dirección de correo real
       String tema = "¡Oferta Especial HTML!";
       
       StringBuilder constructorContenidoHtml = new StringBuilder();
       constructorContenidoHtml.append("<html><body>");
       constructorContenidoHtml.append("<h2 style='color: #007bff;'>¡Saludos desde nuestra aplicación!</h2>");
       constructorContenidoHtml.append("<p>Estamos encantados de presentarte nuestra nueva <strong>oferta exclusiva</strong>.</p>");
       constructorContenidoHtml.append("<p>Haz <a href='https://www.tuweb.com/ofertas' style='color: #28a745; text-decoration: none; font-weight: bold;'>clic aquí para descubrir más</a>.</p>");
       constructorContenidoHtml.append("<img src='https://via.placeholder.com/150' alt='Banner de Oferta' style='width:100%; max-width:300px;'>");
       constructorContenidoHtml.append("<p><small>Este es un correo automático. Por favor, no responda a este mensaje.</small></p>");
       constructorContenidoHtml.append("</body></html>");

       servicioCorreo.enviarHtml(receptor, tema, constructorContenidoHtml.toString());
       return "Solicitud de envío de correo HTML procesada.";
   }
}

Etiquetas: SpringBoot JavaMailSender SMTP Email MailService

Publicado el 7-11 12:58