springboot2.x分别使用freemarker,thymeleaf,velocity发送邮件(包括带附件的)到qq邮箱

1.首先,需要在引入mail,freemarker,thymeleaf,velocity等相关的jar包。

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>
       
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-velocity</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.4</version>
        </dependency>

2.在resources目录下创建templates与img目录,里边分别放了freemarker、thymeleaf、velocity的模板文件与相关的图片与pdf文档等等。

3.在springboot的默认配置文件application.yml中增加freemarker,thymeleaf的相关配置,以及发送邮件需要用到的参数。

spring: 
  freemarker:
    enabled: true
    cache: true
    charset: UTF-8
    content-type: text/html
    check-template-location: true
    # 其实这里是默认的路径,理论上可以不用写,至于不写行不行请各位自己去尝试了
    template-loader-path: classpath:/templates/
  mail:
    host: smtp.qq.com
    protocol: smtp
    username: #自己填写
    # qq邮箱授权码,自己提前开通SMTP,具体操作请自行前往qq邮箱进行相应的操作即可。
    password: xxxxx
  thymeleaf:
    cache: false
    encoding: UTF-8
    mode: LEGACYHTML5
  # 其实这里是默认的路径,理论上可以不用写,至于不写行不行请各位自己去尝试了
    prefix: classpath:/templates/

3.freemarker、thymeleaf与velocity的模板代码截图

有些地方参照了博客:

https://www.cnblogs.com/lovling/p/12761001.html

freemarker的代码

<style type="text/css">
    .mail-table {
        width: 100%;
        border-top: 1px solid #333;
        border-left: 1px solid #333;
        border-collapse: collapse;
        border-spacing: 0;
    }
    .mail-table tr {

    }
    .mail-table th {
        background: rgb(255, 204, 204);
        height: 40px;
        border-bottom: 1px solid #333;
        border-right: 1px solid #333;
    }
    .mail-table td {
        height: 36px;
        text-indent: 14px;
        border-bottom: 1px solid #333;
        border-right: 1px solid #333;
    }
</style>

<h3>${title}</h3>
<table class="mail-table">
    <tr>
        <th>序号</th>
        <th>账号</th>
        <th>昵称</th>
    </tr>
    <#list users as user>
        <tr>
            <td>${user_index + 1}</td>
            <td>${user.realName}</td>
            <td>${user.userName}</td>
        </tr>
    </#list>
</table>
<!-- 图片地址固定为 cid:MailVo的name,此处为为固定写法 -->
<img src="cid:battle-field" alt="img"/>

thymeleaf的模板mail-the.html的代码截图

springboot2.x分别使用freemarker,thymeleaf,velocity发送邮件(包括带附件的)到qq邮箱

velocity的模板mail-vm的代码截图

springboot2.x分别使用freemarker,thymeleaf,velocity发送邮件(包括带附件的)到qq邮箱

发送邮件service代码

package com.springcloud.my.service.impl;

import com.springcloud.my.entity.MailVo;
import com.springcloud.my.utils.ContentTypeEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.File;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.*;


@Service
public class MailSendService {

    @Autowired
    private JavaMailSender mailSender;

    @Value("${spring.mail.username}")
    private String fromMailName;

    @Autowired
    private TemplateEngine templateEngine;

    /**
     * 发送邮件的方法
     * <p>
     * 三种收件人模式的解释
     * 1,Message.RecipientType.TO  直接接收人
     * 2,Message.RecipientType.CC  明抄送收件人
     * 3,Message.RecipientType.BCc 暗抄送收件人(不会 被直接收件人 和 明抄送收件人 看见的收件人)
     * @param toAddr  收件人
     * @param ccAddr  抄送人
     * @param subject 邮件标题
     * @param html    邮件内容
     * @param srcVos  静态资源类
     * @param athVos  附件资源类
     */
    public void sendMail(String[] toAddr, String[] ccAddr, String subject, String html, List<MailVo> srcVos, List<MailVo> athVos) {
        try {
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(fromMailName);
            helper.setSubject(subject);
            helper.setText(html, true);
            if (toAddr != null && toAddr.length > 0) {
                Address[] addresses = getAddresses(toAddr);
                message.setRecipients(Message.RecipientType.TO, addresses);
            }
            if (ccAddr != null && ccAddr.length > 0) {
                Address[] addresses = getAddresses(ccAddr);
                message.setRecipients(Message.RecipientType.CC, addresses);
            }
            if (CollectionUtils.isNotEmpty(srcVos)) {
                for (MailVo srcVo : srcVos) {
                    helper.addInline(srcVo.getName(), srcVo.getFile());
                }
            }
            addAttFile(athVos, helper);
            mailSender.send(message);
        } catch (MessagingException ex) {
            throw new RuntimeException(ex.getMessage());
        }
    }

    private Address[] getAddresses(String[] ccAddr) throws AddressException {
        Address[] addresses = new Address[ccAddr.length];
        for (int i = 0; i < ccAddr.length; i++) {
            addresses[i] = new InternetAddress(ccAddr[i]);
        }
        return addresses;
    }

    public void sendSimpleMail(Map<String, Object> valueMap, List<MailVo> athVos, List<MailVo> srcVos) {
        try {
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            // 设置发件人邮箱
            helper.setFrom(fromMailName);
            // 设置收件人邮箱
            helper.setTo((String[]) valueMap.get("to"));
            // 设置邮件标题
            helper.setSubject(valueMap.get("title").toString());
            // 设置邮件正文
            helper.setSubject(valueMap.get("content").toString());
            // 添加正文(使用thymeleaf模板)
            Context context = new Context();
            context.setVariables(valueMap);

            String stringContext = templateEngine.process("mail-the", context);

            helper.setText(stringContext, true);

            //设置静态
            if (CollectionUtils.isNotEmpty(athVos)) {
                for (MailVo athVo : athVos) {
                    helper.addInline(athVo.getName(), new FileSystemResource(athVo.getFile()));
                }
            }
            addAttFile(srcVos, helper);

            // 发送邮件
            mailSender.send(mimeMessage);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }

    public void setMailByVm(Map<String, Object> contentMap) {
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        //InputStream inputStream = null;
        try {
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
            messageHelper.setFrom(fromMailName);
            messageHelper.setTo(fromMailName);
            messageHelper.setSubject(contentMap.get("content").toString());
            Map<String, Object> map = new HashMap<>();
            map.put("url", contentMap.get("url"));
            map.put("currentDate", contentMap.get("date"));

            Properties properties = new Properties();
            //从类路径加载模板文件 设置velocity资源加载方式为class
            properties.setProperty("resource.loader", "class");
            //设置velocity资源加载方式为class时的处理类
            properties.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
            properties.setProperty(Velocity.ENCODING_DEFAULT, "UTF-8");
            properties.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
            properties.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
            properties.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.NullLogChute");

            //实例化一个VelocityEngine对象
            VelocityEngine velocityEngine = new VelocityEngine(properties);
            velocityEngine.init();

            StringWriter writer = new StringWriter();
            VelocityContext velocityContext = new VelocityContext();

            velocityContext.put("test", map);
            Template template = velocityEngine.getTemplate("templates/mail-vm.vm");
            template.merge(velocityContext, writer);

            // 用来让text内容以html格式进行展示
            messageHelper.setText(writer.toString(), true);

            messageHelper.addInline("identifier01", (File) contentMap.get("imgPath"));

            File pdfFile = (File) contentMap.get("pdf");
            // 添加pdf附件
            messageHelper.addAttachment(MimeUtility.encodeWord(pdfFile.getName()), new FileSystemResource(pdfFile), ContentTypeEnum.PDF.getCentType());

            // 发送邮件
            mailSender.send(mimeMessage);
        } catch (MessagingException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置附件
     *
     * @param srcVos 附件集合
     * @param helper
     * @throws MessagingException
     */
    private void addAttFile(List<MailVo> srcVos, MimeMessageHelper helper) throws MessagingException {
        if (CollectionUtils.isNotEmpty(srcVos)) {
            for (MailVo athVo : srcVos) {
                helper.addAttachment(athVo.getName(), athVo.getFile());
            }
        }
    }

}

发送邮件的controller代码

package com.springcloud.my.controller;

import com.springcloud.my.entity.MailVo;
import com.springcloud.my.entity.User;
import com.springcloud.my.service.impl.MailSendService;
import com.springcloud.my.utils.DateUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;

/**
 * 邮件发送控制器
 *
 * @Author Administrator
 * @Date 2020/6/23/
 */
@RestController
@RequestMapping("/send")
public class SendEmailController {


    @Autowired
    private MailSendService mailService;

    @Autowired
    private Configuration configuration;

    @RequestMapping("/send")
    public ResponseEntity<Object> sendSimpleMail() throws IOException, TemplateException {
        Template template = configuration.getTemplate("mail.ftl", "UTF-8");
        Map<String, Object> model = new HashMap<>();
        List<User> userList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            User user = new User();
            user.setRealName("111111" + i);
            user.setUserName("22222" + i);
            userList.add(user);
        }
        model.put("title", "只是测试的邮件");
        model.put("users", userList);
        String[] toAddr = new String[]{"xxxx@qq.com"};
        //抄送人的邮件地址,可以不设置
        //String[] ccAddr = new String[] {"xxx@qq.com"};
        String subject = "测试邮件";
        String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);

        List<MailVo> srcVos = new ArrayList<>();
        MailVo mailFileSrc = new MailVo();
        mailFileSrc.setName("battle-field");
        mailFileSrc.setFile(ResourceUtils.getFile("classpath:static/img/test.png"));
        srcVos.add(mailFileSrc);

        List<MailVo> athVos = new ArrayList<>();
        MailVo mailFileAth = new MailVo();
        mailFileAth.setName("你的附件.txt");
        mailFileAth.setFile(ResourceUtils.getFile("classpath:static/img/msg.txt"));
        athVos.add(mailFileAth);

        mailService.sendMail(toAddr, null, subject, html, srcVos, athVos);
        return ResponseEntity.ok("邮件发送成功");
    }

    @RequestMapping("/mailByThy")
    public String sendMail() throws FileNotFoundException {
        MailVo mailVo = new MailVo();
        mailVo.setName("test-img");
        mailVo.setFile(ResourceUtils.getFile("classpath:static/img/test.png"));
        List<MailVo> list = new ArrayList<>();
        list.add(mailVo);

        Map<String, Object> valueMap = new HashMap<>();
        valueMap.put("to", new String[]{"你自己的QQ邮箱"});
        valueMap.put("title", "测试邮件标题111");
        valueMap.put("content", "测试邮件内容222");


        MailVo fileVo = new MailVo();
        fileVo.setName("thymeleaf.txt");
        fileVo.setFile(ResourceUtils.getFile("classpath:static/img/msg.txt"));
        List<MailVo> athVos = new ArrayList<>();
        athVos.add(fileVo);

        // 调用发送邮件的方法
        mailService.sendSimpleMail(valueMap, list, athVos);
        return "使用thymeleaf模板发送邮件成功~~~~~";
    }

    @RequestMapping("/mailByVm")
    public String sendMailByVm() throws FileNotFoundException {
        long start = System.currentTimeMillis();
        Map<String, Object> map = new HashMap<>();
        map.put("url", UUID.randomUUID());
        map.put("content", "test");
        map.put("date", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date()));
        map.put("imgPath", ResourceUtils.getFile("classpath:static/img/test.png"));

        map.put("pdf", ResourceUtils.getFile("classpath:static/xxxx.pdf"));
        // 调用发送邮件的方法
        mailService.setMailByVm(map);

        return "使用velocity模板发送邮件成功~~~~~用时:" + (System.currentTimeMillis() - start) + "毫秒";
    }

}

4.ContentTypeEnum.PDF.getCentType()请参考我的另一篇博客:https://blog.****.net/l244112311/article/details/106931863,实在不想去,改为application/pdf即可,DateUtils请参考:https://gitee.com/y_project/RuoYi/blob/master/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java,其他的应该没啥了。有需要的可以参照上面的代码自己去尝试了。

上一篇:关于ActiveMQ的几种集群配置


下一篇:JAVA中集成Freemarker生成静态html