From 931f6e5a8ea7f66493e5eee6768527860d6899d6 Mon Sep 17 00:00:00 2001 From: 502647092 Date: Tue, 27 Sep 2016 15:12:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=82=AE=E4=BB=B6?= =?UTF-8?q?=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 502647092 --- .../java/pw/yumc/YumCore/mail/MailAPI.java | 134 +++++++++++ .../yumc/YumCore/mail/MailAuthenticator.java | 57 +++++ .../java/pw/yumc/YumCore/mail/SimpleMail.java | 81 +++++++ .../yumc/YumCore/mail/SimpleMailSender.java | 139 +++++++++++ src/main/java/pw/yumc/YumCore/mail/XMail.java | 222 ++++++++++++++++++ 5 files changed, 633 insertions(+) create mode 100644 src/main/java/pw/yumc/YumCore/mail/MailAPI.java create mode 100644 src/main/java/pw/yumc/YumCore/mail/MailAuthenticator.java create mode 100644 src/main/java/pw/yumc/YumCore/mail/SimpleMail.java create mode 100644 src/main/java/pw/yumc/YumCore/mail/SimpleMailSender.java create mode 100644 src/main/java/pw/yumc/YumCore/mail/XMail.java diff --git a/src/main/java/pw/yumc/YumCore/mail/MailAPI.java b/src/main/java/pw/yumc/YumCore/mail/MailAPI.java new file mode 100644 index 0000000..42c68be --- /dev/null +++ b/src/main/java/pw/yumc/YumCore/mail/MailAPI.java @@ -0,0 +1,134 @@ +package pw.yumc.YumCore.mail; + +import com.google.common.net.HostAndPort; + +/** + * + * @since 2016年4月9日 下午5:23:09 + * @author 喵♂呜 + */ +public class MailAPI { + + /** + * 快速发信 + * + * @param smtp + * SMTP 服务器 + * @param from + * 发件人 + * @param to + * 收件人 + * @param subject + * 主题 + * @param content + * 内容 + * @return 是否发送成功 + */ + public static boolean send(final HostAndPort smtp, final String from, final String to, final String subject, final String content) { + return send(smtp, from, to, subject, content, null, null); + } + + /** + * 快速发信 + * + * @param smtp + * SMTP 服务器 + * @param from + * 发件人 + * @param to + * 收件人 + * @param subject + * 主题 + * @param content + * 内容 + * @param username + * 用户名 + * @param password + * 密码 + * @return 是否发送成功 + */ + public static boolean send(final HostAndPort smtp, final String from, final String to, final String subject, final String content, final String username, final String password) { + return send(smtp, from, null, to, subject, content, username, password); + } + + /** + * 快速发信 + * + * @param smtp + * SMTP 服务器 + * @param from + * 发件人 + * @param fromName + * 发件人名称 + * @param to + * 收件人 + * @param subject + * 主题 + * @param content + * 内容 + * @param username + * 用户名 + * @param password + * 密码 + * @return 是否发送成功 + */ + public static boolean send(final HostAndPort smtp, final String from, final String fromName, final String to, final String subject, final String content, final String username, final String password) { + return send(smtp, from, fromName, to, null, subject, content, username, password); + } + + /** + * 快速发信 + * + * @param smtp + * SMTP 服务器 + * @param from + * 发件人 + * @param fromName + * 发件人名称 + * @param to + * 收件人 + * @param copyto + * 抄送 + * @param subject + * 主题 + * @param content + * 内容 + * @param username + * 用户名 + * @param password + * 密码 + * @return 是否发送成功 + */ + public static boolean send(final HostAndPort smtp, final String from, final String fromName, final String to, final String copyto, final String subject, final String content, final String username, final String password) { + return send(smtp, from, fromName, to, copyto, subject, content, null, username, password); + } + + /** + * 快速发信 + * + * @param smtp + * SMTP 服务器 + * @param from + * 发件人 + * @param fromName + * 发件人名称 + * @param to + * 收件人 + * @param copyto + * 抄送 + * @param subject + * 主题 + * @param content + * 内容 + * @param filename + * 文件名称 + * @param username + * 用户名 + * @param password + * 密码 + * @return 是否发送成功 + */ + public static boolean send(final HostAndPort smtp, final String from, final String fromName, final String to, final String copyto, final String subject, final String content, final String[] filename, final String username, final String password) { + return XMail.send(smtp, from, fromName, to, copyto, subject, content, filename, username, password, true); + } +} diff --git a/src/main/java/pw/yumc/YumCore/mail/MailAuthenticator.java b/src/main/java/pw/yumc/YumCore/mail/MailAuthenticator.java new file mode 100644 index 0000000..be0aa01 --- /dev/null +++ b/src/main/java/pw/yumc/YumCore/mail/MailAuthenticator.java @@ -0,0 +1,57 @@ +package pw.yumc.YumCore.mail; + +import javax.mail.Authenticator; +import javax.mail.PasswordAuthentication; + +/** + * 服务器邮箱登录验证 + * + * @author MZULE + * + */ +public class MailAuthenticator extends Authenticator { + + /** + * 用户名(登录邮箱) + */ + private String username; + /** + * 密码 + */ + private String password; + + /** + * 初始化邮箱和密码 + * + * @param username + * 邮箱 + * @param password + * 密码 + */ + public MailAuthenticator(final String username, final String password) { + this.username = username; + this.password = password; + } + + public void setPassword(final String password) { + this.password = password; + } + + public void setUsername(final String username) { + this.username = username; + } + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + + String getPassword() { + return password; + } + + String getUsername() { + return username; + } + +} diff --git a/src/main/java/pw/yumc/YumCore/mail/SimpleMail.java b/src/main/java/pw/yumc/YumCore/mail/SimpleMail.java new file mode 100644 index 0000000..bf4fc83 --- /dev/null +++ b/src/main/java/pw/yumc/YumCore/mail/SimpleMail.java @@ -0,0 +1,81 @@ +package pw.yumc.YumCore.mail; + +import java.util.Date; + +import javax.mail.Address; + +class SimpleMail { + + private String subject; + private Object content; + + private Date sentDate = null; + private String from = null; + private Address sender; + + public SimpleMail(final String subject, final Object content) { + this.subject = subject; + this.content = content; + } + + /** + * 内容 + * + * @return + */ + public Object getContent() { + return content; + } + + public String getFrom() { + return from; + } + + public Address getSender() { + return sender; + } + + public Date getSentDate() { + return sentDate; + } + + /** + * 标题 + * + * @return + */ + public String getSubject() { + return subject; + } + + /** + * 内容 + * + * @param content + */ + public void setContent(final Object content) { + this.content = content; + } + + public void setFrom(final String from) { + this.from = from; + } + + public void setSender(final Address sender) { + this.sender = sender; + } + + public void setSentDate(final Date date) { + this.sentDate = date; + } + + /** + * 标题 + * + * @param subject + */ + public void setSubject(final String subject) { + this.subject = subject; + } + +} \ No newline at end of file diff --git a/src/main/java/pw/yumc/YumCore/mail/SimpleMailSender.java b/src/main/java/pw/yumc/YumCore/mail/SimpleMailSender.java new file mode 100644 index 0000000..2b7605c --- /dev/null +++ b/src/main/java/pw/yumc/YumCore/mail/SimpleMailSender.java @@ -0,0 +1,139 @@ +package pw.yumc.YumCore.mail; + +import java.util.Properties; + +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMessage.RecipientType; + +/** + * 简单邮件发送器,可单发,群发。 + * + * @author MZULE + * + */ +public class SimpleMailSender { + /** + * 发送邮件的props文件 + */ + private final transient Properties props = System.getProperties(); + + /** + * 邮件服务器登录验证 + */ + private transient MailAuthenticator authenticator; + + /** + * 邮箱session + */ + private transient Session session; + + /** + * 初始化邮件发送器 + * + * @param username + * 发送邮件的用户名(地址),并以此解析SMTP服务器地址 + * @param password + * 发送邮件的密码 + */ + public SimpleMailSender(final String username, final String password) { + // 通过邮箱地址解析出smtp服务器,对大多数邮箱都管用 + final String smtpHostName = "smtp." + username.split("@")[1]; + init(smtpHostName, username, password); + } + + /** + * 初始化邮件发送器 + * + * @param smtpHostName + * SMTP邮件服务器地址 + * @param username + * 发送邮件的用户名(地址) + * @param password + * 发送邮件的密码 + */ + public SimpleMailSender(final String smtpHostName, final String username, final String password) { + init(username, password, smtpHostName); + } + + /** + * 群发邮件 + * + * @param mail + * 邮件对象 + * @param recipients + * 收件人们 + * @throws AddressException + * @throws MessagingException + */ + public void send(final SimpleMail mail, final String... recipients) throws AddressException, MessagingException { + // 创建mime类型邮件 + final MimeMessage message = new MimeMessage(session); + // 设置发信人 + if (mail.getFrom() != null) { + message.setFrom(new InternetAddress(mail.getFrom())); + } else { + message.setFrom(new InternetAddress(authenticator.getUsername())); + } + // 设置收件人们 + final int num = recipients.length; + final InternetAddress[] addresses = new InternetAddress[num]; + for (int i = 0; i < num; i++) { + addresses[i] = new InternetAddress(recipients[i]); + } + message.setRecipients(RecipientType.TO, addresses); + // 设置主题 + message.setSubject(mail.getSubject()); + // 设置邮件内容 + message.setContent(mail.getContent().toString(), "text/html;charset=utf-8"); + if (mail.getSentDate() != null) { + message.setSentDate(mail.getSentDate()); + } + if (mail.getSender() != null) { + message.setSender(mail.getSender()); + } + // 发送 + Transport.send(message); + } + + /** + * 群发邮件 + * + * @param subject + * 邮件主题 + * @param content + * 邮件内容 + * @param recipients + * 收件人邮箱地址 + * @throws AddressException + * @throws MessagingException + */ + public void send(final String subject, final Object content, final String... recipients) throws AddressException, MessagingException { + this.send(new SimpleMail(subject, content), recipients); + } + + /** + * 初始化 + * + * @param username + * 发送邮件的用户名(地址) + * @param password + * 密码 + * @param smtpHostName + * SMTP主机地址 + */ + private void init(final String smtpHostName, final String username, final String password) { + // 初始化props + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.host", smtpHostName); + // 验证 + authenticator = new MailAuthenticator(username, password); + // 创建session + session = Session.getInstance(props, authenticator); + } + +} diff --git a/src/main/java/pw/yumc/YumCore/mail/XMail.java b/src/main/java/pw/yumc/YumCore/mail/XMail.java new file mode 100644 index 0000000..0a9ccc9 --- /dev/null +++ b/src/main/java/pw/yumc/YumCore/mail/XMail.java @@ -0,0 +1,222 @@ +package pw.yumc.YumCore.mail; + +import java.lang.reflect.Field; +import java.util.Date; +import java.util.HashMap; +import java.util.Properties; + +import javax.activation.DataContentHandler; +import javax.activation.DataContentHandlerFactory; +import javax.activation.DataHandler; +import javax.activation.FileDataSource; +import javax.mail.Authenticator; +import javax.mail.BodyPart; +import javax.mail.Message; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; + +import com.google.common.net.HostAndPort; + +public class XMail { + + private static boolean autoRegister = true; + + private static final HashMap handlers = new HashMap<>(); + private static final DataContentHandlerFactory defaultDataContentHandlerFactory; + static { + // todo + // activation.jar + // CommandMap.getDefaultCommandMap中取出已通过addMailcap注册的handler合集 + // 通过合集遍历type和class打入map, 以取代手工注册 + handlers.put("text/html", new com.sun.mail.handlers.text_html()); + handlers.put("text/xml", new com.sun.mail.handlers.text_html()); + handlers.put("text/plain", new com.sun.mail.handlers.text_plain()); + handlers.put("multipart/mixed", new com.sun.mail.handlers.multipart_mixed()); + handlers.put("multipart/*", new com.sun.mail.handlers.multipart_mixed()); + handlers.put("message/rfc822", new com.sun.mail.handlers.message_rfc822()); + handlers.put("image/gif", new com.sun.mail.handlers.image_gif()); + handlers.put("image/jpeg", new com.sun.mail.handlers.image_jpeg()); + defaultDataContentHandlerFactory = new DataContentHandlerFactory() { + @Override + public DataContentHandler createDataContentHandler(final String type) { + final DataContentHandler handler = handlers.get(type); + if (handler != null) { + return handler; + } + System.out.println("************* Unknown Type: " + type + " *************"); + return null; + } + }; + } + + public static void addDataContentHandler(final String type, final DataContentHandler handler) { + handlers.put(type, handler); + } + + public static boolean isAutoRegister() { + return autoRegister; + } + + public static boolean registerDefaultDataContentHandlerFactory() { + try { + DataHandler.setDataContentHandlerFactory(defaultDataContentHandlerFactory); + return true; + } catch (final Exception e) { + } + return false; + } + + /** + * 快速发信 + * + * @param smtp + * SMTP 服务器 + * @param from + * 发件人 + * @param fromName + * 发件人名称 + * @param to + * 收件人 + * @param copyto + * 抄送 + * @param subject + * 主题 + * @param content + * 内容 + * @param filename + * 文件名称 + * @param username + * 用户名 + * @param password + * 密码 + * @param needAuth + * 是否需要验证 + * @return 是否发送成功 + */ + public static boolean send(final HostAndPort smtp, final String from, String fromName, final String to, final String copyto, final String subject, final String content, final String[] filename, final String username, final String password, final boolean needAuth) { + try { + if (isAutoRegister()) { + unregisterDefaultDataContentHandlerFactory(); + registerDefaultDataContentHandlerFactory(); + } + final Properties props = new Properties(); + props.put("mail.smtp.host", smtp.getHostText()); + props.put("mail.smtp.port", smtp.getPort()); + props.put("mail.smtp.socketFactory.port", smtp.getPort()); + props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); + props.put("mail.smtp.auth", needAuth); + final Session mailSession = Session.getInstance(props, new Authenticator() { + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + if (fromName == null) { + fromName = from; + } + final MimeMessage mimeMsg = new MimeMessage(mailSession); + mimeMsg.setSubject(subject); + + final MimeMultipart mp = new MimeMultipart(); + + if (content != null) { + try { + final BodyPart bp = new MimeBodyPart(); + bp.setContent("" + content, "text/html;charset=GBK"); + mp.addBodyPart(bp); + } catch (final Exception e) { + System.err.println("设置邮件正文时发生错误!" + e); + return false; + } + } + + if (filename != null) { + for (final String file : filename) { + try { + final BodyPart bp = new MimeBodyPart(); + final FileDataSource fileds = new FileDataSource(file); + bp.setDataHandler(new DataHandler(fileds)); + bp.setFileName(fileds.getName()); + mp.addBodyPart(bp); + } catch (final Exception e) { + System.err.println("增加邮件附件:" + file + "发生错误!" + e); + } + } + } + + mimeMsg.setContent(mp); + + try { + // 设置发信人 + try { + mimeMsg.setFrom(new InternetAddress(from, fromName)); + } catch (final Exception e) { + mimeMsg.setFrom(new InternetAddress(from)); + } + } catch (final Exception e) { + System.err.println("设置发信人发生错误!"); + e.printStackTrace(); + return false; + } + + try { + mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); + } catch (final Exception e) { + System.err.println("设置接收人发生错误!"); + e.printStackTrace(); + return false; + } + + if (copyto != null) { + try { + // 设置抄送人 + try { + mimeMsg.setFrom(new InternetAddress(from, fromName)); + } catch (final Exception e) { + mimeMsg.setFrom(new InternetAddress(from)); + } + } catch (final Exception e) { + System.err.println("设置抄送人发生错误!"); + e.printStackTrace(); + } + } + + mimeMsg.setSentDate(new Date()); + + mimeMsg.saveChanges(); + + Transport.send(mimeMsg); + + return true; + } catch (final Exception e) { + e.printStackTrace(); + } finally { + if (isAutoRegister()) { + unregisterDefaultDataContentHandlerFactory(); + } + } + return false; + } + + public static void setAutoRegister(final boolean autoRegister) { + XMail.autoRegister = autoRegister; + } + + public static Object unregisterDefaultDataContentHandlerFactory() { + try { + final Field field = DataHandler.class.getDeclaredField("factory"); + field.setAccessible(true); + final Object object = field.get(null); + field.set(null, null); + return object; + } catch (final Exception e) { + } + return null; + } +}