Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-email
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xingmin
yd-email
Commits
a3153b21
Commit
a3153b21
authored
Sep 24, 2025
by
zhangxingmin
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/dev_zxm' into test
parents
fd1733e7
03e6690a
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
750 additions
and
10 deletions
+750
-10
yd-email-api/src/main/java/com/yd/email/api/config/RestTemplateConfig.java
+15
-0
yd-email-api/src/main/java/com/yd/email/api/config/XxlJobConfig.java
+44
-0
yd-email-api/src/main/java/com/yd/email/api/controller/ApiEmailSendController.java
+31
-0
yd-email-api/src/main/java/com/yd/email/api/handler/MailSendJobHandler.java
+136
-0
yd-email-api/src/main/java/com/yd/email/api/service/ApiEmailSendService.java
+9
-0
yd-email-api/src/main/java/com/yd/email/api/service/ApiEmailService.java
+9
-0
yd-email-api/src/main/java/com/yd/email/api/service/XxlJobService.java
+7
-0
yd-email-api/src/main/java/com/yd/email/api/service/impl/ApiEmailSendServiceImpl.java
+103
-0
yd-email-api/src/main/java/com/yd/email/api/service/impl/ApiEmailServiceImpl.java
+130
-0
yd-email-api/src/main/java/com/yd/email/api/service/impl/XxlJobServiceImpl.java
+0
-0
yd-email-api/src/main/resources/bootstrap.yml
+1
-1
yd-email-feign/pom.xml
+9
-1
yd-email-feign/src/main/java/com/yd/email/feign/client/ApiEmailSendFeignClient.java
+25
-0
yd-email-feign/src/main/java/com/yd/email/feign/dto/ApiEmailTaskRecipientsDto.java
+23
-0
yd-email-feign/src/main/java/com/yd/email/feign/enums/EmailTaskStatusEnum.java
+38
-0
yd-email-feign/src/main/java/com/yd/email/feign/fallback/ApiEmailSendFeignFallbackFactory.java
+26
-0
yd-email-feign/src/main/java/com/yd/email/feign/request/ApiSendEmailRequest.java
+49
-0
yd-email-feign/src/main/java/com/yd/email/feign/response/ApiSendEmailResponse.java
+18
-0
yd-email-service/src/main/java/com/yd/email/service/model/EmailTask.java
+14
-2
yd-email-service/src/main/java/com/yd/email/service/model/EmailTaskRecipients.java
+30
-6
yd-email-service/src/main/java/com/yd/email/service/service/IEmailTaskRecipientsService.java
+3
-0
yd-email-service/src/main/java/com/yd/email/service/service/IEmailTaskService.java
+1
-0
yd-email-service/src/main/java/com/yd/email/service/service/impl/EmailTaskRecipientsServiceImpl.java
+18
-0
yd-email-service/src/main/java/com/yd/email/service/service/impl/EmailTaskServiceImpl.java
+11
-0
No files found.
yd-email-api/src/main/java/com/yd/email/api/config/RestTemplateConfig.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
api
.
config
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.web.client.RestTemplate
;
@Configuration
public
class
RestTemplateConfig
{
@Bean
public
RestTemplate
restTemplate
()
{
return
new
RestTemplate
();
}
}
\ No newline at end of file
yd-email-api/src/main/java/com/yd/email/api/config/XxlJobConfig.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
api
.
config
;
import
com.xxl.job.core.executor.impl.XxlJobSpringExecutor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
@Slf4j
@Configuration
@ConditionalOnClass
(
XxlJobSpringExecutor
.
class
)
public
class
XxlJobConfig
{
@Value
(
"${xxl.job.admin.addresses}"
)
private
String
adminAddresses
;
@Value
(
"${xxl.job.executor.appname}"
)
private
String
appname
;
@Value
(
"${xxl.job.executor.port:9999}"
)
private
int
port
;
@Value
(
"${xxl.job.accessToken:}"
)
private
String
accessToken
;
@Bean
public
XxlJobSpringExecutor
xxlJobExecutor
()
{
log
.
info
(
">>>>>>>>>>> xxl-job config init. appname: {}, port: {}, accessToken: {}"
,
appname
,
port
,
StringUtils
.
isNotBlank
(
accessToken
)
?
"已配置"
:
"未配置"
);
XxlJobSpringExecutor
xxlJobSpringExecutor
=
new
XxlJobSpringExecutor
();
xxlJobSpringExecutor
.
setAdminAddresses
(
adminAddresses
);
xxlJobSpringExecutor
.
setAppname
(
appname
);
xxlJobSpringExecutor
.
setPort
(
port
);
// 设置accessToken
xxlJobSpringExecutor
.
setAccessToken
(
accessToken
);
xxlJobSpringExecutor
.
setLogRetentionDays
(
30
);
return
xxlJobSpringExecutor
;
}
}
\ No newline at end of file
yd-email-api/src/main/java/com/yd/email/api/controller/ApiEmailSendController.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
api
.
controller
;
import
com.yd.common.result.Result
;
import
com.yd.email.api.service.ApiEmailSendService
;
import
com.yd.email.feign.client.ApiEmailSendFeignClient
;
import
com.yd.email.feign.request.ApiSendEmailRequest
;
import
com.yd.email.feign.response.ApiSendEmailResponse
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
@RestController
@RequestMapping
(
"/email"
)
@Slf4j
public
class
ApiEmailSendController
implements
ApiEmailSendFeignClient
{
@Autowired
private
ApiEmailSendService
apiEmailSendService
;
/**
* 发送邮件
* @param request
* @return
*/
@Override
public
Result
<
ApiSendEmailResponse
>
sendEmail
(
ApiSendEmailRequest
request
)
{
return
apiEmailSendService
.
sendEmail
(
request
);
}
}
\ No newline at end of file
yd-email-api/src/main/java/com/yd/email/api/handler/MailSendJobHandler.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
api
.
handler
;
import
com.xxl.job.core.context.XxlJobHelper
;
import
com.xxl.job.core.handler.annotation.XxlJob
;
import
com.yd.email.api.service.ApiEmailService
;
import
com.yd.email.feign.enums.EmailTaskStatusEnum
;
import
com.yd.email.service.model.EmailTask
;
import
com.yd.email.service.model.EmailTaskRecipients
;
import
com.yd.email.service.service.IEmailTaskRecipientsService
;
import
com.yd.email.service.service.IEmailTaskService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.time.LocalDateTime
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Objects
;
/**
* 邮件发送任务处理器 - XXL-Job定时任务执行器
* 使用@XxlJob注解方式
*/
@Component
@Slf4j
public
class
MailSendJobHandler
{
@Autowired
private
IEmailTaskService
iEmailTaskService
;
@Autowired
private
IEmailTaskRecipientsService
iEmailTaskRecipientsService
;
@Autowired
private
ApiEmailService
apiEmailService
;
/**
* XXL-Job任务执行入口方法
*/
@XxlJob
(
"mailSendJobHandler"
)
public
void
execute
()
throws
Exception
{
// 从XXL-Job参数中获取任务ID
String
param
=
XxlJobHelper
.
getJobParam
();
// 记录任务开始日志
log
.
info
(
"开始执行邮件发送任务,参数: {}"
,
param
);
// 解析任务参数(参数为邮件任务业务ID)
String
taskBizId
=
param
;
// 根据邮件任务业务ID查询邮件任务信息
EmailTask
emailTask
=
iEmailTaskService
.
queryOne
(
taskBizId
);
// 检查邮件任务是否存在
if
(
Objects
.
isNull
(
emailTask
))
{
// 记录错误并返回
XxlJobHelper
.
log
(
"邮件任务不存在: "
+
taskBizId
);
XxlJobHelper
.
handleFail
(
"邮件任务不存在"
);
return
;
}
// 更新任务状态为发送中
emailTask
.
setStatus
(
EmailTaskStatusEnum
.
SENDING
.
getItemValue
());
iEmailTaskService
.
saveOrUpdate
(
emailTask
);
try
{
// 查询该任务下的所有收件人信息
List
<
EmailTaskRecipients
>
recipients
=
iEmailTaskRecipientsService
.
queryList
(
taskBizId
);
// 初始化成功和失败计数器
int
successCount
=
0
;
int
failCount
=
0
;
// 遍历所有收件人,逐个发送邮件
for
(
EmailTaskRecipients
recipient
:
recipients
)
{
try
{
// 处理抄送人列表:将数据库中的逗号分隔字符串转换为List
List
<
String
>
ccList
=
StringUtils
.
isNotBlank
(
recipient
.
getCcEmail
())
?
Arrays
.
asList
(
recipient
.
getCcEmail
().
split
(
","
))
:
new
ArrayList
<>();
// 调用邮件服务发送邮件
apiEmailService
.
sendMail
(
emailTask
.
getSendEmail
(),
// 发件人地址
recipient
.
getReceiveEmail
(),
// 收件人地址
ccList
,
// 抄送人列表
emailTask
.
getSubject
(),
// 邮件主题
emailTask
.
getContent
(),
// 邮件内容
emailTask
.
getAttachmentPath
()
// 附件路径
);
// 发送成功:更新收件人状态为成功
recipient
.
setStatus
(
EmailTaskStatusEnum
.
SUCCESSFUL
.
getItemValue
());
recipient
.
setSendTime
(
LocalDateTime
.
now
());
// 记录实际发送时间
iEmailTaskRecipientsService
.
saveOrUpdate
(
recipient
);
successCount
++;
// 成功计数加1
}
catch
(
Exception
e
)
{
// 发送失败:记录错误日志
log
.
error
(
"发送邮件失败: {}"
,
recipient
.
getReceiveEmail
(),
e
);
// 更新收件人状态为失败
recipient
.
setStatus
(
EmailTaskStatusEnum
.
FAILED
.
getItemValue
());
recipient
.
setErrorMsg
(
e
.
getMessage
());
// 保存错误信息
iEmailTaskRecipientsService
.
saveOrUpdate
(
recipient
);
failCount
++;
// 失败计数加1
}
}
// 根据发送结果更新邮件任务状态
emailTask
.
setStatus
(
failCount
==
0
?
EmailTaskStatusEnum
.
ALL_SUCCESSFUL
.
getItemValue
()
:
EmailTaskStatusEnum
.
PARTIAL_FAILURE
.
getItemValue
());
iEmailTaskService
.
saveOrUpdate
(
emailTask
);
// 记录任务完成日志
log
.
info
(
"邮件发送任务完成: 成功{}个, 失败{}个"
,
successCount
,
failCount
);
// 设置任务执行结果
if
(
failCount
==
0
)
{
XxlJobHelper
.
handleSuccess
(
"发送完成: 成功"
+
successCount
+
"个"
);
}
else
{
XxlJobHelper
.
handleSuccess
(
"发送完成: 成功"
+
successCount
+
"个, 失败"
+
failCount
+
"个"
);
}
}
catch
(
Exception
e
)
{
// 任务执行过程中发生异常
log
.
error
(
"邮件发送任务执行异常"
,
e
);
// 更新任务状态为全部发送失败
emailTask
.
setStatus
(
EmailTaskStatusEnum
.
ALL_FAILED
.
getItemValue
());
iEmailTaskService
.
saveOrUpdate
(
emailTask
);
// 返回任务执行异常信息
XxlJobHelper
.
handleFail
(
"任务执行异常: "
+
e
.
getMessage
());
}
}
}
\ No newline at end of file
yd-email-api/src/main/java/com/yd/email/api/service/ApiEmailSendService.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
api
.
service
;
import
com.yd.common.result.Result
;
import
com.yd.email.feign.request.ApiSendEmailRequest
;
import
com.yd.email.feign.response.ApiSendEmailResponse
;
public
interface
ApiEmailSendService
{
Result
<
ApiSendEmailResponse
>
sendEmail
(
ApiSendEmailRequest
request
);
}
yd-email-api/src/main/java/com/yd/email/api/service/ApiEmailService.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
api
.
service
;
import
java.util.List
;
public
interface
ApiEmailService
{
// 发送邮件的主要方法
void
sendMail
(
String
from
,
String
to
,
List
<
String
>
cc
,
String
subject
,
String
content
,
String
attachmentPath
)
throws
Exception
;
}
yd-email-api/src/main/java/com/yd/email/api/service/XxlJobService.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
api
.
service
;
import
java.util.Date
;
public
interface
XxlJobService
{
String
addScheduleJob
(
String
taskBizId
,
Date
scheduleTime
);
}
yd-email-api/src/main/java/com/yd/email/api/service/impl/ApiEmailSendServiceImpl.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
api
.
service
.
impl
;
import
com.yd.common.enums.CommonEnum
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.result.Result
;
import
com.yd.common.utils.DateUtil
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.email.api.service.ApiEmailSendService
;
import
com.yd.email.api.service.XxlJobService
;
import
com.yd.email.feign.enums.EmailTaskStatusEnum
;
import
com.yd.email.feign.request.ApiSendEmailRequest
;
import
com.yd.email.feign.response.ApiSendEmailResponse
;
import
com.yd.email.service.model.EmailTask
;
import
com.yd.email.service.model.EmailTaskRecipients
;
import
com.yd.email.service.service.IEmailTaskService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.CollectionUtils
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.stream.Collectors
;
/**
* 邮件发送实现类
*/
@Service
@Slf4j
public
class
ApiEmailSendServiceImpl
implements
ApiEmailSendService
{
@Autowired
private
XxlJobService
xxlJobService
;
@Autowired
private
IEmailTaskService
iEmailTaskService
;
/**
* 发送邮件
* @param request
* @return
*/
@Override
public
Result
<
ApiSendEmailResponse
>
sendEmail
(
ApiSendEmailRequest
request
)
{
ApiSendEmailResponse
response
=
new
ApiSendEmailResponse
();
try
{
//保存邮件任务到数据库
EmailTask
mailTask
=
new
EmailTask
();
//邮件任务唯一业务ID
mailTask
.
setTaskBizId
(
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_EMAIL_TASK
.
getCode
()));
//任务名称:邮件主题 + 邮件发送任务
mailTask
.
setTaskName
(
request
.
getSubject
()
+
"邮件发送任务"
);
//关联发件人唯一业务ID
mailTask
.
setSenderBizId
(
request
.
getSenderBizId
());
//发件人邮箱
mailTask
.
setSendEmail
(
request
.
getSendEmail
());
//邮件主题
mailTask
.
setSubject
(
request
.
getSubject
());
//邮件内容
mailTask
.
setContent
(
request
.
getContent
());
//发送邮件的附件路径(多个用分号分隔)
mailTask
.
setAttachmentPath
(
request
.
getAttachmentPath
());
//计划发送时间(为空表示立即发送,不为空表示定时发送)
mailTask
.
setScheduleTime
(
request
.
getScheduleTime
());
//任务状态:计划发送时间(为空表示立即发送状态为发送中,不为空表示发送状态为定时发送)
String
taskStatus
=
!
Objects
.
isNull
(
request
.
getScheduleTime
())
?
EmailTaskStatusEnum
.
SCHEDULED
.
getItemValue
()
:
EmailTaskStatusEnum
.
SENDING
.
getItemValue
();
mailTask
.
setStatus
(
taskStatus
);
iEmailTaskService
.
saveOrUpdate
(
mailTask
);
//邮件任务唯一业务ID
String
taskBizId
=
mailTask
.
getTaskBizId
();
// 保存收件人信息
if
(!
CollectionUtils
.
isEmpty
(
request
.
getRecipientsDtoList
()))
{
List
<
EmailTaskRecipients
>
recipientsList
=
request
.
getRecipientsDtoList
()
.
stream
().
map
(
dto
->
{
EmailTaskRecipients
mailRecipient
=
new
EmailTaskRecipients
();
//邮件任务唯一业务ID
mailRecipient
.
setTaskBizId
(
taskBizId
);
mailRecipient
.
setStatus
(
taskStatus
);
mailRecipient
.
setContactBizId
(
dto
.
getContactBizId
());
mailRecipient
.
setReceiveEmail
(
dto
.
getReceiveEmail
());
//抄送人邮箱(多个用分号分隔)
mailRecipient
.
setCcEmail
(!
CollectionUtils
.
isEmpty
(
dto
.
getCcEmailList
())
?
String
.
join
(
";"
,
dto
.
getCcEmailList
())
:
""
);
return
mailRecipient
;
}).
collect
(
Collectors
.
toList
());
}
//计划发送时间(为空表示立即发送,不为空表示定时发送)
String
jobId
=
""
;
if
(!
Objects
.
isNull
(
request
.
getScheduleTime
()))
{
//创建XXL-Job定时任务
jobId
=
xxlJobService
.
addScheduleJob
(
taskBizId
,
DateUtil
.
convertDateByLocalDateTime
(
request
.
getScheduleTime
()));
}
response
.
setJobId
(
jobId
);
response
.
setScheduleTime
(
request
.
getScheduleTime
());
response
.
setTaskBizId
(
taskBizId
);
return
Result
.
success
(
response
);
}
catch
(
Exception
e
)
{
log
.
error
(
"创建邮件发送任务失败"
,
e
);
throw
new
BusinessException
(
"创建邮件发送任务失败"
);
}
}
}
yd-email-api/src/main/java/com/yd/email/api/service/impl/ApiEmailServiceImpl.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
api
.
service
.
impl
;
import
com.yd.email.api.service.ApiEmailService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Service
;
import
javax.activation.DataHandler
;
import
javax.activation.DataSource
;
import
javax.activation.FileDataSource
;
import
javax.mail.*
;
import
javax.mail.internet.InternetAddress
;
import
javax.mail.internet.MimeBodyPart
;
import
javax.mail.internet.MimeMessage
;
import
javax.mail.internet.MimeMultipart
;
import
java.io.File
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Properties
;
/**
* 邮件服务实现类
*/
@Service
@Slf4j
public
class
ApiEmailServiceImpl
implements
ApiEmailService
{
@Value
(
"${spring.mail.host}"
)
// 从配置文件中注入邮件服务器主机地址
private
String
host
;
@Value
(
"${spring.mail.username}"
)
// 从配置文件中注入发件人用户名
private
String
username
;
@Value
(
"${spring.mail.password}"
)
// 从配置文件中注入发件人密码
private
String
password
;
// @Autowired // 自动注入邮件任务Mapper(数据库操作接口)
// private MailTaskMapper mailTaskMapper;
//
// @Autowired // 自动注入邮件收件人Mapper(数据库操作接口)
// private MailRecipientMapper mailRecipientMapper;
// 发送邮件的主要方法
@Override
public
void
sendMail
(
String
from
,
String
to
,
List
<
String
>
cc
,
String
subject
,
String
content
,
String
attachmentPath
)
throws
Exception
{
// 创建邮件配置属性对象
Properties
props
=
new
Properties
();
// 设置SMTP需要身份验证
props
.
put
(
"mail.smtp.auth"
,
"true"
);
// 启用TLS加密传输
props
.
put
(
"mail.smtp.starttls.enable"
,
"true"
);
// 设置邮件服务器主机名
props
.
put
(
"mail.smtp.host"
,
host
);
// 设置邮件服务器端口号(587是TLS标准端口)
props
.
put
(
"mail.smtp.port"
,
"587"
);
// 创建邮件会话对象,传入配置和认证器
Session
session
=
Session
.
getInstance
(
props
,
new
Authenticator
()
{
// 重写获取密码认证的方法
protected
PasswordAuthentication
getPasswordAuthentication
()
{
// 返回用户名密码认证对象
return
new
PasswordAuthentication
(
username
,
password
);
}
});
// 使用try-catch块处理邮件发送异常
try
{
// 创建MIME类型邮件消息对象
Message
message
=
new
MimeMessage
(
session
);
// 设置发件人地址
message
.
setFrom
(
new
InternetAddress
(
from
));
// 设置收件人地址(支持多个收件人,用逗号分隔)
message
.
setRecipients
(
Message
.
RecipientType
.
TO
,
InternetAddress
.
parse
(
to
));
// 判断是否有抄送人
if
(
cc
!=
null
&&
!
cc
.
isEmpty
())
{
// 将抄送人列表转换为逗号分隔的字符串
String
ccAddresses
=
String
.
join
(
","
,
cc
);
// 设置抄送人地址
message
.
setRecipients
(
Message
.
RecipientType
.
CC
,
InternetAddress
.
parse
(
ccAddresses
));
}
// 设置邮件主题
message
.
setSubject
(
subject
);
// 设置邮件发送时间(当前时间)
message
.
setSentDate
(
new
Date
());
// 创建邮件正文部分
MimeBodyPart
messageBodyPart
=
new
MimeBodyPart
();
// 设置正文内容,指定HTML格式和UTF-8编码
messageBodyPart
.
setContent
(
content
,
"text/html;charset=utf-8"
);
// 创建多部分内容容器(用于组合正文和附件)
Multipart
multipart
=
new
MimeMultipart
();
// 将正文部分添加到多部分容器中
multipart
.
addBodyPart
(
messageBodyPart
);
// 判断是否有附件路径
if
(
StringUtils
.
isNotBlank
(
attachmentPath
))
{
// 创建附件部分
MimeBodyPart
attachmentPart
=
new
MimeBodyPart
();
// 创建文件数据源
DataSource
source
=
new
FileDataSource
(
attachmentPath
);
// 设置附件的数据处理器
attachmentPart
.
setDataHandler
(
new
DataHandler
(
source
));
// 设置附件文件名(使用原文件名)
attachmentPart
.
setFileName
(
new
File
(
attachmentPath
).
getName
());
// 将附件部分添加到多部分容器中
multipart
.
addBodyPart
(
attachmentPart
);
}
// 将多部分内容设置为邮件的完整内容
message
.
setContent
(
multipart
);
// 发送邮件
Transport
.
send
(
message
);
// 记录成功日志
log
.
info
(
"邮件发送成功: {} -> {}"
,
from
,
to
);
}
catch
(
MessagingException
e
)
{
// 记录失败日志,包含异常信息
log
.
error
(
"邮件发送失败: {} -> {}"
,
from
,
to
,
e
);
// 抛出运行时异常
throw
new
RuntimeException
(
"邮件发送失败: "
+
e
.
getMessage
());
}
}
}
\ No newline at end of file
yd-email-api/src/main/java/com/yd/email/api/service/impl/XxlJobServiceImpl.java
0 → 100644
View file @
a3153b21
This diff is collapsed.
Click to expand it.
yd-email-api/src/main/resources/bootstrap.yml
View file @
a3153b21
...
...
@@ -44,7 +44,7 @@ spring:
# 配置中心
config
:
# 命名空间id(此处不用public,因public初始化的空间, id为空)
namespace
:
b3b01715-eb85-4242-992a-5aff03d864d4
namespace
:
8fbea9a4-b626-46de-a4e6-9d23f6609318
# nacos的ip地址和端口
server-addr
:
139.224.145.34:8848
# 这个就表示 在我们nacos命名空间id为 dev中 有一个data-id 为 demo-service.yml 的配置文件 读取这个里面的配置
...
...
yd-email-feign/pom.xml
View file @
a3153b21
...
...
@@ -27,11 +27,19 @@
<groupId>
com.fasterxml.jackson.core
</groupId>
<artifactId>
jackson-annotations
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-mail
</artifactId>
</dependency>
<!-- 邮箱依赖 -->
<dependency>
<groupId>
com.sun.mail
</groupId>
<artifactId>
javax.mail
</artifactId>
<version>
${email.version}
</version>
</dependency>
<!-- XXL-Job 核心依赖 -->
<dependency>
<groupId>
com.xuxueli
</groupId>
<artifactId>
xxl-job-core
</artifactId>
</dependency>
</dependencies>
</project>
yd-email-feign/src/main/java/com/yd/email/feign/client/ApiEmailSendFeignClient.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
feign
.
client
;
import
com.yd.common.result.Result
;
import
com.yd.email.feign.fallback.ApiEmailSendFeignFallbackFactory
;
import
com.yd.email.feign.request.ApiSendEmailRequest
;
import
com.yd.email.feign.response.ApiSendEmailResponse
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
/**
* 邮箱服务-邮件发送Feign客户端
*/
@FeignClient
(
name
=
"yd-email-api"
,
fallbackFactory
=
ApiEmailSendFeignFallbackFactory
.
class
)
public
interface
ApiEmailSendFeignClient
{
/**
* 发送邮件
* @param request
* @return
*/
@PostMapping
(
"/send"
)
Result
<
ApiSendEmailResponse
>
sendEmail
(
@Validated
@RequestBody
ApiSendEmailRequest
request
);
}
yd-email-feign/src/main/java/com/yd/email/feign/dto/ApiEmailTaskRecipientsDto.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
feign
.
dto
;
import
lombok.Data
;
import
java.util.List
;
@Data
public
class
ApiEmailTaskRecipientsDto
{
/**
* 收件人唯一业务ID(联系人唯一业务ID)有就传值,没有就不传值
*/
private
String
contactBizId
;
/**
* 收件人邮箱(单个)
*/
private
String
receiveEmail
;
/**
* 抄送人邮箱(数组)
*/
private
List
<
String
>
ccEmailList
;
}
yd-email-feign/src/main/java/com/yd/email/feign/enums/EmailTaskStatusEnum.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
feign
.
enums
;
/**
* 邮件任务状态枚举
*/
public
enum
EmailTaskStatusEnum
{
PENDING
(
"待发送"
,
"PENDING"
),
SENDING
(
"发送中"
,
"SENDING"
),
SUCCESSFUL
(
"发送成功"
,
"SUCCESSFUL"
),
FAILED
(
"发送失败"
,
"FAILED"
),
CANCELLED
(
"已取消"
,
"CANCELLED"
),
SCHEDULED
(
"已定时"
,
"SCHEDULED"
),
ALL_SUCCESSFUL
(
"全部发送成功"
,
"ALL_SUCCESSFUL"
),
ALL_FAILED
(
"全部发送失败"
,
"ALL_FAILED"
),
PARTIALLY_SUCCESSFUL
(
"部分发送成功"
,
"PARTIALLY_SUCCESSFUL"
),
PARTIAL_FAILURE
(
"部分发送失败"
,
"PARTIAL_FAILURE"
),
;
//字典项标签(名称)
private
String
itemLabel
;
//字典项值
private
String
itemValue
;
//构造函数
EmailTaskStatusEnum
(
String
itemLabel
,
String
itemValue
)
{
this
.
itemLabel
=
itemLabel
;
this
.
itemValue
=
itemValue
;
}
public
String
getItemLabel
()
{
return
itemLabel
;
}
public
String
getItemValue
()
{
return
itemValue
;
}
}
yd-email-feign/src/main/java/com/yd/email/feign/fallback/ApiEmailSendFeignFallbackFactory.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
feign
.
fallback
;
import
com.yd.common.result.Result
;
import
com.yd.email.feign.client.ApiEmailSendFeignClient
;
import
com.yd.email.feign.request.ApiSendEmailRequest
;
import
com.yd.email.feign.response.ApiSendEmailResponse
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.cloud.openfeign.FallbackFactory
;
import
org.springframework.stereotype.Component
;
/**
* 邮箱服务-邮件发送Feign降级处理
*/
@Slf4j
@Component
public
class
ApiEmailSendFeignFallbackFactory
implements
FallbackFactory
<
ApiEmailSendFeignClient
>
{
@Override
public
ApiEmailSendFeignClient
create
(
Throwable
cause
)
{
return
new
ApiEmailSendFeignClient
()
{
@Override
public
Result
<
ApiSendEmailResponse
>
sendEmail
(
ApiSendEmailRequest
request
)
{
return
null
;
}
};
}
}
yd-email-feign/src/main/java/com/yd/email/feign/request/ApiSendEmailRequest.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
feign
.
request
;
import
com.yd.email.feign.dto.ApiEmailTaskRecipientsDto
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
import
java.time.LocalDateTime
;
import
java.util.List
;
@Data
public
class
ApiSendEmailRequest
{
/**
* 发件人唯一业务ID
*/
private
String
senderBizId
;
/**
* 发件人邮箱(单个)
*/
@NotBlank
(
message
=
"发件人邮箱不能为空"
)
private
String
sendEmail
;
/**
* 邮件主题
*/
@NotBlank
(
message
=
"邮件主题不能为空"
)
private
String
subject
;
/**
* 邮件内容
*/
@NotBlank
(
message
=
"邮件内容不能为空"
)
private
String
content
;
/**
* 计划发送时间(为空表示立即发送,不为空表示定时发送)
*/
private
LocalDateTime
scheduleTime
;
/**
* 发送邮件的附件路径(多个用分号分隔)
*/
private
String
attachmentPath
;
/**
* 收件人列表信息
*/
private
List
<
ApiEmailTaskRecipientsDto
>
recipientsDtoList
;
}
yd-email-feign/src/main/java/com/yd/email/feign/response/ApiSendEmailResponse.java
0 → 100644
View file @
a3153b21
package
com
.
yd
.
email
.
feign
.
response
;
import
lombok.Data
;
import
java.time.LocalDateTime
;
@Data
public
class
ApiSendEmailResponse
{
private
String
jobId
;
private
String
taskBizId
;
/**
* 计划发送时间(为空表示立即发送,不为空表示定时发送)
*/
private
LocalDateTime
scheduleTime
;
}
yd-email-service/src/main/java/com/yd/email/service/model/EmailTask.java
View file @
a3153b21
...
...
@@ -49,6 +49,12 @@ public class EmailTask implements Serializable {
private
String
senderBizId
;
/**
* 发件人邮箱(单个)
*/
@TableField
(
"send_email"
)
private
String
sendEmail
;
/**
* 邮件主题
*/
@TableField
(
"subject"
)
...
...
@@ -73,18 +79,24 @@ public class EmailTask implements Serializable {
private
String
status
;
/**
* 计划发送时间(为空表示立即发送)
* 计划发送时间(为空表示立即发送
,不为空表示定时发送
)
*/
@TableField
(
"schedule_time"
)
private
LocalDateTime
scheduleTime
;
/**
* 实际发送时间
* 实际发送时间
(发送成功的时间)
*/
@TableField
(
"send_time"
)
private
LocalDateTime
sendTime
;
/**
* 发送邮件的附件路径(多个用分号分隔)
*/
@TableField
(
"attachment_path"
)
private
String
attachmentPath
;
/**
* 通用备注
*/
@TableField
(
"remark"
)
...
...
yd-email-service/src/main/java/com/yd/email/service/model/EmailTaskRecipients.java
View file @
a3153b21
...
...
@@ -43,16 +43,40 @@ public class EmailTaskRecipients implements Serializable {
private
String
contactBizId
;
/**
* 收件人
类型:TO-收件人, CC-抄送, BCC-密送
* 收件人
邮箱(单个)
*/
@TableField
(
"rec
ipient_type
"
)
private
String
rec
ipientType
;
@TableField
(
"rec
eive_email
"
)
private
String
rec
eiveEmail
;
/**
*
邮箱(根据收件人类型显示
)
*
抄送人邮箱(多个用分号分隔
)
*/
@TableField
(
"email"
)
private
String
email
;
@TableField
(
"cc_email"
)
private
String
ccEmail
;
/**
* 密送人邮箱(多个用分号分隔)
*/
@TableField
(
"bcc_email"
)
private
String
bccEmail
;
/**
* 收件人邮件状态:PENDING-待发送, SENDING-发送中, COMPLETED-已完成, FAILED-发送失败, CANCELLED-已取消
*/
@TableField
(
"status"
)
private
String
status
;
/**
* 实际发送时间
*/
@TableField
(
"send_time"
)
private
LocalDateTime
sendTime
;
/**
* 发送失败的错误信息
*/
@TableField
(
"error_msg"
)
private
String
errorMsg
;
/**
* 通用备注
...
...
yd-email-service/src/main/java/com/yd/email/service/service/IEmailTaskRecipientsService.java
View file @
a3153b21
...
...
@@ -3,6 +3,8 @@ package com.yd.email.service.service;
import
com.yd.email.service.model.EmailTaskRecipients
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
java.util.List
;
/**
* <p>
* 邮件任务收件人关联表 服务类
...
...
@@ -13,4 +15,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public
interface
IEmailTaskRecipientsService
extends
IService
<
EmailTaskRecipients
>
{
List
<
EmailTaskRecipients
>
queryList
(
String
taskBizId
);
}
yd-email-service/src/main/java/com/yd/email/service/service/IEmailTaskService.java
View file @
a3153b21
...
...
@@ -13,4 +13,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public
interface
IEmailTaskService
extends
IService
<
EmailTask
>
{
EmailTask
queryOne
(
String
taskBizId
);
}
yd-email-service/src/main/java/com/yd/email/service/service/impl/EmailTaskRecipientsServiceImpl.java
View file @
a3153b21
package
com
.
yd
.
email
.
service
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.yd.email.service.model.EmailContactImport
;
import
com.yd.email.service.model.EmailTaskRecipients
;
import
com.yd.email.service.dao.EmailTaskRecipientsMapper
;
import
com.yd.email.service.service.IEmailTaskRecipientsService
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
/**
* <p>
* 邮件任务收件人关联表 服务实现类
...
...
@@ -17,4 +22,17 @@ import org.springframework.stereotype.Service;
@Service
public
class
EmailTaskRecipientsServiceImpl
extends
ServiceImpl
<
EmailTaskRecipientsMapper
,
EmailTaskRecipients
>
implements
IEmailTaskRecipientsService
{
/**
* 根据任务业务id查询邮件任务收件人关联列表
* @param taskBizId
* @return
*/
@Override
public
List
<
EmailTaskRecipients
>
queryList
(
String
taskBizId
)
{
List
<
EmailTaskRecipients
>
list
=
baseMapper
.
selectList
(
new
LambdaQueryWrapper
<
EmailTaskRecipients
>()
.
eq
(
StringUtils
.
isNotBlank
(
taskBizId
),
EmailTaskRecipients:
:
getTaskBizId
,
taskBizId
)
);
return
list
;
}
}
yd-email-service/src/main/java/com/yd/email/service/service/impl/EmailTaskServiceImpl.java
View file @
a3153b21
package
com
.
yd
.
email
.
service
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.yd.email.service.model.EmailTask
;
import
com.yd.email.service.dao.EmailTaskMapper
;
import
com.yd.email.service.service.IEmailTaskService
;
...
...
@@ -17,4 +18,14 @@ import org.springframework.stereotype.Service;
@Service
public
class
EmailTaskServiceImpl
extends
ServiceImpl
<
EmailTaskMapper
,
EmailTask
>
implements
IEmailTaskService
{
/**
* 查询单个对象
* @param taskBizId
* @return
*/
@Override
public
EmailTask
queryOne
(
String
taskBizId
)
{
return
this
.
getOne
(
new
LambdaQueryWrapper
<
EmailTask
>().
eq
(
EmailTask:
:
getTaskBizId
,
taskBizId
));
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment