【踩坑】
若smtp发送邮件的邮箱平台只有登陆账号及密码而没有授权码,需要写验证类,否则可能出现在本地可以正常发邮件,而到了服务器上则认证不通过。
@Service
public class SaiDaEmailService {
private static final Logger log = LoggerFactory.getLogger(SaiDaEmailService.class);
@Autowired
private SaiDaOutFileService saiDaOutFileService;
/**
* 邮箱相关配置
*/
private static String host;//邮箱服务器
private static String port;//端口号
private static String sendUsername;//发件人邮箱
private static String sendPassword;//发件人密码
private static String sendName;//发件人别名
private static String fileName;//附件文件地址
private static String content;//邮件内容
private static String title;//邮件标题
private static final List<String> toReceiverList = new ArrayList<>();//收件人邮箱
private static final List<String> copyReceiverList = new ArrayList<>();//抄送人邮箱
/**
* @Description 赛达发送邮件
* @Param
**/
public void sendEmail() {
try {
log.info("sendEmail() - send email start!");
//若无配置数据,取数
if (StringUtils.isEmpty(host)) {
getConfigInfo();
}
//配置smtp
Properties props = System.getProperties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", port);
props.put("mail.smtp.connectiontimeout", 10000);
props.put("mail.smtp.timeout", 30000);
// 邮箱设置SSL加密
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
props.put("mail.smtp.ssl.enable", "true");
props.put("mail.smtp.ssl.socketFactory", sf);
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
//创建定义整个应用程序所需的环境信息的 Session 对象
Authenticator auth = new PopupAuthenticator(sendUsername, sendPassword);
Session session = Session.getInstance(props, auth);
session.setDebug(true);
//创建邮件,传入session对象
MimeMessage mime = complexEmail(session);
if (mime == null) {
log.warn("sendEmail() - email content is null, send fail !");
return;
}
//通过session获取transport对象
SMTPTransport trans = (SMTPTransport) session.getTransport("smtp");
//通过transport对象邮箱用户名和授权码连接邮箱服务器
trans.connect(host, sendUsername, sendPassword);
//发送邮件
trans.sendMessage(mime, mime.getAllRecipients());
//关闭链接
trans.close();
log.info("sendEmail() - send email end !");
} catch (Exception e) {
log.warn("sendEmail() - send email error, " + e);
}
}
/**
* @return MimeMessage
* @Description 处理邮件信息
* @Param session
**/
private MimeMessage complexEmail(Session session) {
try {
log.info("complexEmail() - complex email start !");
//消息的固定信息
MimeMessage mimeMessage = new MimeMessage(session);
//发件人
mimeMessage.setFrom(new InternetAddress(sendUsername, sendName, "utf-8"));
//收件人
// 添加收件人
if (toReceiverList.size() > 0) {
mimeMessage.setRecipients(Message.RecipientType.TO, getInternetAddress(toReceiverList));
} else {
log.warn("complexEmail() - receiver is null !");
return null;
}
// 添加抄送人
if (copyReceiverList.size() > 0) {
mimeMessage.setRecipients(Message.RecipientType.CC, getInternetAddress(copyReceiverList));
}
//设置赛达月份
Calendar cal = Calendar.getInstance();
String date = cal.get(Calendar.YEAR) + "年" + cal.get(Calendar.MONTH);
//邮件标题
title = title.replaceAll("X", date);
mimeMessage.setSubject(title);
//准备文本
MimeBodyPart text = new MimeBodyPart();
content = content.replaceAll("X", date);
text.setContent(content, SaiDaGlobal.CONTENT_TYPE);
//附件
ByteArrayOutputStream os = saiDaOutFileService.outFileFromEmail();
if (os == null) {
log.warn("complexEmail() - saiDa excel data is null !");
return null;
}
DataSource source = new ByteArrayDataSource(os.toByteArray(), SaiDaGlobal.SOURCE_TYPE);
MimeBodyPart appendix = new MimeBodyPart();
appendix.setDataHandler(new DataHandler(source));
fileName = fileName.replaceAll("X", date);
appendix.setFileName(MimeUtility.encodeText(fileName));
//拼装邮件正文
MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(text);
mimeMultipart.setSubType("related");
//将拼装好的正文内容设置为主体
MimeBodyPart contentText = new MimeBodyPart();
contentText.setContent(mimeMultipart);
//拼接附件
MimeMultipart allFile = new MimeMultipart();
allFile.addBodyPart(appendix);//附件
allFile.addBodyPart(contentText);//正文
allFile.setSubType("mixed"); //正文和附件都存在邮件中,所有类型设置为mixed
//放到Message消息中
mimeMessage.setContent(allFile);
//保存修改
mimeMessage.saveChanges();
log.info("complexEmail() - complex email end !");
return mimeMessage;
} catch (MessagingException | UnsupportedEncodingException e) {
log.warn("complexEmail() - complex email error, " + e);
return null;
}
}
/**
* @Description 获取邮件相关配置信息
* @Param
**/
private static void getConfigInfo() {
try {
log.info("getConfigInfo() - get email config start!");
//从配置文件中得到
StringBuilder resStr = new StringBuilder();
ResourceBundle rb = ConfigUtil.getPropertiesConfig(SaiDaGlobal.EMAIL_CONFIG_PATH);
host = rb.getString("mail.host");
port = rb.getString("mail.port");
sendUsername = rb.getString("send.username");
sendPassword = rb.getString("send.password");
sendName = rb.getString("send.alias");
fileName = rb.getString("mail.file.name");
content = rb.getString("mail.content");
title = rb.getString("mail.title");
resStr.append("host = ").append(host)
.append("host = ").append(port)
.append("sendUsername = ").append(sendUsername)
.append("sendPassword = ").append(sendPassword)
.append("sendName = ").append(sendName)
.append("fileName = ").append(fileName)
.append("content = ").append(content)
.append("title = ").append(title);
//得到全部的收件人
int toReceiverCount = 1;
while (!StringUtils.isEmpty(rb.getString("to.username" + toReceiverCount))) {
if (!toReceiverList.contains(rb.getString("to.username" + toReceiverCount))) {
toReceiverList.add(rb.getString("to.username" + toReceiverCount));
resStr.append("toReceiver" + toReceiverCount + " = ").append(rb.getString("to.username" + toReceiverCount));
}
toReceiverCount++;
}
//得到全部的抄送人
int copyReceiverCount = 1;
while (!StringUtils.isEmpty(rb.getString("copy.username" + copyReceiverCount))) {
if (!toReceiverList.contains(rb.getString("copy.username" + copyReceiverCount))) {
toReceiverList.add(rb.getString("copy.username" + copyReceiverCount));
resStr.append("copyReceiver" + copyReceiverCount + " = ").append(rb.getString("copy.username" + copyReceiverCount));
}
copyReceiverCount++;
}
log.info("getConfigInfo() - get email config end, " + resStr);
} catch (Exception e) {
log.warn("getConfigInfo() - get email config error, " + e);
}
}
/**
* @return InternetAddress[]
* @Description 处理收件人、抄送人格式
* @Param List<String>
**/
private static InternetAddress[] getInternetAddress(List<String> list) {
int len = list.size();
if (len == 0) {
return null;
}
InternetAddress[] internetAddresses = new InternetAddress[len];
for (int i = 0; i < len; i++) {
try {
internetAddresses[i] = new InternetAddress(list.get(i));
} catch (AddressException e) {
e.printStackTrace();
}
}
return internetAddresses;
}
}
/**
* 邮箱验证类
* @author Huangyu
* @date 2021/8/6
*/
public class PopupAuthenticator extends Authenticator {
private String username;
private String password;
public PopupAuthenticator(String username, String password) {
this.username = username;
this.password = password;
}
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(this.username, this.password);
}
}