package com.flysand;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.j1cn.bizclient.meta.entity.email.EmailEntity;
import com.j1cn.bizclient.meta.entity.email.EmailInfo;
import com.j1cn.bizclient.meta.entity.email.ReceiveEntity;
import com.j1cn.commons.exception.JyException;
import com.j1cn.commons.utils.StringUtils;
import com.sun.net.ssl.internal.ssl.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.Security;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
/**
* 邮件工具类
*
* @author flysand
**/
public class EmailUtils {
private static final Logger logger = LoggerFactory.getLogger(EmailUtils.class);
private static final String MAIL_SMTP_AUTH = "mail.smtp.auth";
private static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol";
private static final String MAIL_SMTP_HOST = "mail.smtp.host";
private static final String TEXT = "TEXT";
private static final String TEXT_PLAIN = "TEXT/PLAIN";
private static final String TEXT_HTML = "TEXT/HTML";
private static final String INVALID_ADDRESS_MESSAGE = "Invalid Addresses";
public static void sendAttachMail(EmailEntity emailEntity, InputStream is, String excelName) {
logger.debug("发送一封带一个附件的邮件");
//基础校验
if (StringUtils.isBlank(emailEntity.getHost())) {
throw new JyException("发件服务器未设置");
}
if (emailEntity.getPort() == null) {
emailEntity.setPort(25);
}
if (StringUtils.isBlank(emailEntity.getFrom())) {
throw new JyException("发件人未设置");
}
if (StringUtils.isBlank(emailEntity.getPassword())) {
throw new JyException("发件人密码未设置");
}
Properties properties = new Properties();
properties.setProperty(MAIL_SMTP_AUTH, "true");
properties.setProperty(MAIL_TRANSPORT_PROTOCOL, "smtp");
properties.setProperty(MAIL_SMTP_HOST, emailEntity.getHost());
Session session = Session.getDefaultInstance(properties);
session.setDebug(false);
MimeMessage message = new MimeMessage(session);
try {
//设置发件人邮箱
message.setFrom(new InternetAddress(emailEntity.getFrom()));
setReCcList(emailEntity, message);
//设置主题
message.setSubject(emailEntity.getSubject());
//设置中文
message.addHeader("charset", "UTF-8");
//正文
Multipart multipart = new MimeMultipart();
BodyPart bodyPart = new MimeBodyPart();
//设置邮件正文内容
bodyPart.setText(emailEntity.getContent());
//设置正文中文
bodyPart.setHeader("Content-Type", "text/html;charset=UTF-8");
multipart.addBodyPart(bodyPart);
//附件
MimeBodyPart fileBody = new MimeBodyPart();
DataSource source = new ByteArrayDataSource(is, "application/vnd.ms-excel");
fileBody.setDataHandler(new DataHandler(source));
String filename = StringUtils.isBlank(excelName) ? "excel" + FileUtils.EXCEL_SUFFIX : excelName;
fileBody.setFileName(MimeUtility.encodeText(filename));
multipart.addBodyPart(fileBody);
message.setContent(multipart);
message.setSentDate(new Date());
message.saveChanges();
Transport transport = session.getTransport("smtp");
transport.connect(emailEntity.getHost(), emailEntity.getPort(), emailEntity.getFrom(), emailEntity.getPassword());
transport.sendMessage(message, message.getAllRecipients());
transport.close();
} catch (Exception e) {
e.printStackTrace();
throw new JyException("邮件发送失败");
}
}
public static void sendSslAttachMail(EmailEntity emailEntity, InputStream is, String excelName) {
logger.debug("发送一封带一个附件的邮件");
//基础校验
if (StringUtils.isBlank(emailEntity.getHost())) {
throw new JyException("发件服务器未设置");
}
if (emailEntity.getPort() == null) {
emailEntity.setPort(465);
}
if (StringUtils.isBlank(emailEntity.getFrom())) {
throw new JyException("发件人未设置");
}
if (StringUtils.isBlank(emailEntity.getPassword())) {
throw new JyException("发件人密码未设置");
}
//设置SSL连接、邮件配置
Security.addProvider(new Provider());
Properties props = System.getProperties();
props.setProperty("mail.smtp.host", emailEntity.getHost());
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.port", "465");
props.setProperty("mail.smtp.socketFactory.port", "465");
props.setProperty("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(emailEntity.getFrom(), emailEntity.getPassword());
}
});
session.setDebug(false);
MimeMessage message = new MimeMessage(session);
try {
//设置发件人邮箱
message.setFrom(new InternetAddress(emailEntity.getFrom()));
setReCcList(emailEntity, message);
//设置主题
message.setSubject(emailEntity.getSubject());
//设置中文
message.addHeader("charset", "UTF-8");
//正文
Multipart multipart = new MimeMultipart();
BodyPart bodyPart = new MimeBodyPart();
//设置邮件正文内容
bodyPart.setText(emailEntity.getContent());
//设置正文中文
bodyPart.setHeader("Content-Type", "text/html;charset=UTF-8");
multipart.addBodyPart(bodyPart);
//附件
MimeBodyPart fileBody = new MimeBodyPart();
DataSource source = new ByteArrayDataSource(is, "application/vnd.ms-excel");
fileBody.setDataHandler(new DataHandler(source));
String filename = StringUtils.isBlank(excelName) ? "excel" + FileUtils.EXCEL_SUFFIX : excelName;
fileBody.setFileName(MimeUtility.encodeText(filename));
multipart.addBodyPart(fileBody);
message.setContent(multipart);
message.setSentDate(new Date());
message.saveChanges();
Transport transport = session.getTransport("smtp");
transport.connect(emailEntity.getHost(), emailEntity.getPort(), emailEntity.getFrom(), emailEntity.getPassword());
transport.sendMessage(message, message.getAllRecipients());
transport.close();
} catch (SendFailedException se) {
// 判断当前失败信息,如果为地址错误,则过滤无效地址后重发
if (INVALID_ADDRESS_MESSAGE.equals(se.getMessage())) {
Address[] addresses = se.getInvalidAddresses();
List<String> addressList = Lists.newArrayList();
List<String> recipientList = emailEntity.getRecipients();
List<String> ccList = emailEntity.getCcList();
for (Address address : addresses) {
InternetAddress internetAddress = (InternetAddress) address;
if (recipientList.contains(internetAddress.getAddress())) {
recipientList.remove(internetAddress.getAddress());
}
if (ccList.contains(internetAddress.getAddress())) {
ccList.remove(internetAddress.getAddress());
}
addressList.add(internetAddress.getAddress());
}
logger.error("存在不可用邮箱地址:{},过滤后重新发送邮件...", JSON.toJSONString(addressList));
if (CollectionUtils.isEmpty(recipientList)) {
logger.error("不存在有效的邮箱地址,已配置但无效的邮箱地址:{}", JSON.toJSONString(addressList));
throw new JyException("不存在有效的邮箱地址,已配置但无效的邮箱地址:" + JSON.toJSONString(addressList));
}
// 重新发送
emailEntity.setRecipients(new Vector<>(recipientList));
if (!CollectionUtils.isEmpty(ccList)) {
emailEntity.setCcList(new Vector<>(ccList));
}
sendSslAttachMail(emailEntity, is, excelName);
}
} catch (Exception e) {
e.printStackTrace();
throw new JyException("邮件发送失败");
}
}
private static void setReCcList(EmailEntity emailEntity, MimeMessage message) throws MessagingException {
//设置收件人和抄送人
if (!CollectionUtils.isEmpty(emailEntity.getRecipients())) {
Address[] addresses = new Address[emailEntity.getRecipients().size()];
for (int i = 0; i < emailEntity.getRecipients().size(); i++) {
addresses[i] = new InternetAddress(emailEntity.getRecipients().get(i));
}
message.addRecipients(Message.RecipientType.TO, addresses);
}
if (!CollectionUtils.isEmpty(emailEntity.getCcList())) {
Address[] ccList = new Address[emailEntity.getCcList().size()];
for (int i = 0; i < emailEntity.getCcList().size(); i++) {
ccList[i] = new InternetAddress(emailEntity.getCcList().get(i));
}
message.addRecipients(Message.RecipientType.CC, ccList);
}
}
/**
* 发送带多个附件的邮件
*
* @param emailEntity 邮箱参数对象
* @param fileList 附件文件列表
*/
public static void sendMultiAttachEmail(EmailEntity emailEntity, List<File> fileList) {
logger.debug("发送多附件邮件...");
//基础校验
if (StringUtils.isBlank(emailEntity.getHost())) {
throw new JyException("发件服务器未设置");
}
if (emailEntity.getPort() == null) {
emailEntity.setPort(25);
}
if (StringUtils.isBlank(emailEntity.getFrom())) {
throw new JyException("发件人未设置");
}
if (StringUtils.isBlank(emailEntity.getPassword())) {
throw new JyException("发件人密码未设置");
}
Properties properties = new Properties();
properties.setProperty(MAIL_SMTP_AUTH, "true");
properties.setProperty(MAIL_TRANSPORT_PROTOCOL, "smtp");
properties.setProperty(MAIL_SMTP_HOST, emailEntity.getHost());
Session session = Session.getDefaultInstance(properties);
session.setDebug(false);
setEmailMessage(emailEntity, fileList, session);
}
private static void setEmailMessage(EmailEntity emailEntity, List<File> fileList, Session session) {
MimeMessage message = new MimeMessage(session);
try {
//设置发件人邮箱
message.setFrom(new InternetAddress(emailEntity.getFrom()));
//设置收件人和抄送人
setReCcList(emailEntity, message);
//设置主题
message.setSubject(MimeUtility.encodeText(emailEntity.getSubject(), "UTF-8", "B"));
//设置中文
message.addHeader("charset", "UTF-8");
//正文
Multipart multipart = new MimeMultipart();
BodyPart bodyPart = new MimeBodyPart();
//设置邮件正文内容
bodyPart.setText(emailEntity.getContent());
//设置正文中文
bodyPart.setHeader("Content-Type", "text/html;charset=UTF-8");
multipart.addBodyPart(bodyPart);
//附件
for (File file : fileList) {
MimeBodyPart fileBody = new MimeBodyPart();
FileDataSource fileDataSource = new FileDataSource(file);
fileBody.setDataHandler(new DataHandler(fileDataSource));
fileBody.setFileName(MimeUtility.encodeText(file.getName(), "UTF-8", "B"));
multipart.addBodyPart(fileBody);
}
message.setContent(multipart);
message.setSentDate(new Date());
message.saveChanges();
Transport transport = session.getTransport("smtp");
transport.connect(emailEntity.getHost(), emailEntity.getPort(), emailEntity.getFrom(), emailEntity.getPassword());
transport.sendMessage(message, message.getAllRecipients());
transport.close();
} catch (SendFailedException se) {
// 判断当前失败信息,如果为地址错误,则过滤无效地址后重发
if (INVALID_ADDRESS_MESSAGE.equals(se.getMessage())) {
Address[] addresses = se.getInvalidAddresses();
List<String> addressList = Lists.newArrayList();
List<String> recipientList = emailEntity.getRecipients();
List<String> ccList = emailEntity.getCcList();
for (Address address : addresses) {
InternetAddress internetAddress = (InternetAddress) address;
if (recipientList.contains(internetAddress.getAddress())) {
recipientList.remove(internetAddress.getAddress());
}
if (ccList.contains(internetAddress.getAddress())) {
ccList.remove(internetAddress.getAddress());
}
addressList.add(internetAddress.getAddress());
}
logger.error("存在不可用邮箱地址:{},过滤后重新发送邮件...", JSON.toJSONString(addressList));
if (CollectionUtils.isEmpty(recipientList)) {
logger.error("不存在有效的邮箱地址,已配置但无效的邮箱地址:{}", JSON.toJSONString(addressList));
throw new JyException("不存在有效的邮箱地址,已配置但无效的邮箱地址:" + JSON.toJSONString(addressList));
}
// 重新发送
emailEntity.setRecipients(new Vector<>(recipientList));
if (!CollectionUtils.isEmpty(ccList)) {
emailEntity.setCcList(new Vector<>(ccList));
}
setEmailMessage(emailEntity, fileList, session);
}
} catch (Exception e) {
e.printStackTrace();
throw new JyException("邮件发送失败");
}
}
/**
* 发送邮件
*
* @param email 邮件发送参数
* @param fileList 附件列表
* @return 是否发送成功
*/
public static boolean sendEmail(EmailEntity email, List<File> fileList) {
try {
EmailUtils.sendMultiAttachEmail(email, fileList);
logger.info("邮件发送成功");
return true;
} catch (JyException e) {
logger.error("邮件发送失败{}", e.getMessage());
return false;
}
}
/**
* SSL发送邮件 465端口
*
* @param email
* @param fileList
* @return
*/
public static boolean sendSslEmail(EmailEntity email, List<File> fileList) {
logger.info("ssl发送邮件...");
try {
if (email.getPort() == null) {
email.setPort(465);
}
//设置SSL连接、邮件配置
Security.addProvider(new Provider());
Properties props = System.getProperties();
props.setProperty("mail.smtp.host", email.getHost());
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.port", "465");
props.setProperty("mail.smtp.socketFactory.port", "465");
props.setProperty("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(email.getFrom(), email.getPassword());
}
});
session.setDebug(true);
setEmailMessage(email, fileList, session);
logger.info("邮件发送成功");
return true;
} catch (JyException e) {
logger.error("邮件发送失败 - {}", e.getMessage());
return false;
}
}
/**
* 获取当前邮箱的所有邮件 -- 暂不能包含附件
*
* @param receiveEntity
* @return
* @throws Exception
*/
public static List<EmailInfo> receiveAllEmail(ReceiveEntity receiveEntity) throws Exception {
logger.info("收取邮件...");
Folder folder = getInBox(receiveEntity);
// 获得收件箱的邮件列表
Message[] messages = folder.getMessages();
return getReceivedEmailContent(messages);
}
/**
* 获取邮件信息,仅支持纯文本邮件
*
* @param messages
* @return
* @throws MessagingException
* @throws IOException
*/
public static List<EmailInfo> getReceivedEmailContent(Message[] messages) throws Exception {
List<EmailInfo> emailInfoList = Lists.newArrayList();
for (Message message : messages) {
emailInfoList.add(getReceivedEmailContent(message));
}
return emailInfoList;
}
/**
* 获取邮件信息,仅支持除文本邮件
*
* @param message
* @return
* @throws Exception
*/
public static EmailInfo getReceivedEmailContent(Message message) throws Exception {
EmailInfo emailInfo = new EmailInfo();
InternetAddress[] fromAddress = (InternetAddress[]) message.getFrom();
InternetAddress[] recipientAddress = (InternetAddress[]) message.getAllRecipients();
emailInfo.setFrom(fromAddress[0].getAddress());
List<String> recipientList = Lists.newArrayList();
for (InternetAddress recipient : recipientAddress) {
recipientList.add(recipient.getAddress());
}
emailInfo.setRecipient(recipientList);
emailInfo.setSubject(message.getSubject());
if (message.getContentType().contains(TEXT)) {
//纯文本 -- 获取html 不包含图片等其他资源
emailInfo.setContent((String) message.getContent());
} else {
//签名信息中含有图片 -- 暂不处理纯文本和图片 获取html内容
Multipart multipart = (Multipart) message.getContent();
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart bodyPart = multipart.getBodyPart(i);
if (!bodyPart.getContentType().contains(TEXT)) {
Multipart part = (Multipart) bodyPart.getContent();
for (int j = 0; j < part.getCount(); j++) {
BodyPart bodyPart1 = part.getBodyPart(j);
if (bodyPart1.getContentType().contains(TEXT_HTML)) {
emailInfo.setContent(bodyPart1.getContent().toString());
break;
}
}
} else if (bodyPart.getContentType().contains(TEXT_HTML)) {
emailInfo.setContent(bodyPart.getContent().toString());
break;
}
if (StringUtils.isNotBlank(emailInfo.getContent())) {
break;
}
}
}
return emailInfo;
}
/**
* 获取收件箱
*
* @param receiveEntity
* @return
* @throws Exception
*/
public static Folder getInBox(ReceiveEntity receiveEntity) throws Exception {
Properties props = new Properties();
props.setProperty("mail.imap.host", receiveEntity.getHost());
props.put("mail.smtp.auth", true);
props.put("mail.smtps.ssl.protocols", "TSLv1 TSLv1.1 TLSv1.2");
props.put("mail.transport.protocol", "imap");
props.put("mail.smtp.ssl.ciphersuites", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, TLS_DH_anon_WITH_AES_128_GCM_SHA256, TLS_DH_anon_WITH_AES_128_CBC_SHA256, TLS_ECDH_anon_WITH_AES_128_CBC_SHA, TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_DH_anon_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA, TLS_RSA_WITH_NULL_SHA256, TLS_ECDHE_ECDSA_WITH_NULL_SHA, TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_RSA_WITH_NULL_SHA, TLS_ECDH_ECDSA_WITH_NULL_SHA, TLS_ECDH_RSA_WITH_NULL_SHA, TLS_ECDH_anon_WITH_NULL_SHA, SSL_RSA_WITH_NULL_MD5, TLS_KRB5_WITH_3DES_EDE_CBC_SHA, TLS_KRB5_WITH_3DES_EDE_CBC_MD5, TLS_KRB5_WITH_DES_CBC_SHA, TLS_KRB5_WITH_DES_CBC_MD5, TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA, TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5");
// 创建session实例对象
Session session = Session.getInstance(props);
session.setDebug(true);
// 创建IMAP协议的Store对象
Store store = session.getStore("imap");
// 连接邮件服务器
store.connect(receiveEntity.getReceiver(), receiveEntity.getPassword());
// 获得收件箱
Folder folder = store.getFolder("INBOX");
// 以读写模式打开收件箱
folder.open(Folder.READ_WRITE);
return folder;
}
}
javamail邮件工具类(增加465端口发送,收件,无效收件人过滤)
点赞
收藏