update 优化 邮件工具代码格式

This commit is contained in:
疯狂的狮子li 2023-04-14 14:20:57 +08:00
parent 4e911a1a98
commit 44a796ed57
7 changed files with 1203 additions and 1203 deletions

View File

@ -6,42 +6,41 @@ import cn.hutool.core.io.IORuntimeException;
* 全局邮件帐户依赖于邮件配置文件{@link MailAccount#MAIL_SETTING_PATHS} * 全局邮件帐户依赖于邮件配置文件{@link MailAccount#MAIL_SETTING_PATHS}
* *
* @author looly * @author looly
*
*/ */
public enum GlobalMailAccount { public enum GlobalMailAccount {
INSTANCE; INSTANCE;
private final MailAccount mailAccount; private final MailAccount mailAccount;
/** /**
* 构造 * 构造
*/ */
GlobalMailAccount() { GlobalMailAccount() {
mailAccount = createDefaultAccount(); mailAccount = createDefaultAccount();
} }
/** /**
* 获得邮件帐户 * 获得邮件帐户
* *
* @return 邮件帐户 * @return 邮件帐户
*/ */
public MailAccount getAccount() { public MailAccount getAccount() {
return this.mailAccount; return this.mailAccount;
} }
/** /**
* 创建默认帐户 * 创建默认帐户
* *
* @return MailAccount * @return MailAccount
*/ */
private MailAccount createDefaultAccount() { private MailAccount createDefaultAccount() {
for (String mailSettingPath : MailAccount.MAIL_SETTING_PATHS) { for (String mailSettingPath : MailAccount.MAIL_SETTING_PATHS) {
try { try {
return new MailAccount(mailSettingPath); return new MailAccount(mailSettingPath);
} catch (IORuntimeException ignore) { } catch (IORuntimeException ignore) {
//ignore //ignore
} }
} }
return null; return null;
} }
} }

View File

@ -13,95 +13,96 @@ import java.util.List;
/** /**
* 邮件内部工具类 * 邮件内部工具类
*
* @author looly * @author looly
* @since 3.2.3 * @since 3.2.3
*/ */
public class InternalMailUtil { public class InternalMailUtil {
/** /**
* 将多个字符串邮件地址转为{@link InternetAddress}列表<br> * 将多个字符串邮件地址转为{@link InternetAddress}列表<br>
* 单个字符串地址可以是多个地址合并的字符串 * 单个字符串地址可以是多个地址合并的字符串
* *
* @param addrStrs 地址数组 * @param addrStrs 地址数组
* @param charset 编码主要用于中文用户名的编码 * @param charset 编码主要用于中文用户名的编码
* @return 地址数组 * @return 地址数组
* @since 4.0.3 * @since 4.0.3
*/ */
public static InternetAddress[] parseAddressFromStrs(String[] addrStrs, Charset charset) { public static InternetAddress[] parseAddressFromStrs(String[] addrStrs, Charset charset) {
final List<InternetAddress> resultList = new ArrayList<>(addrStrs.length); final List<InternetAddress> resultList = new ArrayList<>(addrStrs.length);
InternetAddress[] addrs; InternetAddress[] addrs;
for (String addrStr : addrStrs) { for (String addrStr : addrStrs) {
addrs = parseAddress(addrStr, charset); addrs = parseAddress(addrStr, charset);
if (ArrayUtil.isNotEmpty(addrs)) { if (ArrayUtil.isNotEmpty(addrs)) {
Collections.addAll(resultList, addrs); Collections.addAll(resultList, addrs);
} }
} }
return resultList.toArray(new InternetAddress[0]); return resultList.toArray(new InternetAddress[0]);
} }
/** /**
* 解析第一个地址 * 解析第一个地址
* *
* @param address 地址字符串 * @param address 地址字符串
* @param charset 编码{@code null}表示使用系统属性定义的编码或系统编码 * @param charset 编码{@code null}表示使用系统属性定义的编码或系统编码
* @return 地址列表 * @return 地址列表
*/ */
public static InternetAddress parseFirstAddress(String address, Charset charset) { public static InternetAddress parseFirstAddress(String address, Charset charset) {
final InternetAddress[] internetAddresses = parseAddress(address, charset); final InternetAddress[] internetAddresses = parseAddress(address, charset);
if (ArrayUtil.isEmpty(internetAddresses)) { if (ArrayUtil.isEmpty(internetAddresses)) {
try { try {
return new InternetAddress(address); return new InternetAddress(address);
} catch (AddressException e) { } catch (AddressException e) {
throw new MailException(e); throw new MailException(e);
} }
} }
return internetAddresses[0]; return internetAddresses[0];
} }
/** /**
* 将一个地址字符串解析为多个地址<br> * 将一个地址字符串解析为多个地址<br>
* 地址间使用" "","";"分隔 * 地址间使用" "","";"分隔
* *
* @param address 地址字符串 * @param address 地址字符串
* @param charset 编码{@code null}表示使用系统属性定义的编码或系统编码 * @param charset 编码{@code null}表示使用系统属性定义的编码或系统编码
* @return 地址列表 * @return 地址列表
*/ */
public static InternetAddress[] parseAddress(String address, Charset charset) { public static InternetAddress[] parseAddress(String address, Charset charset) {
InternetAddress[] addresses; InternetAddress[] addresses;
try { try {
addresses = InternetAddress.parse(address); addresses = InternetAddress.parse(address);
} catch (AddressException e) { } catch (AddressException e) {
throw new MailException(e); throw new MailException(e);
} }
//编码用户名 //编码用户名
if (ArrayUtil.isNotEmpty(addresses)) { if (ArrayUtil.isNotEmpty(addresses)) {
final String charsetStr = null == charset ? null : charset.name(); final String charsetStr = null == charset ? null : charset.name();
for (InternetAddress internetAddress : addresses) { for (InternetAddress internetAddress : addresses) {
try { try {
internetAddress.setPersonal(internetAddress.getPersonal(), charsetStr); internetAddress.setPersonal(internetAddress.getPersonal(), charsetStr);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new MailException(e); throw new MailException(e);
} }
} }
} }
return addresses; return addresses;
} }
/** /**
* 编码中文字符<br> * 编码中文字符<br>
* 编码失败返回原字符串 * 编码失败返回原字符串
* *
* @param text 被编码的文本 * @param text 被编码的文本
* @param charset 编码 * @param charset 编码
* @return 编码后的结果 * @return 编码后的结果
*/ */
public static String encodeText(String text, Charset charset) { public static String encodeText(String text, Charset charset) {
try { try {
return MimeUtility.encodeText(text, charset.name(), null); return MimeUtility.encodeText(text, charset.name(), null);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
// ignore // ignore
} }
return text; return text;
} }
} }

View File

@ -32,452 +32,452 @@ public class Mail implements Builder<MimeMessage> {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 邮箱帐户信息以及一些客户端配置信息 * 邮箱帐户信息以及一些客户端配置信息
*/ */
private final MailAccount mailAccount; private final MailAccount mailAccount;
/** /**
* 收件人列表 * 收件人列表
*/ */
private String[] tos; private String[] tos;
/** /**
* 抄送人列表carbon copy * 抄送人列表carbon copy
*/ */
private String[] ccs; private String[] ccs;
/** /**
* 密送人列表blind carbon copy * 密送人列表blind carbon copy
*/ */
private String[] bccs; private String[] bccs;
/** /**
* 回复地址(reply-to) * 回复地址(reply-to)
*/ */
private String[] reply; private String[] reply;
/** /**
* 标题 * 标题
*/ */
private String title; private String title;
/** /**
* 内容 * 内容
*/ */
private String content; private String content;
/** /**
* 是否为HTML * 是否为HTML
*/ */
private boolean isHtml; private boolean isHtml;
/** /**
* 正文附件和图片的混合部分 * 正文附件和图片的混合部分
*/ */
private final Multipart multipart = new MimeMultipart(); private final Multipart multipart = new MimeMultipart();
/** /**
* 是否使用全局会话默认为false * 是否使用全局会话默认为false
*/ */
private boolean useGlobalSession = false; private boolean useGlobalSession = false;
/** /**
* debug输出位置可以自定义debug日志 * debug输出位置可以自定义debug日志
*/ */
private PrintStream debugOutput; private PrintStream debugOutput;
/** /**
* 创建邮件客户端 * 创建邮件客户端
* *
* @param mailAccount 邮件帐号 * @param mailAccount 邮件帐号
* @return Mail * @return Mail
*/ */
public static Mail create(MailAccount mailAccount) { public static Mail create(MailAccount mailAccount) {
return new Mail(mailAccount); return new Mail(mailAccount);
} }
/** /**
* 创建邮件客户端使用全局邮件帐户 * 创建邮件客户端使用全局邮件帐户
* *
* @return Mail * @return Mail
*/ */
public static Mail create() { public static Mail create() {
return new Mail(); return new Mail();
} }
// --------------------------------------------------------------- Constructor start // --------------------------------------------------------------- Constructor start
/** /**
* 构造使用全局邮件帐户 * 构造使用全局邮件帐户
*/ */
public Mail() { public Mail() {
this(GlobalMailAccount.INSTANCE.getAccount()); this(GlobalMailAccount.INSTANCE.getAccount());
} }
/** /**
* 构造 * 构造
* *
* @param mailAccount 邮件帐户如果为null使用默认配置文件的全局邮件配置 * @param mailAccount 邮件帐户如果为null使用默认配置文件的全局邮件配置
*/ */
public Mail(MailAccount mailAccount) { public Mail(MailAccount mailAccount) {
mailAccount = (null != mailAccount) ? mailAccount : GlobalMailAccount.INSTANCE.getAccount(); mailAccount = (null != mailAccount) ? mailAccount : GlobalMailAccount.INSTANCE.getAccount();
this.mailAccount = mailAccount.defaultIfEmpty(); this.mailAccount = mailAccount.defaultIfEmpty();
} }
// --------------------------------------------------------------- Constructor end // --------------------------------------------------------------- Constructor end
// --------------------------------------------------------------- Getters and Setters start // --------------------------------------------------------------- Getters and Setters start
/** /**
* 设置收件人 * 设置收件人
* *
* @param tos 收件人列表 * @param tos 收件人列表
* @return this * @return this
* @see #setTos(String...) * @see #setTos(String...)
*/ */
public Mail to(String... tos) { public Mail to(String... tos) {
return setTos(tos); return setTos(tos);
} }
/** /**
* 设置多个收件人 * 设置多个收件人
* *
* @param tos 收件人列表 * @param tos 收件人列表
* @return this * @return this
*/ */
public Mail setTos(String... tos) { public Mail setTos(String... tos) {
this.tos = tos; this.tos = tos;
return this; return this;
} }
/** /**
* 设置多个抄送人carbon copy * 设置多个抄送人carbon copy
* *
* @param ccs 抄送人列表 * @param ccs 抄送人列表
* @return this * @return this
* @since 4.0.3 * @since 4.0.3
*/ */
public Mail setCcs(String... ccs) { public Mail setCcs(String... ccs) {
this.ccs = ccs; this.ccs = ccs;
return this; return this;
} }
/** /**
* 设置多个密送人blind carbon copy * 设置多个密送人blind carbon copy
* *
* @param bccs 密送人列表 * @param bccs 密送人列表
* @return this * @return this
* @since 4.0.3 * @since 4.0.3
*/ */
public Mail setBccs(String... bccs) { public Mail setBccs(String... bccs) {
this.bccs = bccs; this.bccs = bccs;
return this; return this;
} }
/** /**
* 设置多个回复地址(reply-to) * 设置多个回复地址(reply-to)
* *
* @param reply 回复地址(reply-to)列表 * @param reply 回复地址(reply-to)列表
* @return this * @return this
* @since 4.6.0 * @since 4.6.0
*/ */
public Mail setReply(String... reply) { public Mail setReply(String... reply) {
this.reply = reply; this.reply = reply;
return this; return this;
} }
/** /**
* 设置标题 * 设置标题
* *
* @param title 标题 * @param title 标题
* @return this * @return this
*/ */
public Mail setTitle(String title) { public Mail setTitle(String title) {
this.title = title; this.title = title;
return this; return this;
} }
/** /**
* 设置正文<br> * 设置正文<br>
* 正文可以是普通文本也可以是HTML默认普通文本可以通过调用{@link #setHtml(boolean)} 设置是否为HTML * 正文可以是普通文本也可以是HTML默认普通文本可以通过调用{@link #setHtml(boolean)} 设置是否为HTML
* *
* @param content 正文 * @param content 正文
* @return this * @return this
*/ */
public Mail setContent(String content) { public Mail setContent(String content) {
this.content = content; this.content = content;
return this; return this;
} }
/** /**
* 设置是否是HTML * 设置是否是HTML
* *
* @param isHtml 是否为HTML * @param isHtml 是否为HTML
* @return this * @return this
*/ */
public Mail setHtml(boolean isHtml) { public Mail setHtml(boolean isHtml) {
this.isHtml = isHtml; this.isHtml = isHtml;
return this; return this;
} }
/** /**
* 设置正文 * 设置正文
* *
* @param content 正文内容 * @param content 正文内容
* @param isHtml 是否为HTML * @param isHtml 是否为HTML
* @return this * @return this
*/ */
public Mail setContent(String content, boolean isHtml) { public Mail setContent(String content, boolean isHtml) {
setContent(content); setContent(content);
return setHtml(isHtml); return setHtml(isHtml);
} }
/** /**
* 设置文件类型附件文件可以是图片文件此时自动设置cid正文中引用图片默认cid为文件名 * 设置文件类型附件文件可以是图片文件此时自动设置cid正文中引用图片默认cid为文件名
* *
* @param files 附件文件列表 * @param files 附件文件列表
* @return this * @return this
*/ */
public Mail setFiles(File... files) { public Mail setFiles(File... files) {
if (ArrayUtil.isEmpty(files)) { if (ArrayUtil.isEmpty(files)) {
return this; return this;
} }
final DataSource[] attachments = new DataSource[files.length]; final DataSource[] attachments = new DataSource[files.length];
for (int i = 0; i < files.length; i++) { for (int i = 0; i < files.length; i++) {
attachments[i] = new FileDataSource(files[i]); attachments[i] = new FileDataSource(files[i]);
} }
return setAttachments(attachments); return setAttachments(attachments);
} }
/** /**
* 增加附件或图片附件使用{@link DataSource} 形式表示可以使用{@link FileDataSource}包装文件表示文件附件 * 增加附件或图片附件使用{@link DataSource} 形式表示可以使用{@link FileDataSource}包装文件表示文件附件
* *
* @param attachments 附件列表 * @param attachments 附件列表
* @return this * @return this
* @since 4.0.9 * @since 4.0.9
*/ */
public Mail setAttachments(DataSource... attachments) { public Mail setAttachments(DataSource... attachments) {
if (ArrayUtil.isNotEmpty(attachments)) { if (ArrayUtil.isNotEmpty(attachments)) {
final Charset charset = this.mailAccount.getCharset(); final Charset charset = this.mailAccount.getCharset();
MimeBodyPart bodyPart; MimeBodyPart bodyPart;
String nameEncoded; String nameEncoded;
try { try {
for (DataSource attachment : attachments) { for (DataSource attachment : attachments) {
bodyPart = new MimeBodyPart(); bodyPart = new MimeBodyPart();
bodyPart.setDataHandler(new DataHandler(attachment)); bodyPart.setDataHandler(new DataHandler(attachment));
nameEncoded = attachment.getName(); nameEncoded = attachment.getName();
if (this.mailAccount.isEncodefilename()) { if (this.mailAccount.isEncodefilename()) {
nameEncoded = InternalMailUtil.encodeText(nameEncoded, charset); nameEncoded = InternalMailUtil.encodeText(nameEncoded, charset);
} }
// 普通附件文件名 // 普通附件文件名
bodyPart.setFileName(nameEncoded); bodyPart.setFileName(nameEncoded);
if (StrUtil.startWith(attachment.getContentType(), "image/")) { if (StrUtil.startWith(attachment.getContentType(), "image/")) {
// 图片附件用于正文中引用图片 // 图片附件用于正文中引用图片
bodyPart.setContentID(nameEncoded); bodyPart.setContentID(nameEncoded);
} }
this.multipart.addBodyPart(bodyPart); this.multipart.addBodyPart(bodyPart);
} }
} catch (MessagingException e) { } catch (MessagingException e) {
throw new MailException(e); throw new MailException(e);
} }
} }
return this; return this;
} }
/** /**
* 增加图片图片的键对应到邮件模板中的占位字符串图片类型默认为"image/jpeg" * 增加图片图片的键对应到邮件模板中的占位字符串图片类型默认为"image/jpeg"
* *
* @param cid 图片与占位符占位符格式为cid:${cid} * @param cid 图片与占位符占位符格式为cid:${cid}
* @param imageStream 图片文件 * @param imageStream 图片文件
* @return this * @return this
* @since 4.6.3 * @since 4.6.3
*/ */
public Mail addImage(String cid, InputStream imageStream) { public Mail addImage(String cid, InputStream imageStream) {
return addImage(cid, imageStream, null); return addImage(cid, imageStream, null);
} }
/** /**
* 增加图片图片的键对应到邮件模板中的占位字符串 * 增加图片图片的键对应到邮件模板中的占位字符串
* *
* @param cid 图片与占位符占位符格式为cid:${cid} * @param cid 图片与占位符占位符格式为cid:${cid}
* @param imageStream 图片流不关闭 * @param imageStream 图片流不关闭
* @param contentType 图片类型null赋值默认的"image/jpeg" * @param contentType 图片类型null赋值默认的"image/jpeg"
* @return this * @return this
* @since 4.6.3 * @since 4.6.3
*/ */
public Mail addImage(String cid, InputStream imageStream, String contentType) { public Mail addImage(String cid, InputStream imageStream, String contentType) {
ByteArrayDataSource imgSource; ByteArrayDataSource imgSource;
try { try {
imgSource = new ByteArrayDataSource(imageStream, ObjectUtil.defaultIfNull(contentType, "image/jpeg")); imgSource = new ByteArrayDataSource(imageStream, ObjectUtil.defaultIfNull(contentType, "image/jpeg"));
} catch (IOException e) { } catch (IOException e) {
throw new IORuntimeException(e); throw new IORuntimeException(e);
} }
imgSource.setName(cid); imgSource.setName(cid);
return setAttachments(imgSource); return setAttachments(imgSource);
} }
/** /**
* 增加图片图片的键对应到邮件模板中的占位字符串 * 增加图片图片的键对应到邮件模板中的占位字符串
* *
* @param cid 图片与占位符占位符格式为cid:${cid} * @param cid 图片与占位符占位符格式为cid:${cid}
* @param imageFile 图片文件 * @param imageFile 图片文件
* @return this * @return this
* @since 4.6.3 * @since 4.6.3
*/ */
public Mail addImage(String cid, File imageFile) { public Mail addImage(String cid, File imageFile) {
InputStream in = null; InputStream in = null;
try { try {
in = FileUtil.getInputStream(imageFile); in = FileUtil.getInputStream(imageFile);
return addImage(cid, in, FileTypeMap.getDefaultFileTypeMap().getContentType(imageFile)); return addImage(cid, in, FileTypeMap.getDefaultFileTypeMap().getContentType(imageFile));
} finally { } finally {
IoUtil.close(in); IoUtil.close(in);
} }
} }
/** /**
* 设置字符集编码 * 设置字符集编码
* *
* @param charset 字符集编码 * @param charset 字符集编码
* @return this * @return this
* @see MailAccount#setCharset(Charset) * @see MailAccount#setCharset(Charset)
*/ */
public Mail setCharset(Charset charset) { public Mail setCharset(Charset charset) {
this.mailAccount.setCharset(charset); this.mailAccount.setCharset(charset);
return this; return this;
} }
/** /**
* 设置是否使用全局会话默认为true * 设置是否使用全局会话默认为true
* *
* @param isUseGlobalSession 是否使用全局会话默认为true * @param isUseGlobalSession 是否使用全局会话默认为true
* @return this * @return this
* @since 4.0.2 * @since 4.0.2
*/ */
public Mail setUseGlobalSession(boolean isUseGlobalSession) { public Mail setUseGlobalSession(boolean isUseGlobalSession) {
this.useGlobalSession = isUseGlobalSession; this.useGlobalSession = isUseGlobalSession;
return this; return this;
} }
/** /**
* 设置debug输出位置可以自定义debug日志 * 设置debug输出位置可以自定义debug日志
* *
* @param debugOutput debug输出位置 * @param debugOutput debug输出位置
* @return this * @return this
* @since 5.5.6 * @since 5.5.6
*/ */
public Mail setDebugOutput(PrintStream debugOutput) { public Mail setDebugOutput(PrintStream debugOutput) {
this.debugOutput = debugOutput; this.debugOutput = debugOutput;
return this; return this;
} }
// --------------------------------------------------------------- Getters and Setters end // --------------------------------------------------------------- Getters and Setters end
@Override @Override
public MimeMessage build() { public MimeMessage build() {
try { try {
return buildMsg(); return buildMsg();
} catch (MessagingException e) { } catch (MessagingException e) {
throw new MailException(e); throw new MailException(e);
} }
} }
/** /**
* 发送 * 发送
* *
* @return message-id * @return message-id
* @throws MailException 邮件发送异常 * @throws MailException 邮件发送异常
*/ */
public String send() throws MailException { public String send() throws MailException {
try { try {
return doSend(); return doSend();
} catch (MessagingException e) { } catch (MessagingException e) {
if (e instanceof SendFailedException) { if (e instanceof SendFailedException) {
// 当地址无效时显示更加详细的无效地址信息 // 当地址无效时显示更加详细的无效地址信息
final Address[] invalidAddresses = ((SendFailedException) e).getInvalidAddresses(); final Address[] invalidAddresses = ((SendFailedException) e).getInvalidAddresses();
final String msg = StrUtil.format("Invalid Addresses: {}", ArrayUtil.toString(invalidAddresses)); final String msg = StrUtil.format("Invalid Addresses: {}", ArrayUtil.toString(invalidAddresses));
throw new MailException(msg, e); throw new MailException(msg, e);
} }
throw new MailException(e); throw new MailException(e);
} }
} }
// --------------------------------------------------------------- Private method start // --------------------------------------------------------------- Private method start
/** /**
* 执行发送 * 执行发送
* *
* @return message-id * @return message-id
* @throws MessagingException 发送异常 * @throws MessagingException 发送异常
*/ */
private String doSend() throws MessagingException { private String doSend() throws MessagingException {
final MimeMessage mimeMessage = buildMsg(); final MimeMessage mimeMessage = buildMsg();
Transport.send(mimeMessage); Transport.send(mimeMessage);
return mimeMessage.getMessageID(); return mimeMessage.getMessageID();
} }
/** /**
* 构建消息 * 构建消息
* *
* @return {@link MimeMessage}消息 * @return {@link MimeMessage}消息
* @throws MessagingException 消息异常 * @throws MessagingException 消息异常
*/ */
private MimeMessage buildMsg() throws MessagingException { private MimeMessage buildMsg() throws MessagingException {
final Charset charset = this.mailAccount.getCharset(); final Charset charset = this.mailAccount.getCharset();
final MimeMessage msg = new MimeMessage(getSession()); final MimeMessage msg = new MimeMessage(getSession());
// 发件人 // 发件人
final String from = this.mailAccount.getFrom(); final String from = this.mailAccount.getFrom();
if (StrUtil.isEmpty(from)) { if (StrUtil.isEmpty(from)) {
// 用户未提供发送方则从Session中自动获取 // 用户未提供发送方则从Session中自动获取
msg.setFrom(); msg.setFrom();
} else { } else {
msg.setFrom(InternalMailUtil.parseFirstAddress(from, charset)); msg.setFrom(InternalMailUtil.parseFirstAddress(from, charset));
} }
// 标题 // 标题
msg.setSubject(this.title, (null == charset) ? null : charset.name()); msg.setSubject(this.title, (null == charset) ? null : charset.name());
// 发送时间 // 发送时间
msg.setSentDate(new Date()); msg.setSentDate(new Date());
// 内容和附件 // 内容和附件
msg.setContent(buildContent(charset)); msg.setContent(buildContent(charset));
// 收件人 // 收件人
msg.setRecipients(MimeMessage.RecipientType.TO, InternalMailUtil.parseAddressFromStrs(this.tos, charset)); msg.setRecipients(MimeMessage.RecipientType.TO, InternalMailUtil.parseAddressFromStrs(this.tos, charset));
// 抄送人 // 抄送人
if (ArrayUtil.isNotEmpty(this.ccs)) { if (ArrayUtil.isNotEmpty(this.ccs)) {
msg.setRecipients(MimeMessage.RecipientType.CC, InternalMailUtil.parseAddressFromStrs(this.ccs, charset)); msg.setRecipients(MimeMessage.RecipientType.CC, InternalMailUtil.parseAddressFromStrs(this.ccs, charset));
} }
// 密送人 // 密送人
if (ArrayUtil.isNotEmpty(this.bccs)) { if (ArrayUtil.isNotEmpty(this.bccs)) {
msg.setRecipients(MimeMessage.RecipientType.BCC, InternalMailUtil.parseAddressFromStrs(this.bccs, charset)); msg.setRecipients(MimeMessage.RecipientType.BCC, InternalMailUtil.parseAddressFromStrs(this.bccs, charset));
} }
// 回复地址(reply-to) // 回复地址(reply-to)
if (ArrayUtil.isNotEmpty(this.reply)) { if (ArrayUtil.isNotEmpty(this.reply)) {
msg.setReplyTo(InternalMailUtil.parseAddressFromStrs(this.reply, charset)); msg.setReplyTo(InternalMailUtil.parseAddressFromStrs(this.reply, charset));
} }
return msg; return msg;
} }
/** /**
* 构建邮件信息主体 * 构建邮件信息主体
* *
* @param charset 编码{@code null}则使用{@link MimeUtility#getDefaultJavaCharset()} * @param charset 编码{@code null}则使用{@link MimeUtility#getDefaultJavaCharset()}
* @return 邮件信息主体 * @return 邮件信息主体
* @throws MessagingException 消息异常 * @throws MessagingException 消息异常
*/ */
private Multipart buildContent(Charset charset) throws MessagingException { private Multipart buildContent(Charset charset) throws MessagingException {
final String charsetStr = null != charset ? charset.name() : MimeUtility.getDefaultJavaCharset(); final String charsetStr = null != charset ? charset.name() : MimeUtility.getDefaultJavaCharset();
// 正文 // 正文
final MimeBodyPart body = new MimeBodyPart(); final MimeBodyPart body = new MimeBodyPart();
body.setContent(content, StrUtil.format("text/{}; charset={}", isHtml ? "html" : "plain", charsetStr)); body.setContent(content, StrUtil.format("text/{}; charset={}", isHtml ? "html" : "plain", charsetStr));
this.multipart.addBodyPart(body); this.multipart.addBodyPart(body);
return this.multipart; return this.multipart;
} }
/** /**
* 获取默认邮件会话<br> * 获取默认邮件会话<br>
* 如果为全局单例的会话则全局只允许一个邮件帐号否则每次发送邮件会新建一个新的会话 * 如果为全局单例的会话则全局只允许一个邮件帐号否则每次发送邮件会新建一个新的会话
* *
* @return 邮件会话 {@link Session} * @return 邮件会话 {@link Session}
*/ */
private Session getSession() { private Session getSession() {
final Session session = MailUtils.getSession(this.mailAccount, this.useGlobalSession); final Session session = MailUtils.getSession(this.mailAccount, this.useGlobalSession);
if (null != this.debugOutput) { if (null != this.debugOutput) {
session.setDebugOut(debugOutput); session.setDebugOut(debugOutput);
} }
return session; return session;
} }
// --------------------------------------------------------------- Private method end // --------------------------------------------------------------- Private method end
} }

View File

@ -7,33 +7,34 @@ import java.io.Serial;
/** /**
* 邮件异常 * 邮件异常
*
* @author xiaoleilu * @author xiaoleilu
*/ */
public class MailException extends RuntimeException{ public class MailException extends RuntimeException {
@Serial @Serial
private static final long serialVersionUID = 8247610319171014183L; private static final long serialVersionUID = 8247610319171014183L;
public MailException(Throwable e) { public MailException(Throwable e) {
super(ExceptionUtil.getMessage(e), e); super(ExceptionUtil.getMessage(e), e);
} }
public MailException(String message) { public MailException(String message) {
super(message); super(message);
} }
public MailException(String messageTemplate, Object... params) { public MailException(String messageTemplate, Object... params) {
super(StrUtil.format(messageTemplate, params)); super(StrUtil.format(messageTemplate, params));
} }
public MailException(String message, Throwable throwable) { public MailException(String message, Throwable throwable) {
super(message, throwable); super(message, throwable);
} }
public MailException(String message, Throwable throwable, boolean enableSuppression, boolean writableStackTrace) { public MailException(String message, Throwable throwable, boolean enableSuppression, boolean writableStackTrace) {
super(message, throwable, enableSuppression, writableStackTrace); super(message, throwable, enableSuppression, writableStackTrace);
} }
public MailException(Throwable throwable, String messageTemplate, Object... params) { public MailException(Throwable throwable, String messageTemplate, Object... params) {
super(StrUtil.format(messageTemplate, params), throwable); super(StrUtil.format(messageTemplate, params), throwable);
} }
} }

View File

@ -5,13 +5,12 @@ import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import jakarta.mail.Authenticator; import jakarta.mail.Authenticator;
import jakarta.mail.Session; import jakarta.mail.Session;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;

View File

@ -11,23 +11,23 @@ import jakarta.mail.PasswordAuthentication;
*/ */
public class UserPassAuthenticator extends Authenticator { public class UserPassAuthenticator extends Authenticator {
private final String user; private final String user;
private final String pass; private final String pass;
/** /**
* 构造 * 构造
* *
* @param user 用户名 * @param user 用户名
* @param pass 密码 * @param pass 密码
*/ */
public UserPassAuthenticator(String user, String pass) { public UserPassAuthenticator(String user, String pass) {
this.user = user; this.user = user;
this.pass = pass; this.pass = pass;
} }
@Override @Override
protected PasswordAuthentication getPasswordAuthentication() { protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(this.user, this.pass); return new PasswordAuthentication(this.user, this.pass);
} }
} }