SpringBoot整合Mail傳送郵件&傳送模板郵件

陳大帥哥Ray發表於2020-07-29

  整合mail傳送郵件,其實就是通過程式碼來操作傳送郵件的步驟,編輯收件人、郵件內容、郵件附件等等。通過郵件可以擴充出簡訊驗證碼、訊息通知等業務。

一、pom檔案引入依賴

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!--freemarker模板引擎是為了後面傳送模板郵件 不需要的可以不引入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

二、application.yml檔案中配置


spring:
mail:
host: smtp.qq.xyz #這裡換成自己的郵箱型別 例如qq郵箱就寫smtp.qq.com
username: xx@qq.com #QQ郵箱
password: xxxxxxxxxxx #郵箱密碼或者授權碼
protocol: smtp #傳送郵件協議
properties.mail.smtp.auth: true
properties.mail.smtp.port: 465 #埠號465或587
properties.mail.smtp.starttls.enable: true
properties.mail.smtp.starttls.required: true
properties.mail.smtp.ssl.enable: true #開啟SSL
default-encoding: utf-8
freemarker:
cache: false # 快取配置 開發階段應該配置為false 因為經常會改
suffix: .html # 模版字尾名 預設為ftl
charset: UTF-8 # 檔案編碼
template-loader-path: classpath:/templates/ # 存放模板的資料夾,以resource資料夾為相對路徑

郵箱密碼暴露在配置檔案很不安全,一般都是採取授權碼的形式。點開郵箱,然後在賬戶欄裡面點選生成授權碼:

三、編寫MailUtils工具類

@Component
@Slf4j
public class MailUtils{

    /**
     * Spring官方提供的整合郵件服務的實現類,目前是Java後端傳送郵件和整合郵件服務的主流工具。
     */
    @Resource
    private JavaMailSender mailSender;

    /**
     * 從配置檔案中注入發件人的姓名
     */
    @Value("${spring.mail.username}")
    private String fromEmail;

    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    /**
     * 傳送文字郵件
     * @param to      收件人
     * @param subject 標題
     * @param content 正文
     */
    public void sendSimpleMail(String to, String subject, String content) {
        SimpleMailMessage message = new SimpleMailMessage();
        //發件人
        message.setFrom(fromEmail);
        message.setTo(to);
        message.setSubject(subject);
        message.setText(content);
        mailSender.send(message);
    }

    /**
     * 傳送html郵件
     */
    public void sendHtmlMail(String to, String subject, String content) {
        try {
            //注意這裡使用的是MimeMessage
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(fromEmail);
            helper.setTo(to);
            helper.setSubject(subject);
            //第二個引數:格式是否為html
            helper.setText(content, true);
            mailSender.send(message);
        }catch (MessagingException e){
            log.error("傳送郵件時發生異常!", e);
        }
    }

    /**
     * 傳送模板郵件
     * @param to
     * @param subject
     * @param template
     */
    public void sendTemplateMail(String to, String subject, String template){
        try {
            // 獲得模板
            Template template1 = freeMarkerConfigurer.getConfiguration().getTemplate(template);
            // 使用Map作為資料模型,定義屬性和值
            Map<String,Object> model = new HashMap<>();
            model.put("myname","Ray。");
            // 傳入資料模型到模板,替代模板中的佔位符,並將模板轉化為html字串
            String templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template1,model);
            // 該方法本質上還是傳送html郵件,呼叫之前傳送html郵件的方法
            this.sendHtmlMail(to, subject, templateHtml);
        } catch (TemplateException e) {
            log.error("傳送郵件時發生異常!", e);
        } catch (IOException e) {
            log.error("傳送郵件時發生異常!", e);
        }
    }

    /**
     * 傳送帶附件的郵件
     * @param to
     * @param subject
     * @param content
     * @param filePath
     */
    public void sendAttachmentsMail(String to, String subject, String content, String filePath) {
        try {
            MimeMessage message = mailSender.createMimeMessage();
            //要帶附件第二個引數設為true
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(fromEmail);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(content, true);

            FileSystemResource file = new FileSystemResource(new File(filePath));
            String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
            helper.addAttachment(fileName, file);
            mailSender.send(message);
        }catch (MessagingException e){
            log.error("傳送郵件時發生異常!", e);
        }

    }
}

MailUtils其實就是進一步封裝Mail提供的JavaMailSender類,根據業務場景可以在工具類裡面新增對應的方法,這裡提供了傳送文字郵件、html郵件、模板郵件、附件郵件的方法。

四、Controller層的實現

@Api(tags = "郵件管理")
@RestController
@RequestMapping("/mail")
public class MailController {

    @Autowired
    private MailUtils mailUtils;

    /**
     * 傳送註冊驗證碼
     * @return 驗證碼
     * @throws Exception
     */
    @ApiOperation("傳送註冊驗證碼")
    @GetMapping("/test")
    public String send(){
        mailUtils.sendSimpleMail("ruiyeclub@foxmail.com","普通文字郵件","普通文字郵件內容");
        return "OK";
    }

    /**
     * 傳送註冊驗證碼
     * @return 驗證碼
     * @throws Exception
     */
    @ApiOperation("傳送註冊驗證碼")
    @PostMapping("/sendHtml")
    public String sendTemplateMail(){
        mailUtils.sendHtmlMail("ruiyeclub@foxmail.com","一封html測試郵件",
                "<div style=\"text-align: center;position: absolute;\" >\n"
                        +"<h3>\"一封html測試郵件\"</h3>\n"
                        + "<div>一封html測試郵件</div>\n"
                        + "</div>");
        return "OK";
    }

    @ApiOperation("傳送html模板郵件")
    @PostMapping("/sendTemplate")
    public String sendTemplate(){
        mailUtils.sendTemplateMail("ruiyeclub@foxmail.com", "基於模板的html郵件", "hello.html");
        return "OK";
    }

    @ApiOperation("傳送帶附件的郵件")
    @GetMapping("sendAttachmentsMail")
    public String sendAttachmentsMail(){
        String filePath = "D:\\projects\\springboot\\template.png";
        mailUtils.sendAttachmentsMail("xxxx@xx.com", "帶附件的郵件", "郵件中有附件", filePath);
        return "OK";
    }
}

為了方便測試,這裡使用了swagger3,詳情可以檢視SpringBoot整合Swagger3生成介面文件

傳送模板郵件這裡,會讀取resources下面的templates資料夾,測試中讀取的是hello.html,具體程式碼如下:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>freemarker簡單示例</title>
</head>
<body>
<h1>Hello Freemarker</h1>
<div>My name is ${myname}</div>
</body>
</html>

五、測試結果

如果需要達到通過郵件傳送驗證碼的功能,可以使用redis。後臺隨機生成驗證碼,然後把使用者的主鍵設為key,驗證碼的內容設為value,還可以設定個60s過期儲存,傳送成功後,使用者登入通過主鍵從redis拿到對應的驗證碼,然後再進行登入驗證就好了。

參考連結:Spring Boot整合郵件配置

GitHub地址:https://github.com/ruiyeclub/SpringBoot-Hello