达成的效果:
1、支持添加多个收件人和抄送人;
2、自定义邮件标题;
3、邮件正文有文字和excel表格内容;
4、可以把业务中的数据转成excel并且添加为邮件的附件;
具体如下:(除了第1第2步,可以从后往前看)
1、以网易163邮箱为例,需要到网易邮箱官网申请邮箱账号,作为发邮件的邮箱。然后参照下面的操作:登录网易邮箱后–>设置–>POP3/SMTP/IMAP->开启 IMAP/SMTP服务,然后会生成一个授权码,拷贝记录这个授权码(很重要),后续发邮件的时候需要这个授权码。
2、需要的包(swagger这个包非必须,如果不要的话就把实体类上面的@ApiModelProperty("xxx")去掉)
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.21</version>
</dependency>
<dependency >
<groupId >org.springframework.boot</groupId >
<artifactId >spring-boot-starter-thymeleaf</artifactId >
<version >3.0.11</version >
</dependency >
<!--邮件依赖-->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
3、正文html内容转换
实体类
第一个:
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class HtmlVO {
@ApiModelProperty("收件人名称")
private String emailReceiver;
@ApiModelProperty("邮件正文第一段文字")
private String emailFirstPartTxt;
@ApiModelProperty("数据明细")
List<SendEmaliVo> detail;
}
第二个:
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class SendEmaliVo {
@ApiModelProperty("field_1")
private String field_1;
@ApiModelProperty("时间:yyyy-MM-dd")
private String field_2;
@ApiModelProperty("field_3")
private Long field_3;
@ApiModelProperty("field_4")
private BigDecimal field_4;
@ApiModelProperty("field_5")
private Long field_5;
}
对象转html的工具(这个工具是在最后发邮件的整体流程那个类里面调的):
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
/**
* 把Java对象数据转成html文件。
*/
public class ParseDataToHtmlDataUtils {
/**
* 把数据转成html,后续作为邮件的正文,参照:crm里面的parseThymeleafTemplate()方法写的
*
* @param info html页面要填充的数据
* @param templatePathDir html模板的目录:templates/
* @param postfix 模板后缀:.html
* @param templateName 模板的名字:templateName
* @return 转换后的html
*/
public static String parseDataToHtmlData(Object info, String templatePathDir, String postfix, String templateName) {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix(templatePathDir);
templateResolver.setSuffix(postfix);
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setTemplateMode(TemplateMode.HTML);
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
Context context = new Context();
//传入参数
context.setVariable("info", info);
//解析html
return templateEngine.process(templateName, context);
}
}
html的模板内容如下:
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>xxxx模板</title>
<style>
body{
font-family: 微软雅黑;
font-size:20px;
color:#4d4d4d;
}
.table-wrapper {
width: 100%;
overflow-x: auto;
}
table {
border-top: 1px solid #333;
border-left: 1px solid #333;
border-spacing: 0;
background-color: #fff;
font-size: 14px;
}
table td {
border-bottom: 1px solid #333;
border-right: 1px solid #333;
padding: 5px;
min-width: 120px;
}
.font5 {
color: windowtext;
}
.xl66 {
text-align: left;
}
.custom-font {
font-size: 20px;
font-weight: normal;
}
</style>
</head>
<body>
<h1 class="custom-font" th:text="${info.emailReceiver}"></h1>
<h1 class="custom-font" th:text="${info.emailFirstPartTxt}"></h1>
<div class="table-wrapper">
<table>
<thead>
<tr height="19">
<td class="">表格第一列</td>
<td class="">表格第二列</td>
<td class="">表格第三列</td>
<td class="">表格第四列</td>
<td class="">表格第五列</td>
</tr>
</thead>
<tbody>
<ul th:each="item:${info.detail}">
<tr height="19">
<td class="xl63" th:text="${item.field_1}"></td>
<td class="xl63" th:text="${item.field_2}"></td>
<td class="xl63" th:text="${item.field_3}"></td>
<td class="xl63" th:text="${item.field_4}"></td>
<td class="xl63" th:text="${item.field_5}"></td>
</tr>
</ul>
<!-- <tr height="19">-->
<!-- <td class=""> </td>-->
<!-- <td class=""> </td>-->
<!-- <td class=""> </td>-->
<!-- <td class=""> </td>-->
<!-- <td class=""> </td>-->
<!-- <td class=""> </td>-->
<!-- <td class=""> </td>-->
<!-- <td class="" th:text="${info.xxx}"></td>-->这两列是我业务中表格下面某个金额汇总结果展示的,可以这部分注释的代码删掉即可
<!-- <td class="" th:text="${info.xxx}"></td>-->
<!-- <td class=""> </td>-->
<!-- <td class=""> </td>-->
<!-- <td class=""> </td>-->
<!-- <td class=""> </td>-->
<!-- <td class=""> </td>-->
<!-- </tr>-->
</tbody>
</table>
</div>
</body>
</html>
4、发送邮件
基本类:
package com.goldenstand.cms.util;
import lombok.Data;
import java.util.HashSet;
/**
* 发送邮件的基本信息
*/
@Data
public class SendEmailBaseInfo {
//开启授权码的邮箱
private String smtpSendEmail;
//授权码
private String smtpAuthorizationCode;
//网易163邮箱的SMTP服务器地址
private String smtpUrl;
//发送方名称
private String sendName;
//收件人列表
private HashSet<String> recipientsTO;
//邮件抄送人列表
private HashSet<String> recipientsCC;
//邮件主题
private String emailSubject;
//邮件正文
private String htmlData;
//邮件附件名称
private String attachmentsName;
//邮件附件地址(从发送的服务器上取文件发送)
private String attachmentsUrl;
}
封装的工具类(下面发邮件的时候会调用到这个类的方法):
import com.alibaba.nacos.common.utils.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import javax.activation.DataHandler;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
/**
* 邮件发送信息
*/
@Slf4j
public class SendEmailUtils {
private static String UTF_8 = "UTF-8";
public static void sendEmailWithAttachments(SendEmailBaseInfo baseInfo) {
Properties props = new Properties();// 参数配置
props.put("mail.smtp.ssl.enable", "true");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", baseInfo.getSmtpUrl());
props.put("mail.smtp.port", "465");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.ssl.protocols", "TLSv1.2");
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(baseInfo.getSmtpSendEmail(), baseInfo.getSmtpAuthorizationCode());
}
});
//session.setDebug(true);//设置为debug模式, 可以查看详细的发送日志
MimeMessage message = new MimeMessage(session);
try {
//创建一封邮件
message.setFrom(new InternetAddress(baseInfo.getSmtpSendEmail(), baseInfo.getSendName(), UTF_8));//发件人
ArrayList<InternetAddress> toList = new ArrayList<>();
for (String each : baseInfo.getRecipientsTO()) {
toList.add(new InternetAddress(each));
}
message.setRecipients(MimeMessage.RecipientType.TO, toList.toArray(new InternetAddress[0]));//收件人列表
ArrayList<InternetAddress> ccList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(baseInfo.getRecipientsCC())) {
for (String each : baseInfo.getRecipientsCC()) {
ccList.add(new InternetAddress(each));
}
message.setRecipients(MimeMessage.RecipientType.CC, ccList.toArray(new InternetAddress[0]));//抄送列表
}
message.setSubject(baseInfo.getEmailSubject());//邮件主题
Multipart multipart = new MimeMultipart();
//邮件正文-html
BodyPart textPart = new MimeBodyPart();
textPart.setContent(baseInfo.getHtmlData(), "text/html;charset=utf-8");
multipart.addBodyPart(textPart);
//邮件附件
BodyPart filePart = new MimeBodyPart();
filePart.setFileName(MimeUtility.encodeText(baseInfo.getAttachmentsName(), UTF_8, "B"));
filePart.setDataHandler(new DataHandler(new ByteArrayDataSource(Files.readAllBytes(
Paths.get(baseInfo.getAttachmentsUrl())), "application/octet-stream")));
multipart.addBodyPart(filePart);
//将邮件装入信封
message.setContent(multipart);
Transport.send(message);
} catch (Exception e) {
log.error("send email failed,error:", e);
}
}
}
发送邮件的实现类(所有流程在里开始):
import com.xxxxx.cms.project.statistic.receive.entity.vo.*;
import com.xxxxx.cms.util.ParseDataToHtmlDataUtils;
import com.xxxxx.cms.util.SendEmailBaseInfo;
import com.xxxxx.cms.util.SendEmailUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.*;
@Slf4j
@Service
public class SendEmail {
public static void main(String[] args) {
//1、邮件正文以html格式来发送,html数据转换
HtmlVO htmlVO = new HtmlVO();
htmlVO.setEmailReceiver("邮件正文的称呼");
htmlVO.setEmailFirstPartTxt("邮件正文第一段");
//正文的excel表的实体类(每行)
List<SendEmaliVo> detailList = new ArrayList<>();
//detailList里准备数据的代码自己准备
htmlVO.setDetail(detailList);
//htmlTemplate是一个html模板文件(htmlTemplate.html),放在代码的resources/templates目录下,如下面的截图所示:
String htmlData = ParseDataToHtmlDataUtils.parseDataToHtmlData(htmlVO,"templates/", ".html", "htmlTemplate");
//邮件基本信息封装
SendEmailBaseInfo baseInfo = new SendEmailBaseInfo();
baseInfo.setSmtpUrl("smtp.163.com");
baseInfo.setSmtpSendEmail("前面你在网易注册的邮箱账号如:aaa@163.com");
baseInfo.setSmtpAuthorizationCode("网易邮箱的授权码,就是上一步开启开启 IMAP/SMTP服务服务时得到的授权码");
baseInfo.setSendName("发送邮件时,发送方的名字");
baseInfo.setRecipientsTO(new HashSet<>());//收件人列表 视情况自己加
baseInfo.setRecipientsCC(new HashSet<>());//抄送人列表 视情况自己加
baseInfo.setEmailSubject("邮件标题");
baseInfo.setAttachmentsName("附件名字");
baseInfo.setHtmlData(htmlData);
//ReceiveAccountExcelVo excelVo = new ReceiveAccountExcelVo();
//excelVo.setStaticDetailVOS(staticDetailVOS);
//String excelPath = parseListToExcel(excelVo, "responsible" + eachVo.getTurnoverOwnerId());
baseInfo.setAttachmentsUrl("excelPath");//附件地址,服务器绝对路径,这里业务数据转excel的代码没放这里,可以看看我专栏里的其他文章,如果找不到的话,就百度下其他方法。
//发送邮件
SendEmailUtils.sendEmailWithAttachments(baseInfo);
}
}
5、效果
success!!!