Title

Springboot集成发送邮件功能

1、导入依赖

springboot 集成了发送邮件功能的依赖

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

2、配置文件

spring:
  mail:
    # 配置模板文件
    templates: 'templates.html'
    # 配置 SMTP 服务器地址
    host: smtp.qq.com
    # 发送者邮箱
    username: 239XXXX9@qq.com
    # 配置密码,注意不是真正的密码,而是刚刚申请到的授权码
    password: gplXXXXche
    # 端口号 456 或 587
    port: 587
    # 默认的邮件编码为 UTF-8
    default-encoding: UTF-8
    # 配置 SSL 加密工厂
    properties:
      mail:
        smtp:
          socketFactoryClass: javax.net.ssl.SSLSocketFactory
        # 表示开启 DEBUG 模式,邮件发送过程日志会在控制台打印出来,方便排查错误
        debug: true
  • 注意:
    使用 Nacos 时,使用 @Value 注解来获取配置中的配置信息,但不能实现动态。
    使用 @NacosValue 和 @NacosProperySource 注解还是获取不到时
    解决办法:

//配置文件上下文,使用该类来实现动态获取配置中心的配置文件信息
@Autowired
private ConfigurableApplicationContext configurableApplicationContext;

// 获得配置文件中配置的值
configurableApplicationContext.getEnvironment().getProperty("中心配置的属性值");
  • 模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div class="info-top" style="padding: 15px 25px;
				                                     border-top-left-radius: 10px;
				                                     border-top-right-radius: 10px;
				                                     background: burlywood;
				                                     color: crimson;
				                                     line-height: 10px;">
    <div style="font-size: 18px" ><b>{0}</b></div>
</div>

<div class="info-wrap" style="border-bottom-left-radius: 10px;
				                                  border-bottom-right-radius: 10px;
				                                  border:1px solid #ddd;
				                                  overflow: hidden;
				                                  padding: 15px 15px 20px;">
    <div class="tips" style="padding:15px;">
        <p style=" list-style: 160%; margin: 10px 0;"><h3>Hi</h3>以下信息请您仔细阅读:</p>
        <p style=" list-style: 160%; margin: 10px 0;">&nbsp;&nbsp;{1}</p>
    </div>
</div>
</body>
</html>

3、代码实现

MailService接口

package com.its.server.domain.meet.service;

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

/**
 * 邮件服务
 */
public interface MailService {
    /**
     * 普通邮件发送
     * @param tos 发送邮件地址列表
     * @param subject 标题
     * @param contentText 正文信息
     */
    void sendSimpleMail(String[] tos,String subject,String contentText);
    /**
     * 带抄送人普通邮件发送
     * @param tos 发送邮件地址列表
     * @param cc 邮件抄送人列表
     * @param bcc 隐秘抄送人列表
     * @param subject 标题
     * @param contentText 正文信息
     */
    void sendSimpleMailCc(String[] tos, String[] cc, String[] bcc, String subject, String contentText);

    /**
     * 模板邮件发送
     * @param tos 发送邮件地址列表
     * @param subject 标题
     * @param contentTitle 正文标题
     * @param contentText 正文信息
     */
    void sendMail(String[] tos,String subject,String contentTitle,String contentText) throws MessagingException;
    /**
     * 带抄送人模板邮件发送
     * @param tos 发送邮件地址列表
     * @param cc 邮件抄送人列表
     * @param bcc 隐秘抄送人列表
     * @param subject 标题
     * @param contentTitle 正文标题
     * @param contentText 正文信息
     */
    void sendMailCc(String[] tos, String[] cc, String[] bcc,String subject,String contentTitle,String contentText) throws MessagingException;

    /**
     * 带附件的邮件发送
     * @param tos 发送邮件地址列表
     * @param subject 标题
     * @param contentTitle 正文标题
     * @param contentText 正文信息
     * @param attachFileMap 附件 key: 文件名称(后缀要加上,eg:资料.xlsx) value: 文件位置(eg:/Desktop/测试数据 2.xlsx)
     */
    void sendAttachFileMail(String[] tos, String subject, String contentTitle, String contentText, Map<String ,String> attachFileMap) throws MessagingException;

    /**
     * 带抄送人带附件的邮件发送
     * @param tos 发送邮件地址列表
     * @param cc 邮件抄送人列表
     * @param bcc 隐秘抄送人列表
     * @param subject 标题
     * @param contentTitle 正文标题
     * @param contentText 正文信息
     * @param attachFileMap 附件 key: 文件名称(后缀要加上,eg:资料.xlsx) value: 文件位置(eg:/Desktop/测试数据 2.xlsx)
     */
    void sendAttachFileMailCc(String[] tos,String [] cc,String [] bcc,String subject,String contentTitle,String contentText, Map<String ,String> attachFileMap) throws MessagingException;
}

MailService接口实现类 MailServiceImpl

package com.its.server.domain.meet.service.impl;

import com.its.server.domain.meet.service.MailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.*;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Map;

/**
 * 邮件服务
 *
 * @author z
 * @date 2022-02-07 15:47
 */
@Service
@Slf4j
@RefreshScope
public class MailServiceImpl implements MailService {
    @Resource
    private JavaMailSender mailSender;

    @Autowired
    private ConfigurableApplicationContext configurableApplicationContext;

    private static final String FILENAME="spring.mail.templates";

    private static final String FROM="spring.mail.username";

    /**
     * 读取替换html文件模板中的信息
     * @param title 正文标题
     * @param contentText 正文信息
     * @return 替换后文件模板中的信息
     */
    public String scopeTemplate(String title ,String contentText){
        InputStream inputStream=ClassLoader.getSystemResourceAsStream(configurableApplicationContext.getEnvironment().getProperty(FILENAME));
        BufferedReader fileReader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer buffer = new StringBuffer();

        String line="";
        try{
            while((line = fileReader.readLine())!= null){
                buffer.append(line);
            }
        }catch(IOException e){
            log.info("read template:{}",e);
        }finally{
            if(inputStream != null){
                try{
                    inputStream.close();
                }catch (Exception e){
                    log.info("{}",e);
                }
            }
            if (fileReader != null){
                try{
                    fileReader.close();
                }catch(Exception e){
                    log.info("{}",e);
                }
            }
        }
        return MessageFormat.format(buffer.toString(),title,contentText);
    }
    /**
     * 普通邮件发送
     * @param tos 发送邮件地址列表
     * @param subject 标题
     * @param contentText 正文信息
     */
    @Override
    public void sendSimpleMail(String[] tos,String subject,String contentText) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
        message.setTo(tos);
        message.setSubject(subject);
        message.setSentDate(new Date());
        message.setText(contentText);
        mailSender.send(message);
    }
    /**
     * 带抄送人普通邮件发送
     * @param tos 发送邮件地址列表
     * @param cc 邮件抄送人列表
     * @param bcc 隐秘抄送人列表
     * @param subject 标题
     * @param contentText 正文信息
     */
    @Override
    public void sendSimpleMailCc(String[] tos, String[] cc, String[] bcc, String subject, String contentText) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
        message.setTo(tos);
        message.setCc(cc);
        message.setBcc(bcc);
        message.setSubject(subject);
        message.setSentDate(new Date());
        message.setText(contentText);
        mailSender.send(message);
    }
    /**
     * 模板邮件发送
     * @param tos 发送邮件地址列表
     * @param subject 标题
     * @param contentTitle 正文标题
     * @param contentText 正文信息
     */
    @Override
    public void sendMail(String[] tos, String subject, String contentTitle, String contentText) throws MessagingException {
        MimeMessage mimeMessage=mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage);
        helper.setTo(tos);
        helper.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
        helper.setSubject(subject);
        helper.setSentDate(new Date());
        helper.setText(scopeTemplate(contentTitle,contentText),true);
        mailSender.send(mimeMessage);
    }
    /**
     * 带抄送人模板邮件发送
     * @param tos 发送邮件地址列表
     * @param cc 邮件抄送人列表
     * @param bcc 隐秘抄送人列表
     * @param subject 标题
     * @param contentTitle 正文标题
     * @param contentText 正文信息
     */
    @Override
    public void sendMailCc(String[] tos, String[] cc, String[] bcc, String subject, String contentTitle, String contentText) throws MessagingException {
        MimeMessage mimeMessage=mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage);
        helper.setTo(tos);
        helper.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
        helper.setCc(cc);
        helper.setBcc(bcc);
        helper.setSubject(subject);
        helper.setSentDate(new Date());
        helper.setText(scopeTemplate(contentTitle,contentText),true);
        mailSender.send(mimeMessage);
    }

    /**
     * 带附件的邮件发送
     * @param tos 发送邮件地址列表
     * @param subject 标题
     * @param contentTitle 正文标题
     * @param contentText 正文信息
     * @param attachFileMap 附件 key: 文件名称(后缀要加上,eg:资料.xlsx) value: 文件位置(eg:/Desktop/测试数据 2.xlsx)
     */
    @Override
    public void sendAttachFileMail(String[] tos, String subject, String contentTitle, String contentText, Map<String ,String> attachFileMap) throws MessagingException {
        MimeMessage mimeMessage=mailSender.createMimeMessage();
        // true表示构建一个可以带附件的邮件对象
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
        helper.setTo(tos);
        helper.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
        helper.setSubject(subject);
        helper.setSentDate(new Date());
        helper.setText(scopeTemplate(contentTitle,contentText),true);
        for (String key : attachFileMap.keySet()) {
            // 第一个参数是自定义的名称,后缀需要加上,第二个参数是文件的位置
            helper.addAttachment(key,new File(attachFileMap.get(key)));
        }
        mailSender.send(mimeMessage);
    }
    /**
     * 带抄送人带附件的邮件发送
     * @param tos 发送邮件地址列表
     * @param cc 邮件抄送人列表
     * @param bcc 隐秘抄送人列表
     * @param subject 标题
     * @param contentTitle 正文标题
     * @param contentText 正文信息
     * @param attachFileMap 附件 key: 文件名称(后缀要加上,eg:资料.xlsx) value: 文件位置(eg:/Desktop/测试数据 2.xlsx)
     */
    @Override
    public void sendAttachFileMailCc(String[] tos, String[] cc, String[] bcc, String subject, String contentTitle, String contentText,Map<String ,String> attachFileMap) throws MessagingException {
        MimeMessage mimeMessage=mailSender.createMimeMessage();
        // true表示构建一个可以带附件的邮件对象
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
        helper.setTo(tos);
        helper.setFrom(configurableApplicationContext.getEnvironment().getProperty(FROM));
        helper.setCc(cc);
        helper.setBcc(bcc);
        helper.setSubject(subject);
        helper.setSentDate(new Date());
        helper.setText(scopeTemplate(contentTitle,contentText),true);
        for (String key : attachFileMap.keySet()) {
            // 第一个参数是自定义的名称,后缀需要加上,第二个参数是文件的位置
            helper.addAttachment(key,new File(attachFileMap.get(key)));
        }
        mailSender.send(mimeMessage);
    }
}

测试接口

package com.its.server.domain.meet.web;

import com.its.server.domain.meet.service.impl.MailServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

/**
 * 邮件测试
 *
 * @author z
 * @date 2022-02-07 17:45
 */
@Api("邮件测试")
@RestController
@RequestMapping("/mailTest")
@Slf4j
public class MailTestController {
    @Autowired
    private MailServiceImpl mailService;

    @ApiOperation("测试普通邮件")
    @GetMapping("/sendMail")
    public String sendMail(){
        try {
            mailService.sendMail(new String[]{"303XXXX44@qq.com"},"test","this is a test" ,"这是个测试邮件");
        } catch (MessagingException e) {
            log.info("{}",e);
        }
        return "发送成功";
    }

    @ApiOperation("测试带附件邮件")
    @GetMapping("/sendAttachFileMail")
    public String sendAttachFileMail(){
        try {
            Map<String ,String> map=new HashMap<>();
            map.put("aaa.png","C:\\Users\\Desktop\\aa.png");
            map.put("aab.png","C:\\Users\\Desktop\\aa.png");
            mailService.sendAttachFileMail(new String[]{"303XXXX44@qq.com"},"这是测试邮件","test","this is a test",map);
        } catch (MessagingException e) {
            log.info("{}",e);
        }
        return "发送成功";
    }
}

4、更多

  • 发送带图片资源的邮件

图片资源和附件有什么区别呢?图片资源是放在邮件正文中的,即一打开邮件,就能看到图片。但是一般来说,不建议使用这种方式,一些公司会对邮件内容的大小有限制(因为这种方式是将图片一起发送的)。

/**
 * 正文中带图片的邮件
 * @throws MessagingException
 */
@Test
public void sendImgResMail() throws MessagingException {
    MimeMessage mimeMessage = javaMailSender.createMimeMessage();
    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
    helper.setSubject("这是一封测试邮件");
    helper.setFrom("79*****39@qq.com");
    helper.setTo("10****6@qq.com");
    //helper.setCc("37xxxxx37@qq.com");
    //helper.setBcc("14xxxxx098@qq.com");
    helper.setSentDate(new Date());
    // src='cid:p01' 占位符写法 ,第二个参数true表示这是一个html文本
    helper.setText("<p>hello 大家好,这是一封测试邮件,这封邮件包含两种图片,分别如下</p><p>第一张图片:</p><img src='cid:p01'/><p>第二张图片:</p><img src='cid:p02'/>",true);
    // 第一个参数指的是html中占位符的名字,第二个参数就是文件的位置
    helper.addInline("p01",new FileSystemResource(new File("/Users/gamedev/Desktop/压缩.jpeg")));
    helper.addInline("p02",new FileSystemResource(new File("/Users/gamedev/Desktop/瑞文.jpg")));
    javaMailSender.send(mimeMessage);
}

效果

在公司实际开发中,第一种和第三种都不是使用最多的邮件发送方案。因为正常来说,邮件的内容都是比较的丰富的,所以大部分邮件都是通过 HTML 来呈现的,如果直接拼接 HTML 字符串,这样以后不好维护,为了解决这个问题,一般邮件发送,都会有相应的邮件模板。

  • 使用 Thymeleaf 作邮件模板

推荐在 Spring Boot 中使用 Thymeleaf 来构建邮件模板。因为 Thymeleaf 的自动化配置提供了一个 TemplateEngine,通过 TemplateEngine 可以方便的将 Thymeleaf 模板渲染为 HTML ,同时,Thymeleaf 的自动化配置在这里是继续有效的。

引入 Thymeleaf 依赖:

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

创建Thymeleaf模板:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>hello 欢迎加入 xxx 大家庭,您的入职信息如下:</p>
<table border="1">
    <tr>
        <td>姓名</td>
        <td th:text="${username}"></td>
    </tr>
    <tr>
        <td>工号</td>
        <td th:text="${num}"></td>
    </tr>
    <tr>
        <td>薪水</td>
        <td th:text="${salary}"></td>
    </tr>
</table>
<div style="color: #ff1a0e">一起努力创造辉煌</div>
</body>
</html>

发送邮件:

    @Autowired
    TemplateEngine templateEngine;

    @Test
    public void sendThymeleafMail() throws MessagingException {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
        helper.setSubject("这是一封测试邮件");
        helper.setFrom("790933839@qq.com");
        helper.setTo("1032065316@qq.com");
//        helper.setCc("37xxxxx37@qq.com");
//        helper.setBcc("14xxxxx098@qq.com");
        helper.setSentDate(new Date());
        // 这里引入的是Template的Context
        Context context = new Context();
        // 设置模板中的变量
        context.setVariable("username", "javaboy");
        context.setVariable("num","000001");
        context.setVariable("salary", "99999");
        // 第一个参数为模板的名称
        String process = templateEngine.process("hello.html", context);
        // 第二个参数true表示这是一个html文本
        helper.setText(process,true);
        javaMailSender.send(mimeMessage);
    }

效果:


参考链接:

https://www.cnblogs.com/sun2020/p/13961554.html

posted @ 2022-02-08 10:22  快乐小洋人  阅读(246)  评论(0编辑  收藏  举报