天天看點

SpringBoot整合(三)SpringBoot發送郵件使用SpringBoot發送郵件

使用SpringBoot發送郵件

郵件發送其實是一個非常常見的需求,使用者注冊,找回密碼等地方,都會用到,Spring Boot 中對于郵件發送,提供了相關的自動化配置類,使得郵件發送變得非常容易。

1、前置工作

目前國内大部分的郵件服務商都不允許直接使用使用者名/密碼的方式來在代碼中發送郵件,都是要先申請授權碼,這裡以 QQ 郵箱為例,向大家示範授權碼的申請流程:

首先我們需要先登入 QQ 郵箱網頁版,點選上方的設定按鈕:然後點選賬戶頁籤:在賬戶頁籤中找到開啟POP3/SMTP選項,如下:

SpringBoot整合(三)SpringBoot發送郵件使用SpringBoot發送郵件

點選開啟,開啟相關功能,開啟過程需要手機号碼驗證,按照步驟操作即可,不贅述。開啟成功之後,即可擷取一個授權碼,将該号碼儲存好,一會使用。

2、引入依賴、配置郵箱基本資訊

<!--內建發送郵件的功能-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
           

然後在yml配置檔案中進行配置

spring:
  mail:
    host: smtp.qq.com # 設定郵箱主機
    port: 587 # SMTP 伺服器的端口
    username: [email protected] # 設定使用者名
    password:  yyds # 設定密碼,該處的密碼是QQ郵箱開啟SMTP的授權碼而非QQ密碼

mail:
  from: ${spring.mail.username}
  to: [email protected]
           

做完這些之後,Spring Boot 就會自動幫我們配置好郵件發送類,相關的配置在

org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration

類中,部分源碼如下:

@Configuration
@ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class })
@ConditionalOnMissingBean(MailSender.class)
@Conditional(MailSenderCondition.class)
@EnableConfigurationProperties(MailProperties.class)
@Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class })
public class MailSenderAutoConfiguration {
    
}
           

可以看到,導入了另外一個配置

MailSenderPropertiesConfiguration

類,這個類中,提供了郵件發送相關的工具類,源碼如下:

@Configuration
@ConditionalOnProperty(prefix = "spring.mail", name = "host")
class MailSenderPropertiesConfiguration {
        private final MailProperties properties;
        MailSenderPropertiesConfiguration(MailProperties properties) {
                this.properties = properties;
        }
        @Bean
        @ConditionalOnMissingBean
        public JavaMailSenderImpl mailSender() {
                JavaMailSenderImpl sender = new JavaMailSenderImpl();
                applyProperties(sender);
                return sender;
        }
}

           

可以看到,這裡建立了一個

JavaMailSenderImpl

的執行個體,

JavaMailSenderImpl

JavaMailSender

的一個實作,我們将使用

JavaMailSenderImpl

來完成郵件的發送工作。

3、Service層代碼

自定義的MailProperties配置類,用于解析mail開頭的配置屬性

package com.yyds.domain;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "mail")
public class MailProperties {

    private String from;

    private String to;

}
           

service層

package com.yyds.service;

import freemarker.template.TemplateException;

import javax.mail.MessagingException;
import java.io.IOException;
import java.util.Map;

public interface MailService {

     void sendSimpleMail(String subject, String text) ;

     void sendHtmlMail(String subject, String text, Map<String, String> attachmentMap) throws MessagingException;

     void sendTemplateMail(String subject, Map<String, Object> params) throws MessagingException, IOException, TemplateException;
}

           
package com.yyds.service.impl;

import com.yyds.domain.MailProperties;
import com.yyds.service.MailService;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.IOException;
import java.util.Map;

@Service
public class MailServiceImpl implements MailService {

    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private MailProperties myMailProperties;



    /**
     * 發送簡單文本郵件
     */
    @Override
    public void sendSimpleMail(String subject, String text) {
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setFrom(myMailProperties.getFrom());
        mailMessage.setTo(myMailProperties.getTo());

        mailMessage.setSubject(subject);
        mailMessage.setText(text);

        javaMailSender.send(mailMessage);
    }

    /**
     * 發送帶有連結和附件的複雜郵件
     */
    @Override
    public void sendHtmlMail(String subject, String text, Map<String, String> attachmentMap) throws MessagingException {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();

        //是否發送的郵件是富文本(附件,圖檔,html等)
        MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);

        messageHelper.setFrom(myMailProperties.getFrom());
        messageHelper.setTo(myMailProperties.getTo());

        messageHelper.setSubject(subject);
        messageHelper.setText(text, true);//重點,預設為false,顯示原始html代碼,無效果

        if(attachmentMap != null){
            attachmentMap.entrySet().stream().forEach(entrySet -> {
                try {
                    File file = new File(entrySet.getValue());
                    if(file.exists()){
                        messageHelper.addAttachment(entrySet.getKey(), new FileSystemResource(file));
                    }
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
            });
        }

        javaMailSender.send(mimeMessage);
    }


    /**
     * 發送模版郵件
     */
    @Override
    public void sendTemplateMail(String subject, Map<String, Object> params) throws MessagingException, IOException, TemplateException {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();

        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);

        helper.setFrom(myMailProperties.getFrom());
        helper.setTo(myMailProperties.getTo());

        freemarker.template.Configuration configuration = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_19);
        TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), "/templates/");
        configuration.setTemplateLoader(templateLoader);
        Template template = configuration.getTemplate("mail.ftl");
        String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, params);


        helper.setSubject(subject);
        helper.setText(html, true);//重點,預設為false,顯示原始html代碼,無效果

        javaMailSender.send(mimeMessage);
    }
}

           

4、發送郵件

4.1 測試發送簡單文本郵件

@SpringBootTest(classes = BootStartApplication.class)
public class MimeMailTest {

    @Autowired
    private MailService mailService;

    @Test
    public void sendMail() {
        mailService.sendSimpleMail("測試Springboot發送郵件", "發送郵件...");
    }
}
           
SpringBoot整合(三)SpringBoot發送郵件使用SpringBoot發送郵件

4.2 測試發送帶有連結和附件的複雜郵件

package com.yyds;

import com.yyds.service.MailService;
import freemarker.template.TemplateException;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.mail.MessagingException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@SpringBootTest(classes = BootStartApplication.class)
public class MimeMailTest {

    @Autowired
    private MailService mailService;


    @Test
    public void testMail() throws MessagingException {

        Map<String, String> attachmentMap = new HashMap<>();
        attachmentMap.put("附件", "D:\\D_ENL_MRO資料統計.xlsx");

        mailService.sendHtmlMail("測試Springboot發送帶附件的郵件2", "歡迎進入<a href=\"http://www.baidu.com\">百度首頁</a>", attachmentMap);

    }

}
           
SpringBoot整合(三)SpringBoot發送郵件使用SpringBoot發送郵件

4.3 測試發送發送模版郵件

首先需要引入 Freemarker 依賴:

<!--整合freemarker-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
           

然後在

resources/templates

目錄下建立一個

mail.ftl

作為郵件發送模闆:

SpringBoot整合(三)SpringBoot發送郵件使用SpringBoot發送郵件
<html>
    <body>
    <h3>你好, <span style="color: red;">${username}</span>, 這是一封模闆郵件!</h3>
    </body>
</html>
           
package com.yyds;

import com.yyds.service.MailService;
import freemarker.template.TemplateException;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.mail.MessagingException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@SpringBootTest(classes = BootStartApplication.class)
public class MimeMailTest {

    @Autowired
    private MailService mailService;



    @Test
    public void testFreemarkerMail() throws MessagingException, IOException, TemplateException {

        Map<String, Object> params = new HashMap<>();
        params.put("username", "Tom");

        mailService.sendTemplateMail("測試Springboot發送模版郵件", params);
    }

}
           
SpringBoot整合(三)SpringBoot發送郵件使用SpringBoot發送郵件