Spring Boot: Mail Service

Keywords: Java Spring Thymeleaf Lombok

Articles Catalogue


This paper mainly demonstrates Spring Boot integrated mail function, including sending simple text mail, attachment mail, template mail.

I. Project Initialization Configuration

1.1 Project Dependence

<dependencies>
    <!-- test package-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <!--mail -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    <!--Use Thymeleaf Making mail template -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!-- lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>1.8.4</scope>
    </dependency>
    <!-- Hutool Tool kit-->
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>4.5.1</version>
    </dependency>
</dependencies>

1.2 Project Profile

I use this QQ mailbox as a test. Note: spring.mail.password is not the password of QQ mailbox, but the authorization code generated by QQ mailbox to third-party client mailbox. See specifically: https://service.mail.qq.com/cgi-bin/help?subtype=1&&no=1001256&&id=28

server:
  port: 8081
spring:
  mail:
    host: smtp.qq.com
# Mail account
    username: van93@qq.com
# Mailbox Authorization Code
    password: **************
    default-encoding: UTF-8
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true

2. Code Implementation

2.1 mail entity parameter: Mail.java

@Data
public class Mail {
	
	/** sender*/
	private String sender;
	
	/** recipient  */
	private String receiver;
	
	/** Message topic */
	private String subject;
	
	/** Message content*/
	private String text;
	/**
	 * Annex/Document Address
	 */
	private String filePath;
	/**
	 * Annex/File Name
	 */
	private String fileName;
	/**
	 * Template name
	 */
	private String emailTemplateName;
	/**
	 * Template content
	 */
	private Context emailTemplateContext;
	
}

2.2 Sending Mail Interface: MailService.java

public interface MailService {
    /**
     * Send regular mail
     * @param mail
     */
    void sendSimpleMail(Mail mail);

    /**
     * Send attachment mail
     * @param mail
     * @throws MessagingException
     */
    void sendAttachmentsMail(Mail mail) throws MessagingException;

    /**
     * Send template mail
     * @param mail
     */
    void sendTemplateMail(Mail mail);
}

2.3 Implementation of Sending Mail Interface: MailService Impl. Java

@Service("mailService")
@Slf4j
public class MailServiceImpl implements MailService {

    @Resource
    private JavaMailSender mailSender;

    @Resource
    TemplateEngine templateEngine;
    /**
     * The default sender is the configured mailbox account
     */
    @Value("${spring.mail.username}")
    private String sender;


    @Override
    public void sendSimpleMail(Mail mail){
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setFrom(sender);
        mailMessage.setTo(mail.getReceiver());
        mailMessage.setSubject(mail.getSubject());
        mailMessage.setText(mail.getText());
        mailSender.send(mailMessage);
    }

    /**
     * ResourceUtil From Hutool Toolkit
     * @param mail
     * @throws MessagingException
     */
    @Override
    public void sendAttachmentsMail(Mail mail) throws MessagingException {
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
        helper.setFrom(sender);
        helper.setTo(mail.getReceiver());
        helper.setSubject(mail.getSubject());
        helper.setText(mail.getText());
        URL resource = ResourceUtil.getResource(mail.getFilePath());
        String filePath = resource.getPath();
        String fileName = filePath.substring(filePath.lastIndexOf(File.separator)).substring(1);
        FileSystemResource file = new FileSystemResource(new File(filePath));
        helper.addAttachment(fileName, file);
        mailSender.send(mimeMessage);
    }

    @Override
    public void sendTemplateMail(Mail mail){
        // Template Engine replaces the dynamic parameters to produce the final html
        String emailContent = templateEngine.process(mail.getEmailTemplateName(), mail.getEmailTemplateContext());

        MimeMessage mimeMessage = mailSender.createMimeMessage();

        MimeMessageHelper helper = null;
        try {
            helper = new MimeMessageHelper(mimeMessage, true);
            helper.setFrom(sender);
            helper.setTo(mail.getReceiver());
            helper.setSubject(mail.getSubject());
            helper.setText(emailContent, true);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        mailSender.send(mimeMessage);
    }

}

2.4 Test class: MailServiceTest.java

  1. When testing attachment mail, attachments are placed under the static folder.
  2. When testing template mail, the template is placed in the templates folder.
@RunWith(SpringRunner.class)
@SpringBootTest
public class MailServiceTest {

    @Resource
    MailService mailService;

    /**
     * Test Simple Mail
     */
    @Test
    public void sendSimpleMail() {
        Mail mail = new Mail();
        mail.setReceiver("17098705205@163.com");
        mail.setSubject("Test Simple Mail");
        mail.setText("Testing Simple Contents");
        mailService.sendSimpleMail(mail);
    }

    /**
     * Test attachment mail
     */
    @Test
    public void sendAttachmentsMail() throws MessagingException {
        Mail mail = new Mail();
        mail.setReceiver("17098705205@163.com");
        mail.setSubject("Test attachment mail");
        mail.setText("Annex Mail Content");
        mail.setFilePath("static/dusty_blog.jpg");
        mailService.sendAttachmentsMail(mail);
    }

    /**
     * Test template mail
     */
    @Test
    public void sendTemplateMail(){
        Mail mail = new Mail();
        mail.setReceiver("17098705205@163.com");
        mail.setSubject("Test template mail");
        //Create template text
        Context context = new Context();
        // Setting the parameters of template to be replaced
        context.setVariable("verifyCode", "6666");
        mail.setEmailTemplateContext(context);
        // Template name (template location is in templates directory)
        mail.setEmailTemplateName("emailTemplate");
        mailService.sendTemplateMail(mail);
    }

}

III. Expansion

3.1 Send Failure

For various reasons, there will always be mail failure, such as: mail sent too frequently, network anomalies and so on. When this happens, we usually consider retrying the email, which can be achieved in the following steps:

  1. Receiving the request for sending mail, first record the request and store it in the library.
  2. Call the mail sending interface to send mail, and record the sending results into the library.
  3. During the scanning period of the start-up timing system, no mail was sent successfully and the number of retries was less than 3 times, and then sent again.

3.2 Asynchronous Sending

In many cases, mail delivery is not the result that our main business must pay attention to, such as notification class, reminder class business can allow delay or failure. At this time, the asynchronous way can be used to send mail to speed up the execution of the main transaction. In the actual project, MQ can be used to send mail related parameters and start sending mail after listening to the message queue.

3.3 Sample Code Address

https://github.com/vanDusty/SpringBoot-Home/tree/master/springboot-demo-mail/send-mail

Posted by Doyley on Thu, 15 Aug 2019 02:27:30 -0700