From 81e1c92c570be8d7f69953d63ed36cfd2ee48f4d Mon Sep 17 00:00:00 2001 From: shenyineng Date: Sun, 18 Aug 2019 17:43:49 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=82=AE=E4=BB=B6=E4=B8=AD?= =?UTF-8?q?=E5=B5=8C=E5=85=A5=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/hutool/extra/mail/Mail.java | 742 +++++++++--------- .../java/cn/hutool/extra/mail/MailUtil.java | 618 +++++++++------ 2 files changed, 770 insertions(+), 590 deletions(-) diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java index b225f299d..08620a92b 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/Mail.java @@ -1,354 +1,388 @@ -package cn.hutool.extra.mail; - -import java.io.File; -import java.nio.charset.Charset; -import java.util.Date; - -import javax.activation.DataHandler; -import javax.activation.DataSource; -import javax.activation.FileDataSource; -import javax.mail.Authenticator; -import javax.mail.BodyPart; -import javax.mail.MessagingException; -import javax.mail.Multipart; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; - -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.StrUtil; - -/** - * 邮件发送客户端 - * - * @author looly - * @since 3.2.0 - */ -public class Mail { - - /** 邮箱帐户信息以及一些客户端配置信息 */ - private MailAccount mailAccount; - /** 收件人列表 */ - private String[] tos; - /** 抄送人列表(carbon copy) */ - private String[] ccs; - /** 密送人列表(blind carbon copy) */ - private String[] bccs; - /** 回复地址(reply-to) */ - private String[] reply; - /** 标题 */ - private String title; - /** 内容 */ - private String content; - /** 是否为HTML */ - private boolean isHtml; - /** 附件列表 */ - private DataSource[] attachments; - /** 是否使用全局会话,默认为false */ - private boolean useGlobalSession = false; - - /** - * 创建邮件客户端 - * - * @param mailAccount 邮件帐号 - * @return {@link Mail} - */ - public static Mail create(MailAccount mailAccount) { - return new Mail(mailAccount); - } - - /** - * 创建邮件客户端,使用全局邮件帐户 - * - * @return {@link Mail} - */ - public static Mail create() { - return new Mail(); - } - - // --------------------------------------------------------------- Constructor start - /** - * 构造,使用全局邮件帐户 - */ - public Mail() { - this(GlobalMailAccount.INSTANCE.getAccount()); - } - - /** - * 构造 - * - * @param mailAccount 邮件帐户,如果为null使用默认配置文件的全局邮件配置 - */ - public Mail(MailAccount mailAccount) { - mailAccount = (null != mailAccount) ? mailAccount : GlobalMailAccount.INSTANCE.getAccount(); - this.mailAccount = mailAccount.defaultIfEmpty(); - } - // --------------------------------------------------------------- Constructor end - - // --------------------------------------------------------------- Getters and Setters start - /** - * 设置收件人 - * - * @param tos 收件人列表 - * @return this - * @see #setTos(String...) - */ - public Mail to(String... tos) { - return setTos(tos); - } - - /** - * 设置多个收件人 - * - * @param tos 收件人列表 - * @return this - */ - public Mail setTos(String... tos) { - this.tos = tos; - return this; - } - - /** - * 设置多个抄送人(carbon copy) - * - * @param ccs 抄送人列表 - * @return this - * @since 4.0.3 - */ - public Mail setCcs(String... ccs) { - this.ccs = ccs; - return this; - } - - /** - * 设置多个密送人(blind carbon copy) - * - * @param bccs 密送人列表 - * @return this - * @since 4.0.3 - */ - public Mail setBccs(String... bccs) { - this.bccs = bccs; - return this; - } - - /** - * 设置多个回复地址(reply-to) - * - * @param reply 回复地址(reply-to)列表 - * @return this - * @since 4.6.0 - */ - public Mail setReply(String... reply) { - this.reply = reply; - return this; - } - - /** - * 设置标题 - * - * @param title 标题 - * @return this - */ - public Mail setTitle(String title) { - this.title = title; - return this; - } - - /** - * 设置正文 - * - * @param content 正文 - * @return this - */ - public Mail setContent(String content) { - this.content = content; - return this; - } - - /** - * 设置是否是HTML - * - * @param isHtml 是否为HTML - * @return this - */ - public Mail setHtml(boolean isHtml) { - this.isHtml = isHtml; - return this; - } - - /** - * 设置文件类型附件 - * - * @param files 附件文件列表 - * @return this - */ - public Mail setFiles(File... files) { - if(ArrayUtil.isEmpty(files)) { - return this; - } - - final DataSource[] attachments = new DataSource[files.length]; - for (int i = 0; i < files.length; i++) { - attachments[i] = new FileDataSource(files[i]); - } - return setAttachments(attachments); - } - - /** - * 设置附件,附件使用{@link DataSource} 形式表示,可以使用{@link FileDataSource}包装文件表示文件附件 - * - * @param attachments 附件列表 - * @return this - * @since 4.0.9 - */ - public Mail setAttachments(DataSource... attachments) { - if(ArrayUtil.isNotEmpty(attachments)) { - this.attachments = attachments; - } - return this; - } - - /** - * 设置字符集编码 - * - * @param charset 字符集编码 - * @return this - * @see MailAccount#setCharset(Charset) - */ - public Mail setCharset(Charset charset) { - this.mailAccount.setCharset(charset); - return this; - } - - /** - * 设置是否使用全局会话,默认为true - * - * @param isUseGlobalSession 是否使用全局会话,默认为true - * @return this - * @since 4.0.2 - */ - public Mail setUseGlobalSession(boolean isUseGlobalSession) { - this.useGlobalSession = isUseGlobalSession; - return this; - } - // --------------------------------------------------------------- Getters and Setters end - - /** - * 发送 - * - * @return this - * @throws MailException 邮件发送异常 - */ - public Mail send() throws MailException { - try { - return doSend(); - } catch (MessagingException e) { - throw new MailException(e); - } - } - - // --------------------------------------------------------------- Private method start - /** - * 执行发送 - * - * @return this - * @throws MessagingException 发送异常 - */ - private Mail doSend() throws MessagingException { - Transport.send(buildMsg()); - return this; - } - - /** - * 构建消息 - * - * @return {@link MimeMessage}消息 - * @throws MessagingException 消息异常 - */ - private MimeMessage buildMsg() throws MessagingException { - final Charset charset = this.mailAccount.getCharset(); - final MimeMessage msg = new MimeMessage(getSession(this.useGlobalSession)); - // 发件人 - final String from = this.mailAccount.getFrom(); - if (StrUtil.isEmpty(from)) { - // 用户未提供发送方,则从Session中自动获取 - msg.setFrom(); - } else { - msg.setFrom(InternalMailUtil.parseFirstAddress(from, charset)); - } - // 标题 - msg.setSubject(this.title, charset.name()); - // 发送时间 - msg.setSentDate(new Date()); - // 内容和附件 - msg.setContent(buildContent(charset)); - // 收件人 - msg.setRecipients(MimeMessage.RecipientType.TO, InternalMailUtil.parseAddressFromStrs(this.tos, charset)); - // 抄送人 - if (ArrayUtil.isNotEmpty(this.ccs)) { - msg.setRecipients(MimeMessage.RecipientType.CC, InternalMailUtil.parseAddressFromStrs(this.ccs, charset)); - } - // 密送人 - if (ArrayUtil.isNotEmpty(this.bccs)) { - msg.setRecipients(MimeMessage.RecipientType.BCC, InternalMailUtil.parseAddressFromStrs(this.bccs, charset)); - } - // 回复地址(reply-to) - if (ArrayUtil.isNotEmpty(this.reply)) { - msg.setReplyTo(InternalMailUtil.parseAddressFromStrs(this.reply, charset)); - } - - return msg; - } - - /** - * 构建邮件信息主体 - * - * @param charset 编码 - * @return 邮件信息主体 - * @throws MessagingException 消息异常 - */ - private Multipart buildContent(Charset charset) throws MessagingException { - final Multipart mainPart = new MimeMultipart(); - - // 正文 - final BodyPart body = new MimeBodyPart(); - body.setContent(content, StrUtil.format("text/{}; charset={}", isHtml ? "html" : "plain", charset)); - mainPart.addBodyPart(body); - - // 附件 - if (ArrayUtil.isNotEmpty(this.attachments)) { - BodyPart bodyPart; - for (DataSource attachment : attachments) { - bodyPart = new MimeBodyPart(); - bodyPart.setDataHandler(new DataHandler(attachment)); - bodyPart.setFileName(InternalMailUtil.encodeText(attachment.getName(), charset)); - mainPart.addBodyPart(bodyPart); - } - } - - return mainPart; - } - - /** - * 获取默认邮件会话
- * 如果为全局单例的会话,则全局只允许一个邮件帐号,否则每次发送邮件会新建一个新的会话 - * - * @param isSingleton 是否使用单例Session - * @return 邮件会话 {@link Session} - * @since 4.0.2 - */ - private Session getSession(boolean isSingleton) { - final MailAccount mailAccount = this.mailAccount; - Authenticator authenticator = null; - if (mailAccount.isAuth()) { - authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); - } - - return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) // - : Session.getInstance(mailAccount.getSmtpProps(), authenticator); - } - // --------------------------------------------------------------- Private method end -} +package cn.hutool.extra.mail; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Date; +import java.util.Map; + +import javax.activation.DataHandler; +import javax.activation.DataSource; +import javax.activation.FileDataSource; +import javax.mail.Authenticator; +import javax.mail.BodyPart; +import javax.mail.MessagingException; +import javax.mail.Multipart; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import javax.mail.util.ByteArrayDataSource; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; + +/** + * 邮件发送客户端 + * + * @author looly + * @since 3.2.0 + */ +public class Mail { + + /** 邮箱帐户信息以及一些客户端配置信息 */ + private MailAccount mailAccount; + /** 收件人列表 */ + private String[] tos; + /** 抄送人列表(carbon copy) */ + private String[] ccs; + /** 密送人列表(blind carbon copy) */ + private String[] bccs; + /** 回复地址(reply-to) */ + private String[] reply; + /** 标题 */ + private String title; + /** 内容 */ + private String content; + /** 是否为HTML */ + private boolean isHtml; + /** 附件列表 */ + private DataSource[] attachments; + /** 图片列表 */ + private Map imageMap; + /** 是否使用全局会话,默认为false */ + private boolean useGlobalSession = false; + + /** + * 创建邮件客户端 + * + * @param mailAccount 邮件帐号 + * @return {@link Mail} + */ + public static Mail create(MailAccount mailAccount) { + return new Mail(mailAccount); + } + + /** + * 创建邮件客户端,使用全局邮件帐户 + * + * @return {@link Mail} + */ + public static Mail create() { + return new Mail(); + } + + // --------------------------------------------------------------- Constructor start + /** + * 构造,使用全局邮件帐户 + */ + public Mail() { + this(GlobalMailAccount.INSTANCE.getAccount()); + } + + /** + * 构造 + * + * @param mailAccount 邮件帐户,如果为null使用默认配置文件的全局邮件配置 + */ + public Mail(MailAccount mailAccount) { + mailAccount = (null != mailAccount) ? mailAccount : GlobalMailAccount.INSTANCE.getAccount(); + this.mailAccount = mailAccount.defaultIfEmpty(); + } + // --------------------------------------------------------------- Constructor end + + // --------------------------------------------------------------- Getters and Setters start + /** + * 设置收件人 + * + * @param tos 收件人列表 + * @return this + * @see #setTos(String...) + */ + public Mail to(String... tos) { + return setTos(tos); + } + + /** + * 设置多个收件人 + * + * @param tos 收件人列表 + * @return this + */ + public Mail setTos(String... tos) { + this.tos = tos; + return this; + } + + /** + * 设置多个抄送人(carbon copy) + * + * @param ccs 抄送人列表 + * @return this + * @since 4.0.3 + */ + public Mail setCcs(String... ccs) { + this.ccs = ccs; + return this; + } + + /** + * 设置多个密送人(blind carbon copy) + * + * @param bccs 密送人列表 + * @return this + * @since 4.0.3 + */ + public Mail setBccs(String... bccs) { + this.bccs = bccs; + return this; + } + + /** + * 设置多个回复地址(reply-to) + * + * @param reply 回复地址(reply-to)列表 + * @return this + * @since 4.6.0 + */ + public Mail setReply(String... reply) { + this.reply = reply; + return this; + } + + /** + * 设置标题 + * + * @param title 标题 + * @return this + */ + public Mail setTitle(String title) { + this.title = title; + return this; + } + + /** + * 设置正文 + * + * @param content 正文 + * @return this + */ + public Mail setContent(String content) { + this.content = content; + return this; + } + + /** + * 设置是否是HTML + * + * @param isHtml 是否为HTML + * @return this + */ + public Mail setHtml(boolean isHtml) { + this.isHtml = isHtml; + return this; + } + + /** + * 设置文件类型附件 + * + * @param files 附件文件列表 + * @return this + */ + public Mail setFiles(File... files) { + if(ArrayUtil.isEmpty(files)) { + return this; + } + + final DataSource[] attachments = new DataSource[files.length]; + for (int i = 0; i < files.length; i++) { + attachments[i] = new FileDataSource(files[i]); + } + return setAttachments(attachments); + } + + /** + * 设置附件,附件使用{@link DataSource} 形式表示,可以使用{@link FileDataSource}包装文件表示文件附件 + * + * @param attachments 附件列表 + * @return this + * @since 4.0.9 + */ + public Mail setAttachments(DataSource... attachments) { + if(ArrayUtil.isNotEmpty(attachments)) { + this.attachments = attachments; + } + return this; + } + + /** + * 设置图片,图片的键对应到邮件模板中的占位字符串 + * + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + */ + public Mail setImageMap(Map imageMap) { + if (imageMap != null && imageMap.size() > 0) { + this.imageMap = imageMap; + } + return this; + } + + /** + * 设置字符集编码 + * + * @param charset 字符集编码 + * @return this + * @see MailAccount#setCharset(Charset) + */ + public Mail setCharset(Charset charset) { + this.mailAccount.setCharset(charset); + return this; + } + + /** + * 设置是否使用全局会话,默认为true + * + * @param isUseGlobalSession 是否使用全局会话,默认为true + * @return this + * @since 4.0.2 + */ + public Mail setUseGlobalSession(boolean isUseGlobalSession) { + this.useGlobalSession = isUseGlobalSession; + return this; + } + // --------------------------------------------------------------- Getters and Setters end + + /** + * 发送 + * + * @return this + * @throws MailException 邮件发送异常 + */ + public Mail send() throws MailException { + try { + return doSend(); + } catch (MessagingException e) { + throw new MailException(e); + } + } + + // --------------------------------------------------------------- Private method start + /** + * 执行发送 + * + * @return this + * @throws MessagingException 发送异常 + */ + private Mail doSend() throws MessagingException { + Transport.send(buildMsg()); + return this; + } + + /** + * 构建消息 + * + * @return {@link MimeMessage}消息 + * @throws MessagingException 消息异常 + */ + private MimeMessage buildMsg() throws MessagingException { + final Charset charset = this.mailAccount.getCharset(); + final MimeMessage msg = new MimeMessage(getSession(this.useGlobalSession)); + // 发件人 + final String from = this.mailAccount.getFrom(); + if (StrUtil.isEmpty(from)) { + // 用户未提供发送方,则从Session中自动获取 + msg.setFrom(); + } else { + msg.setFrom(InternalMailUtil.parseFirstAddress(from, charset)); + } + // 标题 + msg.setSubject(this.title, charset.name()); + // 发送时间 + msg.setSentDate(new Date()); + // 内容和附件 + msg.setContent(buildContent(charset)); + // 收件人 + msg.setRecipients(MimeMessage.RecipientType.TO, InternalMailUtil.parseAddressFromStrs(this.tos, charset)); + // 抄送人 + if (ArrayUtil.isNotEmpty(this.ccs)) { + msg.setRecipients(MimeMessage.RecipientType.CC, InternalMailUtil.parseAddressFromStrs(this.ccs, charset)); + } + // 密送人 + if (ArrayUtil.isNotEmpty(this.bccs)) { + msg.setRecipients(MimeMessage.RecipientType.BCC, InternalMailUtil.parseAddressFromStrs(this.bccs, charset)); + } + // 回复地址(reply-to) + if (ArrayUtil.isNotEmpty(this.reply)) { + msg.setReplyTo(InternalMailUtil.parseAddressFromStrs(this.reply, charset)); + } + + return msg; + } + + /** + * 构建邮件信息主体 + * + * @param charset 编码 + * @return 邮件信息主体 + * @throws MessagingException 消息异常 + */ + private Multipart buildContent(Charset charset) throws MessagingException { + final Multipart mainPart = new MimeMultipart(); + + // 正文 + final BodyPart body = new MimeBodyPart(); + body.setContent(content, StrUtil.format("text/{}; charset={}", isHtml ? "html" : "plain", charset)); + mainPart.addBodyPart(body); + + // 附件 + if (ArrayUtil.isNotEmpty(this.attachments)) { + BodyPart bodyPart; + for (DataSource attachment : attachments) { + bodyPart = new MimeBodyPart(); + bodyPart.setDataHandler(new DataHandler(attachment)); + bodyPart.setFileName(InternalMailUtil.encodeText(attachment.getName(), charset)); + mainPart.addBodyPart(bodyPart); + } + } + + // 图片 + for (Map.Entry entry : imageMap.entrySet()) { + BodyPart messageBodyPart = new MimeBodyPart(); + DataSource ds; + try { + ds = new ByteArrayDataSource(entry.getValue(), "image/jpeg"); + } catch (IOException e) { + throw new MailException(e); + } + + messageBodyPart.setDataHandler(new DataHandler(ds)); + messageBodyPart.setHeader("Content-ID", String.format("<%s>", entry.getKey())); + // add it + mainPart.addBodyPart(messageBodyPart); + } + + return mainPart; + } + + /** + * 获取默认邮件会话
+ * 如果为全局单例的会话,则全局只允许一个邮件帐号,否则每次发送邮件会新建一个新的会话 + * + * @param isSingleton 是否使用单例Session + * @return 邮件会话 {@link Session} + * @since 4.0.2 + */ + private Session getSession(boolean isSingleton) { + final MailAccount mailAccount = this.mailAccount; + Authenticator authenticator = null; + if (mailAccount.isAuth()) { + authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); + } + + return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) // + : Session.getInstance(mailAccount.getSmtpProps(), authenticator); + } + // --------------------------------------------------------------- Private method end +} diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailUtil.java index bb54fd5f3..25481863b 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailUtil.java @@ -1,236 +1,382 @@ -package cn.hutool.extra.mail; - -import java.io.File; -import java.util.Collection; -import java.util.List; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.StrUtil; - -/** - * 邮件工具类,基于javax.mail封装 - * - * @author looly - * @since 3.1.2 - */ -public class MailUtil { - - /** - * 使用配置文件中设置的账户发送文本邮件,发送给单个或多个收件人
- * 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔 - * - * @param to 收件人 - * @param subject 标题 - * @param content 正文 - * @param files 附件列表 - * @since 3.2.0 - */ - public static void sendText(String to, String subject, String content, File... files) { - send(to, subject, content, false, files); - } - - /** - * 使用配置文件中设置的账户发送HTML邮件,发送给单个或多个收件人
- * 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔 - * - * @param to 收件人 - * @param subject 标题 - * @param content 正文 - * @param files 附件列表 - * @since 3.2.0 - */ - public static void sendHtml(String to, String subject, String content, File... files) { - send(to, subject, content, true, files); - } - - /** - * 使用配置文件中设置的账户发送邮件,发送单个或多个收件人
- * 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔 - * - * @param to 收件人 - * @param subject 标题 - * @param content 正文 - * @param isHtml 是否为HTML - * @param files 附件列表 - */ - public static void send(String to, String subject, String content, boolean isHtml, File... files) { - send(splitAddress(to), subject, content, isHtml, files); - } - - /** - * 使用配置文件中设置的账户发送邮件,发送单个或多个收件人
- * 多个收件人、抄送人、密送人可以使用逗号“,”分隔,也可以通过分号“;”分隔 - * - * @param to 收件人,可以使用逗号“,”分隔,也可以通过分号“;”分隔 - * @param cc 抄送人,可以使用逗号“,”分隔,也可以通过分号“;”分隔 - * @param bcc 密送人,可以使用逗号“,”分隔,也可以通过分号“;”分隔 - * @param subject 标题 - * @param content 正文 - * @param isHtml 是否为HTML - * @param files 附件列表 - * @since 4.0.3 - */ - public static void send(String to, String cc, String bcc, String subject, String content, boolean isHtml, File... files) { - send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, isHtml, files); - } - - /** - * 使用配置文件中设置的账户发送文本邮件,发送给多人 - * - * @param tos 收件人列表 - * @param subject 标题 - * @param content 正文 - * @param files 附件列表 - */ - public static void sendText(Collection tos, String subject, String content, File... files) { - send(tos, subject, content, false, files); - } - - /** - * 使用配置文件中设置的账户发送HTML邮件,发送给多人 - * - * @param tos 收件人列表 - * @param subject 标题 - * @param content 正文 - * @param files 附件列表 - * @since 3.2.0 - */ - public static void sendHtml(Collection tos, String subject, String content, File... files) { - send(tos, subject, content, true, files); - } - - /** - * 使用配置文件中设置的账户发送邮件,发送给多人 - * - * @param tos 收件人列表 - * @param subject 标题 - * @param content 正文 - * @param isHtml 是否为HTML - * @param files 附件列表 - */ - public static void send(Collection tos, String subject, String content, boolean isHtml, File... files) { - send(tos, null, null, subject, content, isHtml, files); - } - - /** - * 使用配置文件中设置的账户发送邮件,发送给多人 - * - * @param tos 收件人列表 - * @param ccs 抄送人列表,可以为null或空 - * @param bccs 密送人列表,可以为null或空 - * @param subject 标题 - * @param content 正文 - * @param isHtml 是否为HTML - * @param files 附件列表 - * @since 4.0.3 - */ - public static void send(Collection tos, Collection ccs, Collection bccs, String subject, String content, boolean isHtml, File... files) { - send(GlobalMailAccount.INSTANCE.getAccount(), true, tos, ccs, bccs, subject, content, isHtml, files); - } - - //------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount - /** - * 发送邮件给多人 - * - * @param mailAccount 邮件认证对象 - * @param to 收件人,多个收件人逗号或者分号隔开 - * @param subject 标题 - * @param content 正文 - * @param isHtml 是否为HTML格式 - * @param files 附件列表 - * @since 3.2.0 - */ - public static void send(MailAccount mailAccount, String to, String subject, String content, boolean isHtml, File... files) { - send(mailAccount, splitAddress(to), subject, content, isHtml, files); - } - - /** - * 发送邮件给多人 - * - * @param mailAccount 邮件帐户信息 - * @param tos 收件人列表 - * @param subject 标题 - * @param content 正文 - * @param isHtml 是否为HTML格式 - * @param files 附件列表 - */ - public static void send(MailAccount mailAccount, Collection tos, String subject, String content, boolean isHtml, File... files) { - send(mailAccount, tos, null, null, subject, content, isHtml, files); - } - - /** - * 发送邮件给多人 - * - * @param mailAccount 邮件帐户信息 - * @param tos 收件人列表 - * @param ccs 抄送人列表,可以为null或空 - * @param bccs 密送人列表,可以为null或空 - * @param subject 标题 - * @param content 正文 - * @param isHtml 是否为HTML格式 - * @param files 附件列表 - * @since 4.0.3 - */ - public static void send(MailAccount mailAccount, Collection tos, Collection ccs, Collection bccs, String subject, String content, boolean isHtml, File... files) { - send(mailAccount, false, tos, ccs, bccs, subject, content, isHtml, files); - } - - //------------------------------------------------------------------------------------------------------------------------ Private method start - /** - * 发送邮件给多人 - * - * @param mailAccount 邮件帐户信息 - * @param useGlobalSession 是否全局共享Session - * @param tos 收件人列表 - * @param ccs 抄送人列表,可以为null或空 - * @param bccs 密送人列表,可以为null或空 - * @param subject 标题 - * @param content 正文 - * @param isHtml 是否为HTML格式 - * @param files 附件列表 - * @since 4.0.3 - */ - private static void send(MailAccount mailAccount, boolean useGlobalSession, Collection tos, Collection ccs, Collection bccs, String subject, String content, boolean isHtml, File... files) { - final Mail mail = Mail.create(mailAccount).setUseGlobalSession(useGlobalSession); - - //可选抄送人 - if(CollUtil.isNotEmpty(ccs)) { - mail.setCcs(ccs.toArray(new String[ccs.size()])); - } - //可选密送人 - if(CollUtil.isNotEmpty(bccs)) { - mail.setBccs(bccs.toArray(new String[bccs.size()])); - } - - mail.setTos(tos.toArray(new String[tos.size()])); - mail.setTitle(subject); - mail.setContent(content); - mail.setHtml(isHtml); - mail.setFiles(files); - - mail.send(); - } - - /** - * 将多个联系人转为列表,分隔符为逗号或者分号 - * - * @param addresses 多个联系人,如果为空返回null - * @return 联系人列表 - */ - private static List splitAddress(String addresses){ - if(StrUtil.isBlank(addresses)) { - return null; - } - - List result; - if(StrUtil.contains(addresses, ',')) { - result = StrUtil.splitTrim(addresses, ','); - }else if(StrUtil.contains(addresses, ';')) { - result = StrUtil.splitTrim(addresses, ';'); - }else { - result = CollUtil.newArrayList(addresses); - } - return result; - } - //------------------------------------------------------------------------------------------------------------------------ Private method end -} +package cn.hutool.extra.mail; + +import java.io.File; +import java.io.InputStream; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; + +/** + * 邮件工具类,基于javax.mail封装 + * + * @author looly + * @since 3.1.2 + */ +public class MailUtil { + /** + * 使用配置文件中设置的账户发送文本邮件,发送给单个或多个收件人
+ * 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * + * @param to 收件人 + * @param subject 标题 + * @param content 正文 + * @param files 附件列表 + * @since 3.2.0 + */ + public static void sendText(String to, String subject, String content, File... files) { + send(to, subject, content, false, files); + } + + /** + * 使用配置文件中设置的账户发送HTML邮件,发送给单个或多个收件人
+ * 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * + * @param to 收件人 + * @param subject 标题 + * @param content 正文 + * @param files 附件列表 + * @since 3.2.0 + */ + public static void sendHtml(String to, String subject, String content, File... files) { + send(to, subject, content, true, files); + } + + /** + * 使用配置文件中设置的账户发送邮件,发送单个或多个收件人
+ * 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * + * @param to 收件人 + * @param subject 标题 + * @param content 正文 + * @param isHtml 是否为HTML + * @param files 附件列表 + */ + public static void send(String to, String subject, String content, boolean isHtml, File... files) { + send(splitAddress(to), subject, content, isHtml, files); + } + + /** + * 使用配置文件中设置的账户发送邮件,发送单个或多个收件人
+ * 多个收件人、抄送人、密送人可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * + * @param to 收件人,可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * @param cc 抄送人,可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * @param bcc 密送人,可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * @param subject 标题 + * @param content 正文 + * @param isHtml 是否为HTML + * @param files 附件列表 + * @since 4.0.3 + */ + public static void send(String to, String cc, String bcc, String subject, String content, boolean isHtml, File... files) { + send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, isHtml, files); + } + + /** + * 使用配置文件中设置的账户发送文本邮件,发送给多人 + * + * @param tos 收件人列表 + * @param subject 标题 + * @param content 正文 + * @param files 附件列表 + */ + public static void sendText(Collection tos, String subject, String content, File... files) { + send(tos, subject, content, false, files); + } + + /** + * 使用配置文件中设置的账户发送HTML邮件,发送给多人 + * + * @param tos 收件人列表 + * @param subject 标题 + * @param content 正文 + * @param files 附件列表 + * @since 3.2.0 + */ + public static void sendHtml(Collection tos, String subject, String content, File... files) { + send(tos, subject, content, true, files); + } + + /** + * 使用配置文件中设置的账户发送邮件,发送给多人 + * + * @param tos 收件人列表 + * @param subject 标题 + * @param content 正文 + * @param isHtml 是否为HTML + * @param files 附件列表 + */ + public static void send(Collection tos, String subject, String content, boolean isHtml, File... files) { + send(tos, null, null, subject, content, isHtml, files); + } + + /** + * 使用配置文件中设置的账户发送邮件,发送给多人 + * + * @param tos 收件人列表 + * @param ccs 抄送人列表,可以为null或空 + * @param bccs 密送人列表,可以为null或空 + * @param subject 标题 + * @param content 正文 + * @param isHtml 是否为HTML + * @param files 附件列表 + * @since 4.0.3 + */ + public static void send(Collection tos, Collection ccs, Collection bccs, String subject, String content, boolean isHtml, File... files) { + send(GlobalMailAccount.INSTANCE.getAccount(), true, tos, ccs, bccs, subject, content, null, isHtml, files); + } + + //------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount + /** + * 发送邮件给多人 + * + * @param mailAccount 邮件认证对象 + * @param to 收件人,多个收件人逗号或者分号隔开 + * @param subject 标题 + * @param content 正文 + * @param isHtml 是否为HTML格式 + * @param files 附件列表 + * @since 3.2.0 + */ + public static void send(MailAccount mailAccount, String to, String subject, String content, boolean isHtml, File... files) { + send(mailAccount, splitAddress(to), subject, content, isHtml, files); + } + + /** + * 发送邮件给多人 + * + * @param mailAccount 邮件帐户信息 + * @param tos 收件人列表 + * @param subject 标题 + * @param content 正文 + * @param isHtml 是否为HTML格式 + * @param files 附件列表 + */ + public static void send(MailAccount mailAccount, Collection tos, String subject, String content, boolean isHtml, File... files) { + send(mailAccount, tos, null, null, subject, content, isHtml, files); + } + + /** + * 发送邮件给多人 + * + * @param mailAccount 邮件帐户信息 + * @param tos 收件人列表 + * @param ccs 抄送人列表,可以为null或空 + * @param bccs 密送人列表,可以为null或空 + * @param subject 标题 + * @param content 正文 + * @param isHtml 是否为HTML格式 + * @param files 附件列表 + * @since 4.0.3 + */ + public static void send(MailAccount mailAccount, Collection tos, Collection ccs, Collection bccs, String subject, String content, boolean isHtml, File... files) { + send(mailAccount, false, tos, ccs, bccs, subject, content, null, isHtml, files); + } + + /** + * 使用配置文件中设置的账户发送HTML邮件,发送给单个或多个收件人
+ * 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * + * @param to 收件人 + * @param subject 标题 + * @param content 正文 + * @param files 附件列表 + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + * @since 3.2.0 + */ + public static void sendHtml(String to, String subject, String content, Map imageMap, File... files) { + send(to, subject, content, imageMap, true, files); + } + + /** + * 使用配置文件中设置的账户发送邮件,发送单个或多个收件人
+ * 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * + * @param to 收件人 + * @param subject 标题 + * @param content 正文 + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + * @param isHtml 是否为HTML + * @param files 附件列表 + */ + public static void send(String to, String subject, String content, Map imageMap, boolean isHtml, File... files) { + send(splitAddress(to), subject, content, imageMap, isHtml, files); + } + + /** + * 使用配置文件中设置的账户发送邮件,发送单个或多个收件人
+ * 多个收件人、抄送人、密送人可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * + * @param to 收件人,可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * @param cc 抄送人,可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * @param bcc 密送人,可以使用逗号“,”分隔,也可以通过分号“;”分隔 + * @param subject 标题 + * @param content 正文 + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + * @param isHtml 是否为HTML + * @param files 附件列表 + * @since 4.0.3 + */ + public static void send(String to, String cc, String bcc, String subject, String content, Map imageMap, boolean isHtml, File... files) { + send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, imageMap, isHtml, files); + } + + /** + * 使用配置文件中设置的账户发送HTML邮件,发送给多人 + * + * @param tos 收件人列表 + * @param subject 标题 + * @param content 正文 + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + * @param files 附件列表 + * @since 3.2.0 + */ + public static void sendHtml(Collection tos, String subject, String content, Map imageMap, File... files) { + send(tos, subject, content, imageMap, true, files); + } + + /** + * 使用配置文件中设置的账户发送邮件,发送给多人 + * + * @param tos 收件人列表 + * @param subject 标题 + * @param content 正文 + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + * @param isHtml 是否为HTML + * @param files 附件列表 + */ + public static void send(Collection tos, String subject, String content, Map imageMap, boolean isHtml, File... files) { + send(tos, null, null, subject, content, imageMap, isHtml, files); + } + + /** + * 使用配置文件中设置的账户发送邮件,发送给多人 + * + * @param tos 收件人列表 + * @param ccs 抄送人列表,可以为null或空 + * @param bccs 密送人列表,可以为null或空 + * @param subject 标题 + * @param content 正文 + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + * @param isHtml 是否为HTML + * @param files 附件列表 + * @since 4.0.3 + */ + public static void send(Collection tos, Collection ccs, Collection bccs, String subject, String content, Map imageMap, boolean isHtml, File... files) { + send(GlobalMailAccount.INSTANCE.getAccount(), true, tos, ccs, bccs, subject, content, imageMap, isHtml, files); + } + + //------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount + /** + * 发送邮件给多人 + * + * @param mailAccount 邮件认证对象 + * @param to 收件人,多个收件人逗号或者分号隔开 + * @param subject 标题 + * @param content 正文 + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + * @param isHtml 是否为HTML格式 + * @param files 附件列表 + * @since 3.2.0 + */ + public static void send(MailAccount mailAccount, String to, String subject, String content, Map imageMap, boolean isHtml, File... files) { + send(mailAccount, splitAddress(to), subject, content, imageMap, isHtml, files); + } + + /** + * 发送邮件给多人 + * + * @param mailAccount 邮件帐户信息 + * @param tos 收件人列表 + * @param subject 标题 + * @param content 正文 + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + * @param isHtml 是否为HTML格式 + * @param files 附件列表 + */ + public static void send(MailAccount mailAccount, Collection tos, String subject, String content, Map imageMap, boolean isHtml, File... files) { + send(mailAccount, tos, null, null, subject, content, imageMap, isHtml, files); + } + + /** + * 发送邮件给多人 + * + * @param mailAccount 邮件帐户信息 + * @param tos 收件人列表 + * @param ccs 抄送人列表,可以为null或空 + * @param bccs 密送人列表,可以为null或空 + * @param subject 标题 + * @param content 正文 + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + * @param isHtml 是否为HTML格式 + * @param files 附件列表 + * @since 4.0.3 + */ + public static void send(MailAccount mailAccount, Collection tos, Collection ccs, Collection bccs, String subject, String content, Map imageMap, boolean isHtml, File... files) { + send(mailAccount, false, tos, ccs, bccs, subject, content, imageMap, isHtml, files); + } + + //------------------------------------------------------------------------------------------------------------------------ Private method start + /** + * 发送邮件给多人 + * + * @param mailAccount 邮件帐户信息 + * @param useGlobalSession 是否全局共享Session + * @param tos 收件人列表 + * @param ccs 抄送人列表,可以为null或空 + * @param bccs 密送人列表,可以为null或空 + * @param subject 标题 + * @param content 正文 + * @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER + * @param isHtml 是否为HTML格式 + * @param files 附件列表 + * @since 4.0.3 + */ + private static void send(MailAccount mailAccount, boolean useGlobalSession, Collection tos, Collection ccs, Collection bccs, String subject, String content, Map imageMap, boolean isHtml, File... files) { + final Mail mail = Mail.create(mailAccount).setUseGlobalSession(useGlobalSession); + + //可选抄送人 + if(CollUtil.isNotEmpty(ccs)) { + mail.setCcs(ccs.toArray(new String[ccs.size()])); + } + //可选密送人 + if(CollUtil.isNotEmpty(bccs)) { + mail.setBccs(bccs.toArray(new String[bccs.size()])); + } + + mail.setTos(tos.toArray(new String[tos.size()])); + mail.setTitle(subject); + mail.setContent(content); + mail.setHtml(isHtml); + mail.setFiles(files); + mail.setImageMap(imageMap); + + mail.send(); + } + + /** + * 将多个联系人转为列表,分隔符为逗号或者分号 + * + * @param addresses 多个联系人,如果为空返回null + * @return 联系人列表 + */ + private static List splitAddress(String addresses){ + if(StrUtil.isBlank(addresses)) { + return null; + } + + List result; + if(StrUtil.contains(addresses, ',')) { + result = StrUtil.splitTrim(addresses, ','); + }else if(StrUtil.contains(addresses, ';')) { + result = StrUtil.splitTrim(addresses, ';'); + }else { + result = CollUtil.newArrayList(addresses); + } + return result; + } + //------------------------------------------------------------------------------------------------------------------------ Private method end +}