Use Springboot to send template email asynchronously to complete the registration function

catalogue

1. Use Springboot to send template mail and test

1. Add dependency

2. Configure application properties

3. Write HTML mail template

4. Write mail sending tool class

5. Testing

2. In the user's e-mail registration business - use multithreading to send account activation email asynchronously

1. Configure thread pool

2. Add @ Async annotation on the method of sending mail by mail tool class

3. Realize mailbox registration function

3.1 click Register to send the email and password to the back end

3.2. The backend processes the request, encapsulates the result into Ajax result and returns it

4. Realize the mailbox activation function

4.1 click the activation link in the email to jump to the activation page

4.2. Activate the user interface at the back end, and modify the state of the operation database to 1

3. Complete process of mailbox registration and activation

1. Enter the registration page and click Register

2. Enter the mailbox and check the mail

3. Click the link in the email to complete user activation

4. Activate successfully, jump to the login interface:

1. Send template mail using Springboot and test

1. Add dependency

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

2. Configure application properties

You need to obtain the email authorization code. I won't talk about it in detail here

# Set mailbox host (service provider)
spring.mail.host=smtp.qq.com
# Set user name
spring.mail.username=xxx@qq.com
# Set the password. The password here is the authorization code of QQ mailbox to open SMTP instead of QQ password
spring.mail.password=xxx
# Set code
spring.mail.default-encoding=UTF-8
#Sender

# Authorization authentication must be carried out. Its purpose is to prevent others from sending emails arbitrarily
spring.mail.properties.mail.smtp.auth=true

#SMTP encryption method: connect to a TLS protected connection
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

# JavaMailSender configuration
spring.mail.port=465
#SSL configuration
spring.mail.protocol=smtp
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.properties.mail.smtp.socketFactory.port=465
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory

3. Write HTML mail template

Put the template page in the templates directory under resources

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <title>Activate mail</title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: Arial, Helvetica, sans-serif;
        }

        body {
            background-color: #ECECEC;
        }

        .container {
            width: 800px;
            margin: 50px auto;
        }

        .header {
            height: 80px;
            background-color: #49bcff;
            border-top-left-radius: 5px;
            border-top-right-radius: 5px;
            padding-left: 30px;
        }

        .header h2 {
            padding-top: 25px;
            color: white;
        }

        .content {
            background-color: #fff;
            padding-left: 30px;
            padding-bottom: 30px;
            border-bottom: 1px solid #ccc;
        }

        .content h2 {
            padding-top: 20px;
            padding-bottom: 20px;
        }

        .content p {
            padding-top: 10px;
        }

        .footer {
            background-color: #fff;
            border-bottom-left-radius: 5px;
            border-bottom-right-radius: 5px;
            padding: 35px;
        }

        .footer p {
            color: #747474;
            padding-top: 10px;
        }
    </style>
</head>

<body>
<div class="container">
    <div class="header">
        <h1>Welcome to pet home!</h1>
    </div>
    <div class="content">
        <h2>Dear user,Hello!!</h2>
        <p>Your email:<b><span th:text="${email}"></span></b></p>
        <p>Your activation code:<b><span th:text="${code}"></span></b></p>
        <p>Date you registered:<b><span th:text="${createTime}"></span></b></p>
        <P><b>Please complete activation within 10 minutes:<a href="http://127.0.0.1:8083/activation. HTML "> Click me to activate < / a > < / b > < / P >
        <p></p>
        <p>When you use this website, you must abide by laws and regulations</p>
        <p>If you have any questions, you can contact the administrator, Email: <b>r1624603357@126.com</b></p>
    </div>
    <div class="footer">
        <p>This is a system email, please do not reply</p>
        <p>Please take good care of your information to avoid being stolen by others</p>
        <p>©Rk</p>
    </div>
</div>
</body>
</html>

4. Write mail sending tool class

package com.rk.pethome.basic.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.mail.internet.MimeMessage;
import java.util.Map;

@Component
public class SendMailUtil {
    //Sender
    private String sender="1624603357@qq.com";
    @Autowired
     JavaMailSender javaMailSender;
    @Autowired
     TemplateEngine templateEngine;

    /**
     * Send mail
     * @param receiver addressee
     * @param subject  Mail title
     * @param emailTemplate HTML Template
     * @param dataMap  Data in template
     * @throws Exception
     */
    //@Async / / send annotation asynchronously
    public void sendTemplateMail(String receiver, String subject, String emailTemplate, Map<String, Object> dataMap) throws Exception {
        Context context = new Context();
        for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
            context.setVariable(entry.getKey(), entry.getValue());
        }
        String templateContent = templateEngine.process(emailTemplate, context);
        MimeMessage message = javaMailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        helper.setFrom(sender);
        helper.setTo(receiver);
        helper.setSubject(subject);
        helper.setText(templateContent, true);
        javaMailSender.send(message);
    }
}

5. Testing

package com.rk.pethome.mail;
import com.rk.pethome.basic.util.SendMailUtil;
import com.rk.pethome.basic.util.StrUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.mail.internet.MimeMessage;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class MailSenderTest {

    @Autowired
    private SendMailUtil mailUtil;

    //addressee
    private final String receiver = "1624603357@qq.com";

    @Test
    public void testTemplateMail(){
        //Send mail
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy year MM month dd day HH Time mm branch ss second");
        String subject = "Pet home--User registration";
        String emailTemplate = "registerTemplate";
        String code = StrUtils.getRandomString(5);
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("email", receiver);
        dataMap.put("code", code);
        dataMap.put("createTime", sdf.format(new Date()));
        try {
            mailUtil.sendTemplateMail(receiver, subject, emailTemplate, dataMap);
            System.out.println("Send complete");
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
    }

}

 

2. In the user's email registration business - use multithreading to send account activation email asynchronously

1. Configure thread pool

package com.rk.pethome.basic.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
@EnableAsync  // Enable asynchronous tasks
public class AsyncConfiguration {
    // Declare a thread pool (and specify the name of the thread pool)
    @Bean("taskExecutor")
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //Number of core threads 5: the number of threads initialized when the thread pool is created
        executor.setCorePoolSize(5);
        //Maximum number of threads 5: the maximum number of threads in the thread pool. Threads exceeding the number of core threads will be applied only after the buffer queue is full
        executor.setMaxPoolSize(5);
        //Buffer queue 500: a queue used to buffer the execution of tasks
        executor.setQueueCapacity(500);
        //Allow thread idle time of 60 seconds: threads beyond the core thread will be destroyed after the idle time arrives
        executor.setKeepAliveSeconds(60);
        //Prefix of thread pool name: after setting, it is convenient for us to locate the thread pool where the processing task is located
        executor.setThreadNamePrefix("DailyAsync-");
        executor.initialize();
        return executor;
    }
}

2. Add @ Async annotation on the method of sending mail by mail tool class

3. Realize mailbox registration function

3.1 click Register to send the email and password to the back end

             //Register users via email
            emilReg(){
                //Get parameters
                let para = Object.assign({}, this.user);
                //Send request
                this.$http.post("/user/registerByEmial",para).then((res)=>{
                    console.debug(res);
                    console.debug(para);
                    let {success,msg}=res.data;
                    if(!success)//If it fails
                     {
                        this.errorMsg=msg;
                    }else{
                        //Clear error message
                        this.errorMsg="";
                        //location.href="login.html";
                    }
                });
            },

3.2. The backend processes the request, encapsulates the result into Ajax result and returns it

AjaxResult:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class AjaxResult {
    private Boolean success=true;
    private String msg;
    //Result value returned to the front end
    private Object result;

    public AjaxResult(Boolean success,String msg)
    {
        this.success=success;
        this.msg=msg;
    }

    public AjaxResult setResult(Object result){
        this.result=result;
        return this;
    }
}

Controller layer:

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private IUserService userService;


    /**
     * Register via email
     * @param userDot
     * @return
     */
    @PostMapping("/registerByEmial")
    public AjaxResult registerByEmial(@RequestBody UserDot userDot){
        try {
            System.out.println(userDot);
            return userService.registerEmail(userDot);
        } catch (Exception e) {
            e.printStackTrace();
            return new AjaxResult(false,"login has failed");
        }
    }
}

Service layer:

1. First, judge whether the password is entered and whether the two password inputs are consistent. Before that, judge whether it has been registered asynchronously, so there is no need to judge the mailbox here.

2. Save the registered mailbox and password to the database. The mailbox is also the user name

3. Send the activation email asynchronously (multithreaded). If it is not asynchronous, it will take about 6s to send the email, which greatly reduces the user's experience. After clicking registration, it is stuck for 6s - I thought there was a problem with the network

Note: the @ Async annotation should also be used in the method of sending mail, so that it can be executed asynchronously

4. In the testTemplateMail method of sending template mail, an activation code will be generated and stored on the redis server

@Service
public class IUserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SendMailUtil mailUtil;


    /**
     * Register via email
     * @param userDot
     * @return
     */
    @Override
    public AjaxResult registerEmail(UserDot userDot){
        try {
            //Judge whether the password is entered
            if(StringUtils.isBlank(userDot.getPassword())||StringUtils.isBlank(userDot.getConfirmPassword()))
                return new AjaxResult(false,"Please input a password");
            //If the two faces are not equal
            if(!userDot.getPassword().equals(userDot.getConfirmPassword()))
                return new AjaxResult(false,"The two passwords are inconsistent");

            //Save object
            User user=new User();
            user.setUsername(userDot.getEmail());
            user.setEmail(userDot.getEmail());
            user.setCreatetime(new Date());
            user.setState(0);//Activated after mobile phone verification

            //Salt value encryption for user password
            user.setPassword(MD5Utils.encrypByMd5(userDot.getPassword()));
            //Save user
            userMapper.saveUser(user);
            //Send email to newly registered users
            testTemplateMail(user.getEmail());
            return new AjaxResult(false,"The email has been sent to the mailbox. Please complete the activation within 10 minutes!");
        } catch (Exception e){
            e.printStackTrace();
            return new AjaxResult(false,"login has failed!");
        }
    }

    /**
     * Send mail
     * @param receiver addressee
     */
    @Async
    public void testTemplateMail(String receiver){
        //Send mail
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy year MM month dd day HH Time mm branch ss second");
        String subject = "Pet home--User registration";
        String emailTemplate = "registerTemplate";
        //Get activation code
        String code = StrUtils.getRandomString(5);
        //Save the activation code to the redis server
        //Set the validity period to 10 minutes. The key value is: Action + email. The value value is: verification code
        RedisUtils.INSTANCE.set("Action:"+receiver,code,10*60);
        System.out.println("key:"+"Action:"+receiver+"   value:"+code);
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("email", receiver);
        dataMap.put("code", code);
        dataMap.put("createTime", sdf.format(new Date()));
        try {
            mailUtil.sendTemplateMail(receiver, subject, emailTemplate, dataMap);
            System.out.println("Send complete");
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
    }
}

Mapper layer:

    /**
     * Save user
     * @param user
     */
    void saveUser(User user);

Mapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rk.pethome.user.mapper.UserMapper">
    <!--Save user-->
    <insert id="saveUser" parameterType="user">
        insert into t_user(username,email,phone, password, state, createtime)
        VALUES (#{username},#{email},#{phone},#{password},#{state},#{createtime})
    </insert>
</mapper>

At this time, the user state attribute is 0, and the user is in an inactive state. We need to go to the mailbox and click the activate button to complete the activation operation before logging in.

4. Realize the mailbox activation function

4.1 click the activation link in the email to jump to the activation page

     userActivation(){
                let para={"email":this.email,"code":this.code};
                this.$http.post("/user/userAction",para).then((res)=> {
                    let {success,msg}=res.data;
                    if(!success)//If activated / / printing fails
                    {
                        this.errorMsg=msg;
                    }else{
                        //Clear error message
                        this.errorMsg="";
                        //Complete the activation and jump to the login page
                        location.href="login.html";
                    }
                })
            },

4.2. Activate the user interface at the back end and modify the state of the operation database to 1

Controller layer:

 /**
     * Log in via email or mobile number
     * @return
     */
    @PostMapping("/userAction")
    public AjaxResult activation(@RequestBody HashMap<String,String> para){
        try {
            System.out.println(para.get("code"));
            String email=para.get("email");
            String code = para.get("code");
            return userService.activation(email,code);
        } catch (Exception e) {
            e.printStackTrace();
            return new AjaxResult(false, e.getMessage());
        }
    }

Service layer:

1. Judge whether the entered value is empty

2. Receive the delivered email and the activation code of the user through Action+email. The code is the activation code entered by the user.

3. Judge whether the user name is correctly entered or whether the activation code is expired by obtaining the value from the redis server through Action+email. If it is not empty, compare it with the value entered by the user. Equal indicates that the activation code is correct.

4. Modify the user's state to 1 through email. Indicates that the user has been activated. At this time, remove the activation code on the redis server

    /**
     * User activation
     *
     * @param email mailbox
     * @param code  Activation code
     * @return
     */
    @Override
    public AjaxResult activation(String email, String code) {
        //Judge whether the input is empty
        if(StringUtils.isBlank(email)||StringUtils.isBlank(code)){
            return new AjaxResult(false,"Please enter email address and activation code!!");
        }
        //Check whether the activation code is normal
        //Get the code value from the redis server. If the code value is empty, the activation code is wrong or expired!
        String s = RedisUtils.INSTANCE.get("Action:" + email);//Activation code obtained from redis server
        System.out.println("redis The activation code obtained on the server is:"+s);
        if(s==null)
            return new AjaxResult(false,"Mailbox error or activation code has expired!!");
        //Is the activation code correct
        if(!code.equals(s))//incorrect
        {
            return new AjaxResult(false,"Activation code error!!");
        }

        //Remove from redis server after activation
        RedisUtils.INSTANCE.del("Action:" + email);

        //Modifying the user status to 1 indicates that the user has been activated
        userMapper.updateState(email);

        return new AjaxResult();
    }

Mapper layer:

    /**
     * Activate user
     * @param email
     */
    void updateState(String email);

Mapper.xml:

    <!--Modify user to active status-->
    <update id="updateState">
        update t_user set state=1 where email=#{email}
    </update>

3. Complete process of mailbox registration and activation

1. Enter the registration page and click Register

2. Enter the mailbox and check the mail

To view the key on the redis server:

To view users registered in the database:

3. Click the link in the email to complete user activation

Incorrect activation code entered:

Enter the correct activation code:

4. Activate successfully, jump to the login interface:

View users in the database

Check the activation code on the redis server:

 

 

 

 

 

 

 

 

 

 

 

 

 

Tags: Java Redis Spring Boot

Posted by Springroll on Thu, 14 Apr 2022 19:00:12 +0930