工具类
package com.morning.star.pt.common.component;
import com.morning.star.exception.CODE;
import com.morning.star.exception.MorningStarException;
import com.morning.star.pt.common.entity.EmailAttachmentVo;
import com.morning.star.pt.common.entity.EmailInfoVo;
import com.morning.star.pt.common.entity.MailAccount;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
/**
* 邮件发送工具类
*
*/
public class EmailUtils {
private static final String MAIL_SMTP_HOST = "smtp.exmail.qq.com";
private static final String MAIL_SMTP_PORT = "465";
private static Logger logger = LoggerFactory.getLogger(EmailUtils.class);
public static boolean sendMail(EmailInfoVo mailInfo) {
try {
sendMailWithEx(mailInfo);
}
catch (Exception ex) {
logger.warn("发送邮件时出现异常:{}", ex);
return false;
}
return true;
}
public static void sendMailWithEx(EmailInfoVo mailInfo) {
checkParams(mailInfo);
logger.info("邮件发送参数: 主题 [{}],发件人 [{}],密码 [{}],收件人 [{}],发件人昵称 [{}],smtpServer [{}],smtpPort [{}],邮件内容 [{}],附件个数 [{}]",
new Object[]{mailInfo.getSubject(), mailInfo.getUserName(), mailInfo.getPassword(),
Arrays.asList(mailInfo.getTos()), mailInfo.getSendName(),
mailInfo.getSmtpServer(), mailInfo.getSmtpPort(),
mailInfo.getContent(),
mailInfo.getAttachmentList() != null ? mailInfo.getAttachmentList().size() : 0}
);
mailInfo.setFrom(mailInfo.getUserName());
if (StringUtils.isBlank(mailInfo.getSendName())) {
mailInfo.setSendName("技术部智能机器人");
}
MailAccount account = new MailAccount(mailInfo.getUserName(), mailInfo.getPassword(),
StringUtils.isBlank(mailInfo.getSmtpServer()) ? MAIL_SMTP_HOST : mailInfo.getSmtpServer(),
StringUtils.isBlank(mailInfo.getSmtpPort()) ? MAIL_SMTP_PORT : mailInfo.getSmtpPort(),
true);
try {
sendMail(mailInfo, account, false);
} catch (UnsupportedEncodingException e) {
logger.error("邮件发送出错:", e);
throw new MorningStarException(new CODE(CODE.FAIL.getIndex(),
e.getClass().getSimpleName() + ": " + e.getMessage()));
} catch (SendFailedException e) {
Address[] inVaild = e.getInvalidAddresses();
if (inVaild != null) {
for (Address address : inVaild) {
logger.error("无效的邮箱:"+address);
}
}
Address[] vaild = e.getValidUnsentAddresses();
if (vaild != null && vaild.length > 0) {
String[] new_emails = address2emails(vaild);
mailInfo.setTos(new_emails);
try {
sendMail(mailInfo, account, false);
} catch (Exception e1) {
logger.error("重新发送邮件出错:", e1);
throw new MorningStarException(new CODE(CODE.FAIL.getIndex(),
e1.getClass().getSimpleName() + ": " + e1.getMessage()));
}
}
} catch (MessagingException |IOException e) {
logger.error("邮件发送出错:", e);
throw new MorningStarException(new CODE(CODE.FAIL.getIndex(),
e.getClass().getSimpleName() + ": " + e.getMessage()));
}
}
/**
* 底部发送邮件方法不直接对外调用
*
* @param mailInfo 邮件信息
* @param mailAccount 邮箱账号地址信息
* @param debug 是否debug打印出发送过程
*
* @throws SendFailedException
* @throws MessagingException
* @throws IOException
*/
private static void sendMail(EmailInfoVo mailInfo, MailAccount mailAccount, boolean debug)
throws SendFailedException, MessagingException, IOException {
final String userName = mailAccount.getUserName();
final String password = mailAccount.getPassword();
String mial_transport_protocol = "smtp";
Properties props = new Properties();
if (debug) {
props.setProperty("mail.debug", "true");
}
props.setProperty("mail.transport.protocol", mial_transport_protocol);
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.host", mailAccount.getMail_smtp_host());
String mail_smtp_port = mailAccount.getMail_smtp_port();
if (mail_smtp_port != null && mail_smtp_port.length() > 0) {
props.setProperty("mail.smtp.port", mail_smtp_port);
}
if (mailAccount.isSsl()) {
String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
props.setProperty("mail.smtp.socketFactory.port", mail_smtp_port);
props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.ssl.enable", "true");
}
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
return new javax.mail.PasswordAuthentication(userName, password);
}
});
Message msg = new MimeMessage(session);
msg.setSubject(encodeText(mailInfo.getSubject()));
msg.setFrom(new InternetAddress(mailInfo.getFrom(), mailInfo.getSendName(), "UTF-8"));
msg.setRecipients(Message.RecipientType.TO, emails2address(mailInfo.getTos()));
msg.setSentDate(new Date());
MimeMultipart partList = new MimeMultipart();
msg.setContent(partList);
MimeBodyPart contentPart = new MimeBodyPart();
contentPart.setContent(
(mailInfo.getContent() == null) ? "" : mailInfo.getContent(),
"text/html;charset=utf-8");
partList.addBodyPart(contentPart);
List<File> attachFileList = new ArrayList<>();
if (!CollectionUtils.isEmpty(mailInfo.getAttachmentList())) {
for (EmailAttachmentVo attach : mailInfo.getAttachmentList()) {
File attachFile = createFile(attach);
attachFileList.add(attachFile);
MimeBodyPart attachPart = new MimeBodyPart();
attachPart.attachFile(attachFile);
if (!StringUtils.isBlank(attach.getFileName())) {
attachPart.setFileName(encodeText(attach.getFileName()));
}
else {
attachPart.setFileName(encodeText(attachFile.getName()));
}
partList.addBodyPart(attachPart);
}
}
Transport.send(msg);
if (!CollectionUtils.isEmpty(attachFileList)) {
deleteFile(attachFileList);
}
}
private static void checkParams(EmailInfoVo mailInfo) {
if (mailInfo==null) {
logger.error("参数对象为null!");
throw new MorningStarException(new CODE(CODE.PARAMERROR.index, "EmailInfoVo不能为null"));
}
if (StringUtils.isBlank(mailInfo.getUserName())) {
logger.error("发送邮箱为null!");
throw new MorningStarException(new CODE(CODE.PARAMERROR.index, "发送邮箱为null"));
}
if (mailInfo.getTos() == null || mailInfo.getTos().length < 1) {
logger.error("收件人邮箱列表为空!");
throw new MorningStarException(new CODE(CODE.PARAMERROR.index, "收件人邮箱列表为空"));
}
if (StringUtils.isBlank(mailInfo.getPassword())) {
logger.error("发送邮箱密码异常!");
throw new MorningStarException(new CODE(CODE.PARAMERROR.index, "发送邮箱密码异常"));
}
if (!StringUtils.isBlank(mailInfo.getSmtpPort())) {
int smtpPort;
try {
smtpPort = Integer.valueOf(mailInfo.getSmtpPort());
if (!(0 <= smtpPort && smtpPort <= 65535)) {
throw new RuntimeException();
}
}
catch (Exception ex) {
throw new MorningStarException(new CODE(CODE.PARAMERROR.getIndex(), "发送服务器SMTP端口错误"));
}
}
}
private static String[] address2emails(Address[] address) {
if(address == null || address.length == 0){
return new String[]{};
}
String[] emails = new String[address.length];
for (int i = 0; i < address.length; ++i) {
emails[i] = address[i].toString();
}
return emails;
}
private static Address[] emails2address(String[] emails) throws AddressException {
if (emails == null || emails.length == 0) {
return new Address[]{};
}
Address[] address = new Address[emails.length];
for (int i = 0; i < emails.length; ++i) {
address[i] = new InternetAddress(emails[i]);
}
return address;
}
private static String encodeText(String text) throws UnsupportedEncodingException {
return MimeUtility.encodeText(text, "UTF-8", "B");
}
private static File createFile(EmailAttachmentVo attach) throws IOException {
File attachFile = null;
attachFile = File.createTempFile("message-email.", ".attach");
try (FileOutputStream fileout = new FileOutputStream(attachFile)) {
fileout.write(attach.getFileContent());
fileout.flush();
return attachFile;
}
}
private static void deleteFile(File file) {
if (file != null) {
try {
file.delete();
}
catch (Exception ex) {
}
}
}
private static void deleteFile(List<File> fileList) {
if (!CollectionUtils.isEmpty(fileList)) {
for (File file : fileList) {
deleteFile(file);
}
}
}
}
实体EmailInfoVo
package com.morning.star.pt.common.entity;
import java.io.Serializable;
import java.util.List;
public class EmailInfoVo implements Serializable {
private static final long serialVersionUID = -6814843971004397989L;
private String subject;
private String content;
private String[] tos;
private String userName;
private String password;
private String from;
private String sendName;
private String smtpServer;
private String smtpPort;
private List<EmailAttachmentVo> attachmentList;
get set 方法省略
}
实体EmailInfoVo
package com.morning.star.pt.common.entity;
import java.io.Serializable;
public class MailAccount implements Serializable {
/**
* 邮箱用户名
*/
private String userName;
/**
* 邮箱用户密码
*/
private String password;
/**
* 发送邮件服务器
*/
private String mail_smtp_host;
/**
* 发送邮件端口 (使用默认端口请填null,否则填邮件服务器对应端口;如启用ssl方式发送邮件,请设置邮件服务器ssl端口)
*/
private String mail_smtp_port;
/**
* SSL:使用SSL加密方式发送 true; 否则false
*/
private boolean ssl;
public MailAccount() {
}
public MailAccount(String userName, String password, String mail_smtp_host,
String mail_smtp_port, boolean ssl) {
this.userName = userName;
this.password = password;
this.mail_smtp_host = mail_smtp_host;
this.mail_smtp_port = mail_smtp_port;
this.ssl = ssl;
}
get set 方法省略
实体EmailAttachmentVo
package com.morning.star.pt.common.entity;
import java.io.Serializable;
public class EmailAttachmentVo implements Serializable {
private static final long serialVersionUID = 7316991294294102884L;
private String fileName;
private byte[] fileContent;
public EmailAttachmentVo() {
super();
}
public EmailAttachmentVo(String fileName, byte[] fileContent) {
super();
this.fileName = fileName;
this.fileContent = fileContent;
}
get set 方法省略
}
调用示例
@RequestMapping("/testSendEmail")
@ResponseBody
public WebJsonBean testSendEmail() {
EmailInfoVo emailInfoVo = new EmailInfoVo();
emailInfoVo.setSubject("订单清单");
emailInfoVo.setContent("测试一下邮件发送");
emailInfoVo.setTos(new String[]{"x812603834@qq.com"});
emailInfoVo.setUserName("aaa@hah.com");
emailInfoVo.setPassword("123456");
EmailUtils.sendMail(emailInfoVo);
return new WebJsonBean(CODE.SUCCESS, true);
}