需求:
客户需要把查询出来的数据放到excel文档中,并且把附件发送到邮箱。
涉及思路:
1、easypoi技术来写入excel文档;
2、jakarta.mail技术来发送附件邮件;
使用的技术:
poi-4.1.1.jar
easypoi-base-4.3.0.jar
easypoi-annotation-4.3.0.jar
jakarta.mail-1.6.5.jar
代码实现:
1、公共类:
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import org.apache.poi.ss.usermodel.Workbook;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 导出Excel文档工具类
*/
public class PoiExcelUtil {
/**
* excel导出公共接口 支持一文档多sheet页
* @param response
* @param fileName 文件名 格式:测试.xls
* @param sheetsList sheet集合
* 格式如下:
* 每个sheet需要这样写:【Map的key是固定写死的,不用改】
* ExportParams exportParams = new ExportParams(null, "出国备案", ExcelType.HSSF); title标题,sheet页名称,类型【固定就这样写】
* exportMap.put("title", exportParams);
* exportMap.put("entity", SearchRecordRespBean.class); 导出实体类【需要自己写一个】
* exportMap.put("data", recordList); 数据列表,必须是List集合。数组会报错
*
*/
public static void downExcel(HttpServletResponse response, String fileName, List<Map<String, Object>> sheetsList){
// 导出,并获取工作簿
Workbook workbook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.HSSF);
if("xlsx".equals(fileName.substring(fileName.indexOf("."),fileName.length()))){
workbook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.XSSF);
}
//导出Excel
try {
response.setHeader("Content-disposition", "attachment;" + "filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8"));
response.setContentType("application/octet-stream; charset=UTF-8");
workbook.write(response.getOutputStream());
workbook.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static InputStream excelInputStream( String fileName, List<Map<String, Object>> sheetsList) throws IOException {
// 导出,并获取工作簿
Workbook workbook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.HSSF);
if("xlsx".equals(fileName.substring(fileName.indexOf("."),fileName.length()))){
workbook = ExcelExportUtil.exportExcel(sheetsList, ExcelType.XSSF);
}
// 将 Workbook 写入字节数组输出流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
workbook.write(outputStream);
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
return inputStream;
}
public static void responseWorkbook(HttpServletResponse response, String path, List<Map<String, Object>> list, String fileName) {
// 获取模板数据
TemplateExportParams params = new TemplateExportParams(path, 0);
HashMap<String, Object> workbookNeedMap = new HashMap<>();
workbookNeedMap.put("maps", list);
try {
// 导出,并获取工作簿
Workbook workbook = ExcelExportUtil.exportExcel(params, workbookNeedMap);
response.setHeader("Content-disposition", "attachment;" + "filename*=utf-8''" + URLEncoder.encode(fileName, "UTF-8"));
response.setContentType("application/octet-stream; charset=UTF-8");
workbook.write(response.getOutputStream());
workbook.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import java.io.Serializable;
@Data
public class DirectorExcelBean implements Serializable {
/**
*备案号
*/
@Excel(name = "公司名称", needMerge = true, width = 60.0)
private String company;
/**
* 单位名称
*/
@Excel(name = "会议", needMerge = true, width = 100.0)
private String meeting;
}
2、邮件封装类:
import lombok.Data;
import java.io.InputStream;
import java.util.List;
@Data
public class Mail {
/**
* 收件人
*/
private List<String> to;
/**
* 发件人
*/
private String from;
/**
* SMTP主机
*/
private String host;
/**
* 发件人的用户名
*/
private String username;
/**
* 发件人的密码
*/
private String password;
/**
* 邮件主题
*/
private String subject;
/**
* 邮件正文
*/
private String content;
private String attachmentName;
private InputStream attachmentStream;
}
3、整体代码实现:
public void toSendEmailMessage() {
//excel列表的数据
List<DirectorExcelBean> recordList = new ArrayList<>();
List<Map<String, Object>> sheetsList = Lists.newArrayList();
Map<String, Object> exportMap = Maps.newHashMap();
ExportParams exportParams = new ExportParams(null, "未开会公司", ExcelType.HSSF);
exportMap.put("title", exportParams);
exportMap.put("entity", DirectorExcelBean.class);
exportMap.put("data", recordList);
// 加入多sheet配置列表
sheetsList.add(exportMap);
try {
//附件输入流
InputStream inputStream = PoiExcelUtil.excelInputStream("董事会预警.xls", sheetsList);
//给多人发送邮件
List<String> ss = new ArrayList<>();
ss.add("123@qq.com");
//组装数据
sendMail(ss,"邮件标题","邮件内容【有附件,请下载查看】",inputStream,"附件名字.xls");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void sendMail(List<String> emails, String subject, String content, InputStream attachmentStream, String attachmentName) {
Mail mail = new Mail();
mail.setHost("smtp.163.com"); //发件人的邮箱的 SMTP 服务器地址
mail.setUsername("ss@163.com"); // 设置发件人邮箱的用户名
mail.setPassword("*"); // 设置发件人邮箱的密码,需将*号邮箱的授权码
mail.setFrom("ss@163.com"); // 设置发件人的邮箱
mail.setTo(emails); // 设置收件人的邮箱
mail.setSubject(subject); // 设置邮件的主题
mail.setContent(content); // 设置邮件的正文
mail.setAttachmentName(attachmentName);
mail.setAttachmentStream(attachmentStream);
if (mailReady(mail)) { // 发送邮件
System.out.println("发送成功!");
} else {
System.out.println("发送失败!");
}
}
/**
* 获取发送邮件信息
*
* @param mb
*/
public boolean mailReady(Mail mb) {
String host = mb.getHost();
final String username = mb.getUsername();
final String password = mb.getPassword();
String from = mb.getFrom();
List<String> toList = mb.getTo();
String subject = mb.getSubject();
String content = mb.getContent();
InputStream attachmentStream = mb.getAttachmentStream(); // 获取附件流
String attachmentName = mb.getAttachmentName(); // 获取附件名称
Properties props = System.getProperties();
props.put("mail.smtp.host", host); // 设置SMTP的主机
props.put("mail.smtp.auth", "true"); // 需要经过验证
Session session = Session.getInstance(props, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);//接收邮件的用户名和密码
}
});
try {
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
InternetAddress[] address = new InternetAddress().parse(String.join(",",toList));
msg.setRecipients(Message.RecipientType.TO, address);
try {
msg.setSubject(MimeUtility.encodeWord(subject, "UTF-8", "Q"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 创建消息部分
BodyPart messageBodyPart = new MimeBodyPart();
// 填写邮件内容
messageBodyPart.setContent(content, "text/html;charset=UTF-8");
Multipart multipart = new MimeMultipart();
// 添加邮件内容到multipart.
multipart.addBodyPart(messageBodyPart);
// 如果有附件,则添加附件
if (attachmentStream != null && attachmentName != null && !attachmentName.isEmpty()) {
messageBodyPart = new MimeBodyPart();
DataSource source = new ByteArrayDataSource(attachmentStream, "application/octet-stream");
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(MimeUtility.encodeWord(attachmentName));
multipart.addBodyPart(messageBodyPart);
}
msg.setContent(multipart);
msg.setSentDate(new Date());
Transport.send(msg);
} catch (Exception me) {
me.printStackTrace();
return false;
}
return true;
}
借鉴地址:https://blog.youkuaiyun.com/lovewebeye/article/details/107294042
报错解决方案:
javax.mail.AuthenticationFailedException: 535 Error: authentication failed解决办法【邮箱的授权码开启方式】: