java 实现发送邮件(带附件)
需求说明:
通过WinMail Server 实现内网邮件的发送,并且邮件中带还有附件信息
实现步骤
1.引入依赖包
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
2.邮箱配置(项目中集成了nacos,配置文件在nacos上获取)
2.1 配置
mail:
send:
user: 登录用户名
pd: 登录用户密码(明文即可)
address: xxxxx@test.com
senderName: 管理员
smtp:
host: 192.168.X.XX
auth: true
debug: false
transport:
protocol: smtp
2.2 读取配置
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
@Data
@Api(value = "邮件配置", tags = "邮件配置")
public class EmailConfig {
@ApiModelProperty("设置发件人的SMTP服务器地址")
public static String mailHost ;
@ApiModelProperty("发件人账户名")
public static String sendUser ;
@ApiModelProperty("发件人账户密码")
public static String sendPd ;
@ApiModelProperty("发件人地址")
public static String senderAddress;
@ApiModelProperty("发件人姓名")
public static String senderName;
@ApiModelProperty("设置传输协议")
public static String transportProtocol ;
@ApiModelProperty("设置用户的认证方式")
public static String smtpAuth ;
@ApiModelProperty("设置调试信息在控制台打印出来")
public static Boolean debug;
@Value("${mail.smtp.host}")
public void setMailHost(String mailHost) {
EmailConfig.mailHost = mailHost;
}
@Value("${mail.send.user}")
public void setSendUser(String sendUser) {
EmailConfig.sendUser = sendUser;
}
@Value("${mail.send.pd}")
public void setSendPd(String sendPd) {
EmailConfig.sendPd = sendPd;
}
@Value("${mail.send.address}")
public void setSenderAddress(String senderAddress) {
EmailConfig.senderAddress = senderAddress;
}
@Value("${mail.send.senderName}")
public void setSenderName(String senderName) {
EmailConfig.senderName = senderName;
}
@Value("${mail.transport.protocol}")
public void setTransportProtocol(String transportProtocol) {
EmailConfig.transportProtocol = transportProtocol;
}
@Value("${mail.smtp.auth}")
public void setSmtpAuth(String smtpAuth) {
EmailConfig.smtpAuth = smtpAuth;
}
@Value("${mail.smtp.debug}")
public void setDebug(Boolean debug) {
EmailConfig.debug = debug;
}
}
3.代码中实体类
NotifyAlarmBO.java
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NonNull;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 通知告警
* @author
*/
@Data
@Api(value = "通知告警", tags = "通知告警")
public class NotifyAlarmBO implements Serializable {
private static final long serialVersionUID = -2494061479403692809L;
@ApiModelProperty("发送人 操作员账号")
private String sendOperatorId;
@ApiModelProperty(value = "接收人员类型, 1 操作员账号 表S_OPERATOR_ACCOUNT中 OPERATOR_ID 字段值" +
"2 角色 表 S_ROLE 中 ROLE_ID 字段值 ; 3 邮箱地址(内网邮箱地址)" , required = true)
private String receiveType;
@ApiModelProperty("接收人, 多个用逗号 , 分隔")
private String toUser;
@ApiModelProperty("抄送人, 多个用逗号 , 分隔")
private String ccUser;
@ApiModelProperty("密送人, 多个用逗号 , 分隔")
private String bccUser;
@ApiModelProperty(value = "标题", required = true)
private String topic;
@ApiModelProperty(value = "正文内容", required = true)
private String mailText;
@ApiModelProperty("发送时间")
private String sendTime;
@ApiModelProperty("消息类型(发送消息方式: msgNtceMode) 1 短信, 2 微信, 3 邮件 目前只支持邮件")
private String messageType;
@ApiModelProperty("邮件附件信息,多个用逗号分隔")
private String fileIds;
}
MailFile.java
import lombok.Data;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
/**
* 邮件附件
*/
@Data
public class MailFile {
private String fileName;
private InputStream inputStream;
}
MailCommon.java
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* @author
*/
@Data
public class MailCommon{
@ApiModelProperty("邮件主题")
private String topic;
@ApiModelProperty("邮件正文类型 (html 或者 纯文本)")
private String mailType;
@ApiModelProperty("邮件正文")
private String mailText;
@ApiModelProperty("发送人邮箱地址")
private String sendAddres;
@ApiModelProperty("发送人名称")
private String sendName;
@ApiModelProperty("接收人")
private List<MailUser> toUser;
@ApiModelProperty("抄送人")
private List<MailUser> ccUser;
@ApiModelProperty("密送人")
private List<MailUser> bccUser;
@ApiModelProperty("发送时间")
private String sendTime;
@ApiModelProperty("附件信息")
private List<MailFile> fileList;
}
MailUser.java
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @author
*/
@Data
@Accessors(chain = true)
public class MailUser implements Serializable {
private static final long serialVersionUID = 5387796169093723935L;
@ApiModelProperty("邮箱地址")
private String emailAddr;
@ApiModelProperty("邮箱所属人名称")
private String emailName;
}
4.发送邮件接口业务处理
NotifyAlarmController.java
/**
* 通知告警
* @author
*/
@Api(value = "通知告警" , tags = "通知告警")
@Slf4j
@RestController
@RequestMapping("/notify-alarm")
public class NotifyAlarmController {
private static final String version = "v1";
@Autowired
private NotifyAlarmService notifyAlarmService;
/**
* 发送通知告警消息
* @param notifyAlarmBO
* @return
*/
@ApiOperation(value = "发送通知告警消息")
@PostMapping("/sendNotifyAlarmMessage/" + version)
public R sendNotifyAlarmMessage(@RequestBody NotifyAlarmBO notifyAlarmBO){
log.info("发送通知告警消息接收参数: {}", notifyAlarmDTO);
R messageResult = notifyAlarmService.sendNotifyAlarmMessage(notifyAlarmBO);
log.info("发送通知告警消息返回结果: {}", messageResult);
return messageResult;
}
}
NotifyAlarmServiceImpl.java
/**
* @author
*/
@Service
@Slf4j
public class NotifyAlarmServiceImpl implements NotifyAlarmService {
String sqlId = "com.sgcc.ami.ms0866.mail.mapper.OperatorAccountMapper.";
@Autowired
private FileInfoRemoteService fileInfoRemoteService;
/**
* 发送通知告警信息 OperatorAccount
* @param notifyAlarmBO
* @return
*/
@Override
public R sendNotifyAlarmMessage(NotifyAlarmBO notifyAlarmBO) {
log.info("发送邮件信息: {}", notifyAlarmBO);
String receiveType = notifyAlarmBO.getReceiveType();
MailCommon mailCommon = new MailCommon();
// 设置发送时间
mailCommon.setSendTime(notifyAlarmBO.getSendTime());
// 设置发送topic
mailCommon.setTopic(notifyAlarmBO.getTopic());
mailCommon.setMailText(notifyAlarmBO.getMailText());
switch (receiveType){
case "1":
this.setMailInfoByOperator(notifyAlarmBO, mailCommon);
break;
case "2":
this.setMailInfoByRole(notifyAlarmBO, mailCommon);
break;
case "3":
this.setMailInfoByMailAddress(notifyAlarmBO, mailCommon);
break;
default:
log.info("无此类型处理方法");
}
// 处理附件信息
if (StringUtil.isNotBlank(notifyAlarmBO.getFileIds())){
String[] fileIds = notifyAlarmBO.getFileIds().split(",");
List<MailFile> fileList = new ArrayList<>();
for (int i = 0; i < fileIds.length; i++) {
MailFile mailFile = new MailFile();
// 获取附件信息
FileInfoDTO data = fileInfoRemoteService.viewFileInfo(Long.valueOf(fileIds[i])).getData();
log.info("附件信息: {}", data);
InputStream inputStream = MinioFile.downloadInputStream(Long.valueOf(fileIds[i]));
if (data != null){
mailFile.setFileName(data.getFullName());
}
mailFile.setInputStream(inputStream);
fileList.add(mailFile);
}
mailCommon.setFileList(fileList);
}
try {
// 发送邮件
EmailUtil.sendEmail(mailCommon);
} catch (Exception e) {
log.error("发送邮件事变: {}", e.getMessage());
return R.fail(e.getMessage());
}
return R.success("邮件发送成功");
}
/**
* 设置类型为 操作员账号的邮件信息
* @param notifyAlarmBO
* @param mailCommon
*/
private void setMailInfoByOperator(NotifyAlarmBO notifyAlarmBO, MailCommon mailCommon){
// 发送人信息
Map<String, Object> param = new HashMap<>();
param.put("operatorId", notifyAlarmBO.getSendOperatorId());
OperatorAccountPO sendOperator = XXXXXXXX;// 获取发送人信息
mailCommon.setSendAddres(sendOperator.getEmail());// 邮箱地址
mailCommon.setSendName(sendOperator.getName());// 发送人
// 接收人
if (StringUtil.isNotBlank(notifyAlarmBO.getToUser())){
String[] operatorIds = notifyAlarmBO.getToUser().split(",");
List<MailUser> toUser = new ArrayList<>();
for (int i = 0; i < operatorIds.length; i++) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("operatorId", operatorIds[i]);
OperatorAccountPO toOperator = XXXXXXXX; // 获取接收人信息
MailUser mailUser = new MailUser();
mailUser.setEmailAddr(toOperator.getEmail()).setEmailName(toOperator.getName());
toUser.add(mailUser);
}
mailCommon.setToUser(toUser);
log.info("邮件接收人: {}", toUser);
}
// 抄送人
if (StringUtil.isNotBlank(notifyAlarmBO.getCcUser())){
String[] operatorIds = notifyAlarmBO.getCcUser().split(",");
List<MailUser> ccUser = new ArrayList<>();
for (int i = 0; i < operatorIds.length; i++) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("operatorId", operatorIds[i]);
OperatorAccountPO toOperator =XXXXXXXX; // 获取抄送人信息
MailUser mailUser = new MailUser();
mailUser.setEmailAddr(toOperator.getEmail()).setEmailName(toOperator.getName());
ccUser.add(mailUser);
}
mailCommon.setCcUser(ccUser);
log.info("邮件抄送人: {}", ccUser);
}
// 密送人
if (StringUtil.isNotBlank(notifyAlarmBO.getBccUser())){
String[] operatorIds = notifyAlarmBO.getBccUser().split(",");
List<MailUser> bccUser = new ArrayList<>();
for (int i = 0; i < operatorIds.length; i++) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("operatorId", operatorIds[i]);
OperatorAccountPO toOperator =XXXXXXXX; // 获取密送人信息
MailUser mailUser = new MailUser();
mailUser.setEmailAddr(toOperator.getEmail()).setEmailName(toOperator.getName());
bccUser.add(mailUser);
}
mailCommon.setBccUser(bccUser);
log.info("邮件密送人: {}", bccUser);
}
}
/**
* 设置类型为 角色的邮件信息
* @param notifyAlarmBO
* @param mailCommon
*/
private void setMailInfoByRole(NotifyAlarmBO notifyAlarmBO, MailCommon mailCommon){
// 发送人信息
Map<String, Object> param = new HashMap<>();
param.put("operatorId", notifyAlarmBO.getSendOperatorId());
OperatorAccountPO sendOperator =XXXXXXXX; // 获取发送人信息
mailCommon.setSendAddres(sendOperator.getEmail());
mailCommon.setSendName(sendOperator.getName());
// 接收人
if (StringUtil.isNotBlank(notifyAlarmBO.getToUser())){
String[] roleIds = notifyAlarmBO.getToUser().split(",");
List<MailUser> toUser = new ArrayList<>();
for (int i = 0; i < roleIds.length; i++) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("roleId", roleIds[i]);
List<OperatorAccountPO> accountPOS =XXXXXXXX; // 获取接收人信息
List<MailUser> collect = accountPOS.stream().map(accountPO -> {
MailUser mailUser = new MailUser();
mailUser.setEmailAddr(accountPO.getEmail()).setEmailName(accountPO.getName());
return mailUser;
}).distinct().collect(Collectors.toList());
collect.stream().forEach(mailStr -> {
toUser.add(mailStr);
});
}
mailCommon.setToUser(toUser);
log.info("邮件接收人: {}", toUser);
}
// 抄送人
if (StringUtil.isNotBlank(notifyAlarmBO.getCcUser())){
String[] roleIds = notifyAlarmBO.getCcUser().split(",");
List<MailUser> ccUser = new ArrayList<>();
for (int i = 0; i < roleIds.length; i++) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("roleId", roleIds[i]);
List<OperatorAccountPO> accountPOS =XXXXXXXX; // 获取抄送人信息
List<MailUser> collect = accountPOS.stream().map(accountPO -> {
MailUser mailUser = new MailUser();
mailUser.setEmailAddr(accountPO.getEmail()).setEmailName(accountPO.getName());
return mailUser;
}).distinct().collect(Collectors.toList());
collect.stream().forEach(mailStr -> {
ccUser.add(mailStr);
});
}
mailCommon.setCcUser(ccUser);
log.info("邮件抄送人: {}", ccUser);
}
// 密送人
if (StringUtil.isNotBlank(notifyAlarmBO.getBccUser())){
String[] roleIds = notifyAlarmBO.getBccUser().split(",");
List<MailUser> bccUser = new ArrayList<>();
for (int i = 0; i < roleIds.length; i++) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("roleId", roleIds[i]);
List<OperatorAccountPO> accountPOS =XXXXXXXX; // 获取密送人信息
List<MailUser> collect = accountPOS.stream().map(accountPO -> {
MailUser mailUser = new MailUser();
mailUser.setEmailAddr(accountPO.getEmail()).setEmailName(accountPO.getName());
return mailUser;
}).distinct().collect(Collectors.toList());
collect.stream().forEach(mailStr -> {
bccUser.add(mailStr);
});
}
mailCommon.setBccUser(bccUser);
log.info("邮件密送人: {}", bccUser);
}
}
/**
* 设置类型为 邮箱的邮件信息
* @param notifyAlarmBO
* @param mailCommon
*/
private void setMailInfoByMailAddress(NotifyAlarmBO notifyAlarmBO, MailCommon mailCommon){
// 发送人信息
Map<String, Object> param = new HashMap<>();
param.put("operatorId", notifyAlarmBO.getSendOperatorId());
OperatorAccountPO sendOperator =XXXXXXXX; // 获取发送人信息
if (sendOperator != null && StringUtil.isNotBlank(sendOperator.getEmail())){
mailCommon.setSendAddres(sendOperator.getEmail());
mailCommon.setSendName(sendOperator.getName());
} else {
mailCommon.setSendAddres(EmailConfig.senderAddress);
mailCommon.setSendName(EmailConfig.senderName);
}
// 接收人
if (StringUtil.isNotBlank(notifyAlarmBO.getToUser())){
List<String> collect = Arrays.stream(notifyAlarmBO.getToUser().split(",")).collect(Collectors.toList());
log.info("邮件接收人: {}", collect);
List<MailUser> toUser = new ArrayList<>();
collect.stream().forEach(emailAddr -> {
MailUser mailUser = new MailUser();
mailUser.setEmailAddr(emailAddr).setEmailName(emailAddr.split("@")[0]);
toUser.add(mailUser);
});
mailCommon.setToUser(toUser);
}
// 抄送人
if (StringUtil.isNotBlank(notifyAlarmBO.getCcUser())){
List<String> collect = Arrays.stream(notifyAlarmBO.getCcUser().split(",")).collect(Collectors.toList());
log.info("邮件抄送人: {}", collect);
List<MailUser> ccUser = new ArrayList<>();
collect.stream().forEach(emailAddr -> {
MailUser mailUser = new MailUser();
mailUser.setEmailAddr(emailAddr).setEmailName(emailAddr.split("@")[0]);
ccUser.add(mailUser);
});
mailCommon.setCcUser(ccUser);
}
// 密送人
if (StringUtil.isNotBlank(notifyAlarmBO.getBccUser())){
List<String> collect = Arrays.stream(notifyAlarmBO.getBccUser().split(",")).collect(Collectors.toList());
log.info("邮件密送人: {}", collect);
List<MailUser> bccUser = new ArrayList<>();
collect.stream().forEach(emailAddr -> {
MailUser mailUser = new MailUser();
mailUser.setEmailAddr(emailAddr).setEmailName(emailAddr.split("@")[0]);
bccUser.add(mailUser);
});
mailCommon.setBccUser(bccUser);
}
}
}
5.发送邮件工具类EmailUtil.java
EmailUtil.java
/**
* 邮件
*
* @author
*/
@Slf4j
public class EmailUtil {
/**
*
* @param mailCommon
* @throws Exception
*/
public static void sendEmail(MailCommon mailCommon) throws Exception{
//1、连接邮件服务器的参数配置
Properties props = new Properties();
//设置用户的认证方式
props.setProperty("mail.smtp.auth", EmailConfig.smtpAuth);
//设置传输协议
props.setProperty("mail.transport.protocol", EmailConfig.transportProtocol);
//设置发件人的SMTP服务器地址
props.setProperty("mail.smtp.host", EmailConfig.mailHost);
//2、创建定义整个应用程序所需的环境信息的 Session 对象
Session session = Session.getInstance(props);
//设置调试信息在控制台打印出来
session.setDebug(EmailConfig.debug);
//3、创建邮件的实例对象
MimeMessage message = getMimeMessage(session, mailCommon);
//4、根据session对象获取邮件传输对象Transport
Transport transport = session.getTransport();
//设置发件人的账户名和密码
transport.connect(EmailConfig.sendUser, EmailConfig.sendPd);
//发送邮件,并发送到所有收件人地址,message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
transport.sendMessage(message, message.getAllRecipients());
//5、关闭邮件连接
transport.close();
}
/**
* 获得创建一封邮件的实例对象
* @param session
* @return
*/
public static MimeMessage getMimeMessage(Session session, MailCommon mailCommon) throws Exception{
// 1.创建一封邮件的实例对象
MimeMessage message = new MimeMessage(session);
// 2.设置发件人地址
if (mailCommon.getSendAddres() == null || mailCommon.getSendAddres().length()< 1){
message.setFrom(new InternetAddress(EmailConfig.senderAddress, EmailConfig.senderName, "UTF-8"));
} else {
message.setFrom(new InternetAddress(mailCommon.getSendAddres(), mailCommon.getSendName(), "UTF-8"));
}
/**
* 3. 设置收件人地址(可以增加多个收件人、抄送、密送),即下面这一行代码书写多行
* MimeMessage.RecipientType.TO:发送
* MimeMessage.RecipientType.CC:抄送
* MimeMessage.RecipientType.BCC:密送
*/
message.setRecipients(Message.RecipientType.TO, getAddress(mailCommon.getToUser()));
// 判断是否需要设置抄送人
if (mailCommon.getCcUser() != null && mailCommon.getCcUser().size() > 0){
message.setRecipients(Message.RecipientType.CC, getAddress(mailCommon.getCcUser()));
}
// 判断是否需要设置密送人
if (mailCommon.getBccUser() != null && mailCommon.getBccUser().size() > 0){
message.setRecipients(Message.RecipientType.BCC, getAddress(mailCommon.getBccUser()));
}
// 4.设置邮件主题
message.setSubject(mailCommon.getTopic(),"UTF-8");
// 5. 设置邮件正文
// 设置邮件正文(邮件文本消息)
MimeBodyPart textBody = new MimeBodyPart();
textBody.setContent(mailCommon.getMailText(), "text/html;charset=gbk");
//拼装邮件正文内容
MimeMultipart textMultipart = new MimeMultipart();
textMultipart.addBodyPart(textBody);
// 1.文本和图片内嵌成功!
textMultipart.setSubType("related");
// 拼装正文内容
MimeMultipart mimeMultipart = new MimeMultipart();
// 将拼装好的正文内容设置为主体
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(textMultipart);
mimeMultipart.addBodyPart(contentText);
message.setContent(mimeMultipart);
// 6. 处理邮件附件
if (mailCommon.getFileList() != null && mailCommon.getFileList().size()> 0){
for (MailFile mailFile : mailCommon.getFileList()){
MimeBodyPart mimeBodyPart = new MimeBodyPart();
/**
* 此处附件是在minio文件服务器上存储,此处拿到的是文件的输入流inpu* tStream,需特殊处理后才能放在DataHandler中InputStreamDataSource
* 如果是直接在本地获取文件可以直接使用FileDataSource
* DataHandler handler = new DataHandler(new FileDataSource("文件存储路径,例如: D:\\file\\111.doc");
*/
DataHandler handler = new DataHandler(new InputStreamDataSource(mailFile.getInputStream(), mailFile.getFileName()));
mimeBodyPart.setDataHandler(handler);
//对文件名进行编码,防止出现乱码
String fileName = MimeUtility.encodeWord(mailFile.getFileName(), "utf-8", "B");
mimeBodyPart.setFileName(fileName);
mimeMultipart.addBodyPart(mimeBodyPart);
}
}
// 7.设置邮件的发送时间,默认立即发送
if (mailCommon.getSendTime() != null && mailCommon.getSendTime().length() > 0){
// 设置定时发送时间
Date sendDate = DateUtil.parse(mailCommon.getSendTime(), DateUtil.PATTERN_DATETIME);
message.setSentDate(sendDate);
} else {
message.setSentDate(new Date());
}
// 7. 保存设置
message.saveChanges();
return message;
}
public static InternetAddress[] getAddress(List<MailUser> userList){
if (userList != null && userList.size() > 0){
InternetAddress[] internetAddresses = new InternetAddress[userList.size()];
for (int i = 0; i < userList.size(); i++) {
MailUser mailUser = userList.get(i);
try {
internetAddresses[i] = new InternetAddress(mailUser.getEmailAddr(), mailUser.getEmailName(), "UTF-8");
} catch (UnsupportedEncodingException e) {
log.error("发送邮件设计接收人失败: {}", e.getMessage());
}
}
return internetAddresses;
}
return new InternetAddress[0];
}
}
InputStreamDataSource.java
import javax.activation.DataSource;
import javax.activation.MimetypesFileTypeMap;
import java.io.*;
/**
* @author
*/
public class InputStreamDataSource implements DataSource {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private final String name;
public InputStreamDataSource(InputStream inputStream, String name) {
this.name = name;
try {
int nRead;
byte[] data = new byte[16384];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String getContentType() {
return new MimetypesFileTypeMap().getContentType(name);
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(buffer.toByteArray());
}
@Override
public String getName() {
return name;
}
@Override
public OutputStream getOutputStream() throws IOException {
throw new IOException("Read-only data");
}
}
编码不易,转载请注明出处
相关文章
暂无评论...