Sending emails with Spring


Within the framework of Spring Boot Tutorial Series in this article, we’ll take a look at a way to send emails using Spring.

Introduction

Sending emails is one of the basic functions that any application might need. This article will show you how to send emails using Spring. To send emails, you need SMTP server details. You can use SMTP for Gmail as an example (keep in mind that Gmail has certain restrictions on sending email). The JavaMailSender interface in the Spring Framework offers a simple abstraction for sending email, while Spring Boot does automatic configuration this interface and the starter module.

1. Maven Dependencies

To add the Spring Boot auto-configuration feature to the application, we need to add spring-boot-starter-mail to the pom.xml file. Below is a snippet of our file pom.xml:

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

2. Email configuration

After we have defined the dependencies, the next step is to add the mail configuration for auto configuration with Spring Boot:

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

The above configuration values ​​are for the Gmail SMTP server. Replace them with your own if necessary.

3. Email service

Next, we will create a simple email service class that will allow our application to send emails. In our example mail service, we will implement two methods:

  1. sending simple emails;

  2. Sending emails with attachments.

Our code will look like this:

@Service
public class DefaultEmailService implements EmailService {

 @Autowired
 public JavaMailSender emailSender;

 @Override
 public void sendSimpleEmail(String toAddress, String subject, String message) {

  SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
  simpleMailMessage.setTo(toAddress);
  simpleMailMessage.setSubject(subject);
  simpleMailMessage.setText(message);
  emailSender.send(simpleMailMessage);
 }

 @Override
 public void sendEmailWithAttachment(String toAddress, String subject, String message, String attachment) throws MessagingException, FileNotFoundException {

  MimeMessage mimeMessage = emailSender.createMimeMessage();
  MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
  messageHelper.setTo(toAddress);
  messageHelper.setSubject(subject);
  messageHelper.setText(message);
  FileSystemResource file = new FileSystemResource(ResourceUtils.getFile(attachment));
  messageHelper.addAttachment("Purchase Order", file);
  emailSender.send(mimeMessage);
 }
}

4. Test controller

Let’s create a simple REST controller to test how the code works. Our REST controller will have two methods. The controller itself will look like this:

package com.javadevjournal.controller;

import com.javadevjournal.email.service.EmailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.mail.MailException;
import org.springframework.web.bind.annotation.*;

import javax.mail.MessagingException;
import java.io.FileNotFoundException;

@RestController
@RequestMapping("/email")
public class EmailController {

    private static final Logger LOG = LoggerFactory.getLogger(EmailController.class);

    @Autowired
    EmailService emailService;

    @GetMapping(value = "/simple-email/{user-email}")
    public @ResponseBody ResponseEntity sendSimpleEmail(@PathVariable("user-email") String email) {

        try {
            emailService.sendSimpleEmail(email, "Welcome", "This is a welcome email for your!!");
        } catch (MailException mailException) {
            LOG.error("Error while sending out email..{}", mailException.getStackTrace());
            return new ResponseEntity<>("Unable to send email", HttpStatus.INTERNAL_SERVER_ERROR);
        }

        return new ResponseEntity<>("Please check your inbox", HttpStatus.OK);
    }

    @GetMapping(value = "/simple-order-email/{user-email}")
    public @ResponseBody ResponseEntity sendEmailAttachment(@PathVariable("user-email") String email) {

        try {
            emailService.sendEmailWithAttachment(email, "Order Confirmation", "Thanks for your recent order",
                    "classpath:purchase_order.pdf");
        } catch (MessagingException | FileNotFoundException mailException) {
            LOG.error("Error while sending out email..{}", mailException.getStackTrace());
            return new ResponseEntity<>("Unable to send email", HttpStatus.INTERNAL_SERVER_ERROR);
        }

        return new ResponseEntity<>("Please check your inbox for order confirmation", HttpStatus.OK);
    }

}

5. The main Spring Boot class

@SpringBootApplication
public class SendEmailUsingSpringApplication {

   public static void main(String[] args) {
      SpringApplication.run(SendEmailUsingSpringApplication.class, args);
   }

}

Run the application and follow the following links:

http://localhost:8080/email/order-email/umeshawasthi@www.javadevjournal.com
http://localhost:8080/email/simple-email/umeshawasthi@www.javadevjournal.com

6. Configuring Gmail SMTP Server

Before using the Gmail SMTP server, please read next article. Due to additional security measures in Gmail, your regular email password will not work.

Sending emails with Spring Boot and Thymeleaf

In the previous section, we looked at how to send emails using Spring. However, for a working application, you need a more advanced way. In this section, we’ll take a look at how to send emails using Spring Boot and Thymeleaf.

Thyleleaf is a templating engine. Thymeleaf will help us send emails in rich HTML format. Let’s say we want to send an email to a customer to verify their account.

7. EmailContext class

For more versatility, let’s create a class EmailContextcontaining all the basic information that we need for email. Our class will look like this:

public abstract class AbstractEmailContext {

    private String from;
    private String to;
    private String subject;
    private String email;
    private String attachment;
    private String fromDisplayName;
    private String emailLanguage;
    private String displayName;
    private String templateLocation;
    private Map <String, Object> context;
    //getter and seter methods
}

Let’s consider several fields of this class:

  • templateLocation – indicates the location of the HTML template. We will need this field to generate the final output.

  • context – contains all dynamic values ​​passed in the email. Thymeleaf will use this map to replace expressions with actual values ​​(like your name, etc.).

Next, we will configure our email service to process Thymeleaf HTML templates for filling emails.

8. EmailService implementation

package com.javadevjournal.core.email.service;

    import com.javadevjournal.core.email.context.AbstractEmailContext;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.mail.javamail.JavaMailSender;
    import org.springframework.mail.javamail.MimeMessageHelper;
    import org.springframework.stereotype.Service;
    import org.thymeleaf.context.Context;
    import org.thymeleaf.spring5.SpringTemplateEngine;
    
    import javax.mail.MessagingException;
    import javax.mail.internet.MimeMessage;
    import java.nio.charset.StandardCharsets;
    
    @Service
    public class DefaultEmailService implements EmailService {
    
        @Autowired
        private JavaMailSender emailSender;
    
        @Autowired
        private SpringTemplateEngine templateEngine;
    
        @Override
        public void sendMail(AbstractEmailContext email) throws MessagingException {
            MimeMessage message = emailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message,
                MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
                StandardCharsets.UTF_8.name());
            Context context = new Context();
            context.setVariables(email.getContext());
            String emailContent = templateEngine.process(email.getTemplateLocation(), context);
    
            mimeMessageHelper.setTo(email.getTo());
            mimeMessageHelper.setSubject(email.getSubject());
            mimeMessageHelper.setFrom(email.getFrom());
            mimeMessageHelper.setText(emailContent, true);
            emailSender.send(message);
        }
    }

There are several important points in the above code.

  1. We create and configure the map as a set of variables. Thymeleaf will use this context to replace placeholders or expressions with values ​​passed through it.

  2. SpringTemplateEngine is an abstraction of various template engines, this function selects a customized template engine. In our case it is Thymeleaf

  3. Function templateEngine.process() responsible for processing and returning the result as a string. It selects an HTML template, processes it, and replaces the expressions with the actual values.

  4. Finally, we embed the resulting result in MimeMessage and make the mail server treat it as HTML (mimeMessageHelper.setText(emailContent, true))

9. Email template

Here’s our HTML email template (I’ve shortened the HTML a bit to save space).

<!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
    <head>
        <meta charset="utf-8"> <!-- utf-8 works for most cases -->
        <meta name="viewport" content="width=device-width"> <!-- Forcing initial-scale shouldn't be necessary -->
        <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Use the latest (edge) version of IE rendering engine -->
        <meta name="x-apple-disable-message-reformatting">  <!-- Disable auto-scale in iOS 10 Mail entirely -->
        <title></title> <!-- The title tag shows in email notifications, like Android 4.4. -->
    
        <link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
    
        <!-- CSS Reset : BEGIN -->
     </head>
    
    <body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
    <center style="width: 100%; background-color: #f1f1f1;">
        <div style="display: none; font-size: 1px;max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;">
            &zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;
        </div>
        <div style="max-width: 600px; margin: 0 auto;" class="email-container">
            <!-- BEGIN BODY -->
            <table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin: auto;">
                <tr>
                    <td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
                        <table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
                            <tr>
                                <td class="logo" style="text-align: center;">
                                    <h1>Welcome</h1>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr><!-- end tr -->
                <tr>
                    <td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
                        <table>
                            <tr>
                                <td>
                                    <div class="text" style="padding: 0 2.5em; text-align: center;">
                                        <h2>Finish creating your account.</h2>
                                        <h3>Hi<p th:text="${firstName}"></h3>
                                        <h3>We're excited to have you get started. First, you need to confirm your account. Just press the button below.</h3>
                                        <p><a th:href="${verificationURL}" class="btn btn-primary">Validate Account</a></p>
                                    </div>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <div class="text" style="padding: 0 2.5em; text-align: center;">
                                        <h3>if you experience any issues with the button above, copy and paste the URL below into your web browser.</h3>
                                        <p th:text="${verificationURL}"></p>
                                    </div>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr><!-- end tr -->
                <!-- 1 Column Text + Button : END -->
            </table>
            <table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin: auto;">
                <tr>
                    <td valign="middle" class="bg_light footer email-section">
                        <table>
                            <tr>
                                <td valign="top" width="33.333%" style="padding-top: 20px;">
                                    <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
                                        <tr>
                                            <td style="text-align: left; padding-right: 10px;">
                                                <h3 class="heading">About</h3>
                                                <p>Welcome to Java Development Journal Blog. We publish articles on
                                                    Spring, Spring Boot and Spring Security.
                                                </p>
                                            </td>
                                        </tr>
                                    </table>
                                </td>
                                <td valign="top" width="33.333%" style="padding-top: 20px;">
                                    <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
                                        <tr>
                                            <td style="text-align: left; padding-left: 5px; padding-right: 5px;">
                                                <h3 class="heading">Contact Info</h3>
                                                <ul>
                                                    <li><span class="text">Java Development Journal</span></li>
                                                </ul>
                                            </td>
                                        </tr>
                                    </table>
                                </td>
                                <td valign="top" width="33.333%" style="padding-top: 20px;">
                                    <table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
                                        <tr>
                                            <td style="text-align: left; padding-left: 10px;">
                                                <h3 class="heading">Useful Links</h3>
                                                <ul>
                                                    <li><a href="https://habr.com/ru/company/otus/blog/557798/#">Home</a></li>
                                                    <li><a href="https://habr.com/ru/company/otus/blog/557798/#">About</a></li>
                                                </ul>
                                            </td>
                                        </tr>
                                    </table>
                                </td>
                            </tr>
                        </table>
                    </td>
                </tr><!-- end: tr -->
            </table>
    
        </div>
    </center>
    </body>
    </html>

Keep in mind that you need to contextualize the values ​​for ${firstName} and ${verifyURL}so that Thymeleaf could substitute actual values ​​for these variables during processing.

Summary

In this article, we learned how to send emails using Spring. We learned how you can implement email functionality using Spring Boot autoconfiguration. The source code provided in this post is available at Github


The translation of the material was prepared on the eve of the start of the online course Spring Framework Developer.

We also invite everyone to an open webinar Spring in Docker. Practical advice “… In this lesson, we will look at the well-known topic of running Spring applications in a Docker container and not everyone knows solutions to emerging problems.

Similar Posts

Leave a Reply