Spring Boot使用网易云企业邮箱发送带附件的邮件
前置准备
网易企业邮箱的smtp服务器
可通过https://qiye.163.com/help/client-profile.html查询
授权码
在网易企业邮箱登陆后->左上角设置-> 客户端设置 -> 生成授权密码
依赖
<!-- 发送邮件模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.2</version>
</dependency>
代码实现
使用easyExcel导出为附件(流)
easyExcel填充模板可以阅读easyExcel官方文档:
https://easyexcel.opensource.alibaba.com/docs/current/quickstart/fill
@Override
public void sendEmailAttachment(String billId, String email) {
Map<String,Object> data = new HashMap<>();
// 构建请求数据
buildData(data,billId);
try(InputStream fileInputStream = new ClassPathResource("excel/bill_template.xlsx").getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ) {
ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(fileInputStream).build();
// 填充信息
WriteSheet billSheet = EasyExcel.writerSheet("***").build();
excelWriter.fill(data, billSheet);
// 填充列表数据
if (data.containsKey("****") && data.get("****") instanceof List && !((List<?>) data.get("****")).isEmpty()) {
excelWriter.fill( data.get("****"), billSheet);
}
// 关闭writer
excelWriter.finish();
outputStream.flush();
log.info("文件已生成,包含的导出数据为:{}",data);
// 发送邮件
String subject = "****";
String text = "****";
// 直接使用ByteArrayResource,避免多次转换
InputStreamSource attachmentSource = new ByteArrayResource(outputStream.toByteArray());
emailService.sendEmailWithAttachment(email, subject, text,
"****" + data.get("billNo") + ".xlsx", attachmentSource);
} catch (Exception e) {
log.error("****", e);
throw new BusinessException("发送邮件失败: " + e.getMessage());
}
}
private void buildData(Map<String, Object> data,String billId) {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
EomsBillDetailDTO billDetail = detail(billId);
// 模板中的字段名
data.put("name", billDetail.getName());
// 列表数据
List<Map<String, Object>> itemList = new ArrayList<>();
for(EomsBillExpense billExpense : billDetail.getBillExpenseList()){
Map<String, Object> item = new HashMap<>();
item.put("expenseNo", billExpense.getExpenseNo());
itemList.add(item);
}
data.put("expense", itemList);
}
发送附件
配置文件
# 邮件地址配置
# 邮箱服务器
spring.mail.host=smtphz.qiye.163.com
spring.mail.port=25
# 企业邮箱账号
spring.mail.username=${MAIL_USERNAME:****}
# 授权码
spring.mail.password=${MAIL_PASSWORD:*****}
spring.mail.protocol=smtp
spring.mail.default-encoding=UTF-8
# SMTP 属性配置
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000
spring.mail.properties.mime.charset=UTF-8
spring.mail.properties.default-encoding=UTF-8
/**
* 发送带附件的邮件(带指数重试机制)
* @param to 收件人邮箱地址
* @param subject 邮件主题
* @param text 邮件内容
* @param attachmentName 附件名称
* @param attachmentSource 附件资源
*/
@Override
public void sendEmailWithAttachment(String to, String subject, String text,
String attachmentName, InputStreamSource attachmentSource) {
int retryCount = 0;
while (true) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, StandardCharsets.UTF_8.name());
helper.setFrom(mailProperties.getUsername());
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
// 添加附件
helper.addAttachment(attachmentName, attachmentSource,"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
mailSender.send(message);
log.info("带附件邮件发送成功: {} -> {} (重试次数: {})", mailProperties.getUsername(), to, retryCount);
// 发送成功,直接返回
return;
} catch (Exception e) {
retryCount++;
if (retryCount > MAX_RETRY_TIME) {
log.error("带附件邮件发送失败,已达到最大重试次数({}): {}", MAX_RETRY_TIME, to, e);
throw new BusinessException("邮件发送失败 ");
}
// 计算指数退避延迟时间: 1s, 2s, 4s
long delayMs = BASE_DELAY_MS * (1L << (retryCount - 1));
log.warn("带附件邮件发送失败,将在 {}ms 后进行第 {} 次重试: {}", delayMs, retryCount, to, e);
try {
Thread.sleep(delayMs);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
log.error("重试等待被中断: {}", to, ie);
throw new RuntimeException("邮件发送重试被中断: " + ie.getMessage(), ie);
}
}
}
}
问题
发送的附件打开为乱码
添加附件时,设置contenType
helper.addAttachment(attachmentName, attachmentSource,"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

浙公网安备 33010602011771号