package message.email; import message.base.utils.ApplicationHelper; import message.utils.StringUtils; import message.utils.ValidateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.activation.DataHandler; import javax.activation.FileDataSource; import javax.mail.*; import javax.mail.internet.*; import java.io.File; import java.io.UnsupportedEncodingException; import java.util.*; /** * 发送邮件服务器. * * @author sunhao(sunhao.java@gmail.com) * @version V1.0, 13-3-25 上午6:19 */ public class EmailServer { private static final Logger logger = LoggerFactory.getLogger(EmailServer.class); //spring中配置 /** * 邮箱服务器配置* */ private static List<EmailConfig> configs = new ArrayList<EmailConfig>(); /** * 是否开启debug调试模式* */ private boolean isDebug = false; /** * 是否启用身份验证* */ private boolean isAuth = true; /** * 验证类型* */ private String authType = "auth"; /** * 是否初始化 */ private static boolean isInit = false; private static EmailServer emailServer; /** * 私有化默认构造器,使外部不可实例化 */ private EmailServer(boolean isAuth, boolean isDebug) { this.isAuth = isAuth; this.isDebug = isDebug; } /** * 单例,保证上下文中只有一个EmailServer * * @return EmailServer */ public static EmailServer getInstance() { if (!isInit) { Map<String, EmailConfig> configsInContext = ApplicationHelper.getInstance().getBeansByType(EmailConfig.class); configs.addAll(configsInContext.values()); isInit = true; } if (emailServer == null) emailServer = new EmailServer(true, false); return emailServer; } /** * 发送普通邮件(单个接收人) * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receiver 单个接收人 * @return */ public boolean sendTextMail(String username, String password, String title, String content, String receiver) { return this.sendTextMail(username, password, title, content, Collections.singletonList(receiver)); } /** * 发送普通邮件(多个接收人) * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receivers 多个接收人 * @return */ public boolean sendTextMail(String username, String password, String title, String content, List<String> receivers) { return this.sendMail(username, password, title, content, receivers, false, null); } /** * 发送HTML邮件(单个接收人) * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receiver 单个接收人 * @return */ public boolean sendHtmlMail(String username, String password, String title, String content, String receiver) { return this.sendHtmlMail(username, password, title, content, Collections.singletonList(receiver)); } /** * 发送HTML邮件(多个接收人) * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receivers 多个接收人 * @return */ public boolean sendHtmlMail(String username, String password, String title, String content, List<String> receivers) { return this.sendMail(username, password, title, content, receivers, true, null); } /** * 发送有附件的邮件 * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receivers 多个接收人 * @param files 要发送的附件 * @return */ public boolean sendAttachmentMail(String username, String password, String title, String content, List<String> receivers, List<File> files) { return this.sendMail(username, password, title, content, receivers, true, files); } /** * 发送有附件的邮件 * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receiver 接收人 * @param files 要发送的附件 * @return */ public boolean sendAttachmentMail(String username, String password, String title, String content, String receiver, List<File> files) { return this.sendAttachmentMail(username, password, title, content, Collections.singletonList(receiver), files); } /** * 发送有附件的邮件 * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receiver 接收人 * @param file 要发送的附件 * @return */ public boolean sendAttachmentMail(String username, String password, String title, String content, String receiver, File file) { return this.sendAttachmentMail(username, password, title, content, Collections.singletonList(receiver), Collections.singletonList(file)); } /** * 发送有附件的邮件 * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receivers 多个接收人 * @param fileNames 要发送的附件 * @return */ public boolean sendAttachmentMail(String username, String password, String title, List<String> fileNames, String content, List<String> receivers) { List<File> fs = new ArrayList<File>(); for (String fn : fileNames) { File f = new File(fn); if (f.exists() && f.canRead()) fs.add(f); } return this.sendAttachmentMail(username, password, title, content, receivers, fs); } /** * 发送有附件的邮件 * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receivers 多个接收人 * @param fileName 要发送的附件 * @return */ public boolean sendAttachmentMail(String username, String password, String title, String content, List<String> receivers, String fileName) { return this.sendAttachmentMail(username, password, title, Collections.singletonList(fileName), content, receivers); } /** * 发送有附件的邮件 * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receiver 多个接收人 * @param fileName 要发送的附件 * @return */ public boolean sendAttachmentMail(String username, String password, String title, String content, String receiver, String fileName) { return this.sendAttachmentMail(username, password, title, Collections.singletonList(fileName), content, Collections.singletonList(receiver)); } /** * 发送邮件(多个接收人)(可以指定是否是html邮件) * * @param username 发件人用户名 * @param password 发件人密码 * @param title 邮件标题 * @param content 邮件正文 * @param receivers 多个接收人 * @param isHtmlMail 是否是html邮件 * @param files 要发送的附件 * @return */ private boolean sendMail(String username, String password, String title, String content, List<String> receivers, boolean isHtmlMail, List<File> files) { Authentication auth = null; if (this.isAuth) { //如果需要身份认证,则创建一个密码验证器 auth = new Authentication(username, password); } Properties props = new Properties(); props.setProperty("mail.smtp.auth", this.isAuth ? "true" : "false"); props.setProperty("mail.transport.protocol", "auth"); EmailConfig config = this.getEmailConfig(username); props.setProperty("mail.smtp.host", config.getSmtp()); props.setProperty("mail.smtp.port", config.getPort() + ""); // 根据邮件会话属性和密码验证器构造一个发送邮件的session Session session = Session.getDefaultInstance(props, auth); session.setDebug(this.isDebug); Message message = null; if (files == null || files.isEmpty()) { //非发送附件 message = this.makeSimpleMail(session, title, content, username, receivers, isHtmlMail); } else { //发送附件 message = this.makeAttachmentMail(session, title, content, username, receivers, files); } try { Transport.send(message); return true; } catch (MessagingException e) { logger.error(e.getMessage(), e); return false; } } /** * 获取邮件服务器配置 * * @param email 邮箱地址 * @return */ private EmailConfig getEmailConfig(String email) { String mailServiceDomainName = this.getMailServiceDomainName(email); for (EmailConfig config : configs) { if (config.getName().equals(mailServiceDomainName)) { return config; } } return null; } /** * 创建邮件message(无附件) * * @param session 根据配置获得的session * @param title 邮件主题 * @param content 邮件的内容 * @param from 发件者 * @param receivers 收件者 * @param isHtmlMail 是否是html邮件 */ private Message makeSimpleMail(Session session, String title, String content, String from, List<String> receivers, boolean isHtmlMail) { Message message = new MimeMessage(session); try { /**标题**/ logger.info("this mail's title is {}", title); message.setSubject(title); /**内容**/ logger.info("this mail's content is {}", content); if (isHtmlMail) { //是html邮件 message.setContent(content, "text/html;charset=utf-8"); } else { //普通邮件 message.setText(content); } /**发件者地址**/ logger.info("this mail's sender is {}", from); Address fromAddress = new InternetAddress(from); message.setFrom(fromAddress); /**接收者地址**/ Address[] tos = new InternetAddress[receivers.size()]; for (int i = 0; i < receivers.size(); i++) { String receiver = receivers.get(i); if (ValidateUtils.isEmail(receiver)) { tos[i] = new InternetAddress(receiver); } } /**发件时间**/ message.setSentDate(new Date()); message.setRecipients(Message.RecipientType.TO, tos); } catch (MessagingException e) { logger.error(e.getMessage(), e); e.printStackTrace(); } return message; } /** * 创建邮件message(有附件) * * @param session 根据配置获得的session * @param title 邮件主题 * @param content 邮件的内容 * @param from 发件者 * @param receivers 收件者 * @param files 附件 */ private Message makeAttachmentMail(Session session, String title, String content, String from, List<String> receivers, List<File> files) { Message message = new MimeMessage(session); try { /**标题**/ logger.info("this mail's title is {}", title); message.setSubject(title); /**内容**/ logger.info("this mail's content is {}", content); Multipart multipart = new MimeMultipart(); MimeBodyPart mimeBodyPart = new MimeBodyPart(); mimeBodyPart.setContent(content, "text/html;charset=utf-8"); multipart.addBodyPart(mimeBodyPart); if (files != null && !files.isEmpty()) { //存在附件 for (Iterator<File> it = files.iterator(); it.hasNext(); ) { mimeBodyPart = new MimeBodyPart(); File attachment = it.next(); //得到数据源 FileDataSource fds = new FileDataSource(attachment); //得到附件本身并至入BodyPart mimeBodyPart.setDataHandler(new DataHandler(fds)); //得到文件名同样至入BodyPart(附件名乱码解决方案MimeUtility.encodeText(name)) mimeBodyPart.setFileName(MimeUtility.encodeText(attachment.getName())); multipart.addBodyPart(mimeBodyPart); } } message.setContent(multipart); /**发件者地址**/ logger.info("this mail's sender is {}", from); Address fromAddress = new InternetAddress(from); message.setFrom(fromAddress); /**接收者地址**/ Address[] tos = new InternetAddress[receivers.size()]; for (int i = 0; i < receivers.size(); i++) { String receiver = receivers.get(i); if (ValidateUtils.isEmail(receiver)) { tos[i] = new InternetAddress(receiver); } } /**发件时间**/ message.setSentDate(new Date()); message.setRecipients(Message.RecipientType.TO, tos); } catch (MessagingException e) { logger.error(e.getMessage(), e); e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return message; } /** * 获取邮箱域名 * * @param email 邮箱 * @return */ private String getMailServiceDomainName(String email) { if (StringUtils.isEmpty(email)) { return ""; } else { int firstIndex = StringUtils.indexOf(email, "@"); int secondIndex = StringUtils.lastIndexOf(email, "."); return StringUtils.substring(email, firstIndex + 1, secondIndex); } } public String getAuthType() { return authType; } public void setAuthType(String authType) { this.authType = authType; } }