Como enviar emails con Spring Boot

En este post, vamos a entender como enviar un email con Spring Boot.

La dependencia necesaria

Para enviar un email, se necesita esta dependencia.

build.gradle

    implementation 'org.springframework.boot:spring-boot-starter-mail'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

La configuración para enviar emails en Spring

Nosotros necesitamos definir JavaMailSender si queremos establecer las propiedades programáticamente.

Tú puedes usar JavaMailSenderImpl que implementa JavaMailSender para definir la configuración del servidor de email. Por ejemplo para Gmail, la configuración podría verse así:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;

import java.util.Properties;

@Configuration
public class MailSenderConfig {

    @Bean("javaMailSender")
    public JavaMailSender javaMailSender() {
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setHost("smtp.gmail.com");
        sender.setPort(587);
        sender.setUsername("user@gmail.com");
        sender.setPassword("password");

        Properties props = sender.getJavaMailProperties();
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.debug", "true");

        return sender;
    }
}

Observa. Para usar los servicios de Google SMTP tu necesitas crear una única “app password” para el servicio.

https://support.google.com/accounts/answer/185833?hl=en

Configuración usando properties para enviar e-mails en Spring

Antes, nosotros definimos la configuración cargando las propiedades en la JavaMailSenderImpl class.

Sin embargo, podemos saltar esto y definir las propiedades directamente en el application.properties file.

Si tú defines las propiedades, sin crear el ‘bean config’, Spring creará la clase JavaMailSenderImpl por ti con dichas propiedades.

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=user@gmail.com
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

Enviando un email con Spring

Puedes enviar un email simple, solo texto.

La class SimpleMailMessage provee un modelo simple para enviar mensajes de solo-texto.

SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setSubject(subject);
message.setText(text);
mailSender.send(message);

También, puedes enviar email con archivos adjuntos.

Para enviar e-mails con archivos adjuntos necesitas dos clases.

MimeMessage te permite el agregado de archivos adjuntos y MimeMessageHelper te ayuda a crear el mail.

MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
helper.addAttachment(attachName, inputStream);
mailSender.send(message);

Si tu quieres, pueden agregar HTML tags.

Por ejemplo, aquí nosotros agregamos un texto con un tag HTML de negrita.

MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText("<b>bold message</b>", true);  // text with HTML tags
helper.addAttachment(attachName, inputStream);
mailSender.send(message);

MIME message significa “Multipurpose Internet Mail Extensions”. Con MIME messages tu puedes enviar HTML, y agregar archivos (text, audio, images, etc).

Resumen de las clases que usamos

  • JavaMailSender: interface para configurar Spring Email
  • JavaMailSenderImpl: implementación de JavaMailSender
  • SimpleMailMessage: modelo para completar los atributos necesarios para enviar un email.
  • MimeMessage: una class que representa un mensaje de tipo MIME.
  • MimeMessageHelper: una clase de ayuda para crear mensajes MIME.

Ejemplo de un servicio usando JavaMailSender

Aquí nosotros creamos un servicio y usamos JavaMailSender que definimos previamente.

@Service
public class EmailService {

    private JavaMailSender mailSender;

    public EmailService(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }

    public void send(String from, String to, String subject, String text) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);
        message.setSubject(subject);
        message.setText(text);
        mailSender.send(message);
    }

    public void sendWithAttach(String from, String to, String subject,
                               String text, String attachName,
                               InputStreamSource inputStream) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        helper.setFrom(from);
        helper.setTo(to);
        helper.setSubject(subject);
        helper.setText(text, true);
        helper.addAttachment(attachName, inputStream);
        mailSender.send(message);
    }

}

Testeando nuestro Servicio de Email

Con el objetivo de chequear la funcionalidad de nuestro servicio, vamos a utilizar https://greenmail-mail-test.github.io/greenmail/

GreenMail es un open-source framework que provee test servers para validar nuestro email service construido.

build.gradle

    implementation 'org.springframework.boot:spring-boot-starter-mail'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'com.icegreen:greenmail-junit5:1.6.9'

Vamos a definir las propiedades de test para GreenMail.

## test properties for test email Greenmail
spring.mail.host=localhost
spring.mail.port=3025
spring.mail.username=user@gmail.com
spring.mail.password=password

Test usando GreenMail para validar EmailService

import com.icegreen.greenmail.configuration.GreenMailConfiguration;
import com.icegreen.greenmail.junit5.GreenMailExtension;
import com.icegreen.greenmail.util.ServerSetupTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;

import javax.mail.internet.MimeMessage;
import java.io.File;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
class EmailServiceTest {

    @RegisterExtension
    static GreenMailExtension greenMail = new GreenMailExtension(ServerSetupTest.SMTP)
            .withConfiguration(GreenMailConfiguration
                    .aConfig().withUser("user@gmail.com", "password"));

    @Autowired
    private EmailService emailService;

    @Test
    void send() throws Exception {
        emailService.send("gus@gmail.com", "jhon@gmail.com",
                "Hello", "How are you?");

        MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
        MimeMessage receivedMessage = receivedMessages[0];

        assertEquals("gus@gmail.com", receivedMessage.getFrom()[0].toString());
        assertEquals("jhon@gmail.com", receivedMessage.getAllRecipients()[0].toString());
        assertEquals("Hello", receivedMessage.getSubject().trim());
        assertEquals("How are you?", receivedMessage.getContent().toString().trim());
        // others test assertions with receivedMessage..
    }

    @Test
    void sendWithAttach() throws Exception {
        ClassPathResource classPathResource = new ClassPathResource("info.txt");
        File file = classPathResource.getFile();
        FileSystemResource fileResource = new FileSystemResource(file);
        emailService.sendWithAttach("gus@gmail.com", "jhon@gmail.com",
                "Hello", "How are you?", "info.txt", fileResource);

        MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
        MimeMessage receivedMessage = receivedMessages[0];

        assertEquals("gus@gmail.com", receivedMessage.getFrom()[0].toString());
        assertEquals("jhon@gmail.com", receivedMessage.getAllRecipients()[0].toString());
        assertEquals("Hello", receivedMessage.getSubject().trim());
        // others test assertions with receivedMessage..
    }
}

Conclusión:

En este post nosotros aprendimos como configurar Java Email Sender con Spring Boot usando ‘beans’ configuration y property files. También entendimos como crear un JUnit test con GreenMail.

El código:

El código lo encuentras en GitHub.
https://github.com/gustavopeiretti/spring-boot-examples/tree/master/spring-boot-email

Hi! If you find my posts helpful, please support me by inviting me for a coffee :)

Ver también