How to send emails with Spring Boot

In this post, we will understand how to send an email with Spring Boot.

The dependency necessary

In order to send an email, you need this dependency

build.gradle

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

The configuration for sending emails in Spring

We need to define the JavaMailSender if we want to set the properties programmatically.

You can use JavaMailSenderImpl which implements JavaMailSender to define the mail server configuration. For example, for Gmail, the configuration could look like this:

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;
    }
}

Note. To use Google SMTP services you need to create a unique “app password” for the service.

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

Configuration using properties for sending e-mails in Spring

In the previous section, we defined the configuration by loading the properties in JavaMailSenderImpl class.

However, we can skip this and define the properties directly in the http://application.properties file.

If you only set the properties, without creating the ‘bean config’, Spring will create the JavaMailSenderImpl for you.

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

Sending an email with Spring

You can send a simple email, only text.

The SimpleMailMessage class provides a simple model for sending text-only messages.

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

Also, you can send an email with attached files.

To send e-mails with attachments you need two classes.

MimeMessage allows the addition of attachments and MimeMessageHelper helps us create the 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);

If you want, you can add HTML tags.

For example, here we add a text with a bold HTML tag.

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 means “Multipurpose Internet Mail Extensions”. With MIME messages you can send HTML texts, and attach files (text, audio, images, etc)

Summary of classes involved

  • JavaMailSender: interface to configure Spring Email
  • JavaMailSenderImpl: implementation of JavaMailSender
  • SimpleMailMessage: model to complete attributes necessaries to send an email.
  • MimeMessage: a class that represents a MIME message.
  • MimeMessageHelper: a helper class to create a MIME message.

Example of service using JavaMailSender

Here we create a service and use JavaMailSender that we define in our previous configuration.

@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);
    }

}

Testing our Email Service

In order to check the functionality of our service we are going to use https://greenmail-mail-test.github.io/greenmail/

GreenMail is an open-source framework that provides servers for testing our mail services.

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'

We will define the properties to test with 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

Email Service Test using GreenMail to validate 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..
    }
}

Conclusion:

In this post we learn how to configure the Java Email Sender with Spring Boot using ‘beans’ configuration and property files. We also understood how to create a JUnit test with GreenMail.

The code :

As always you can see this code in GitHub.
https://github.com/gustavopeiretti/spring-boot-examples/tree/master/spring-boot-email

If you wish to send me any corrections or suggestions, please contact me.
Thanks for your feedback :)

See also