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
ed904f15
Commit
ed904f15
authored
Sep 24, 2025
by
zhangxingmin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
push
parent
e9aa8ae5
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
645 additions
and
102 deletions
+645
-102
yd-email-api/src/main/java/com/yd/email/api/controller/ApiEmailSendController.java
+82
-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
+69
-0
yd-email-api/src/main/java/com/yd/email/api/service/impl/ApiEmailServiceImpl.java
+4
-3
yd-email-api/src/main/java/com/yd/email/api/service/impl/XxlJobServiceImpl.java
+137
-0
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/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
+21
-0
yd-email-feign/src/main/java/com/yd/email/feign/response/ApiSendEmailResponse.java
+7
-0
yd-email-service/src/main/java/com/yd/email/service/handler/MailSendJobHandler.java
+0
-89
yd-email-service/src/main/java/com/yd/email/service/model/EmailTask.java
+12
-0
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/EmailService.java
+0
-4
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/controller/ApiEmailSendController.java
0 → 100644
View file @
ed904f15
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
);
}
// @Autowired
// private MailTaskMapper mailTaskMapper;
//
// @Autowired
// private MailRecipientMapper mailRecipientMapper;
//
// @Autowired
// private XxlJobService xxlJobService;
//
// @PostMapping("/send")
// public ResponseResult sendMail(@RequestBody MailSendRequest request) {
// try {
// // 1. 保存邮件任务到数据库
// MailTask mailTask = new MailTask();
// mailTask.setFromAddress(request.getFrom());
// mailTask.setSubject(request.getSubject());
// mailTask.setContent(request.getContent());
// mailTask.setAttachmentPath(request.getAttachmentPath());
// mailTask.setSendTime(request.getSendTime());
// mailTask.setStatus(0);
// mailTaskMapper.insert(mailTask);
//
// Long taskId = mailTask.getId();
//
// // 2. 保存收件人信息
// for (MailSendRequest.Recipient recipient : request.getRecipients()) {
// MailRecipient mailRecipient = new MailRecipient();
// mailRecipient.setTaskId(taskId);
// mailRecipient.setToAddress(recipient.getTo());
// if (recipient.getCc() != null && !recipient.getCc().isEmpty()) {
// mailRecipient.setCcAddresses(String.join(",", recipient.getCc()));
// }
// mailRecipient.setSendStatus(0);
// mailRecipientMapper.insert(mailRecipient);
// }
//
// // 3. 创建XXL-Job定时任务
// String jobId = xxlJobService.addScheduleJob(taskId, request.getSendTime());
//
// return ResponseResult.success("邮件任务创建成功", Map.of(
// "taskId", taskId,
// "jobId", jobId,
// "scheduleTime", request.getSendTime()
// ));
//
// } catch (Exception e) {
// log.error("创建邮件发送任务失败", e);
// return ResponseResult.error("创建任务失败: " + e.getMessage());
// }
// }
}
\ No newline at end of file
yd-email-api/src/main/java/com/yd/email/api/handler/MailSendJobHandler.java
0 → 100644
View file @
ed904f15
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 @
ed904f15
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 @
ed904f15
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 @
ed904f15
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 @
ed904f15
package
com
.
yd
.
email
.
api
.
service
.
impl
;
import
com.yd.common.result.Result
;
import
com.yd.email.api.service.ApiEmailSendService
;
import
com.yd.email.api.service.XxlJobService
;
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.stereotype.Service
;
/**
* 邮件发送实现类
*/
@Service
@Slf4j
public
class
ApiEmailSendServiceImpl
implements
ApiEmailSendService
{
@Autowired
private
XxlJobService
xxlJobService
;
/**
* 发送邮件
* @param request
* @return
*/
@Override
public
Result
<
ApiSendEmailResponse
>
sendEmail
(
ApiSendEmailRequest
request
)
{
// try {
// // 1. 保存邮件任务到数据库
// MailTask mailTask = new MailTask();
// mailTask.setFromAddress(request.getFrom());
// mailTask.setSubject(request.getSubject());
// mailTask.setContent(request.getContent());
// mailTask.setAttachmentPath(request.getAttachmentPath());
// mailTask.setSendTime(request.getSendTime());
// mailTask.setStatus(0);
// mailTaskMapper.insert(mailTask);
//
// Long taskId = mailTask.getId();
//
// // 2. 保存收件人信息
// for (MailSendRequest.Recipient recipient : request.getRecipients()) {
// MailRecipient mailRecipient = new MailRecipient();
// mailRecipient.setTaskId(taskId);
// mailRecipient.setToAddress(recipient.getTo());
// if (recipient.getCc() != null && !recipient.getCc().isEmpty()) {
// mailRecipient.setCcAddresses(String.join(",", recipient.getCc()));
// }
// mailRecipient.setSendStatus(0);
// mailRecipientMapper.insert(mailRecipient);
// }
//
// // 3. 创建XXL-Job定时任务
// String jobId = xxlJobService.addScheduleJob(taskId, request.getSendTime());
//
// return ResponseResult.success("邮件任务创建成功", Map.of(
// "taskId", taskId,
// "jobId", jobId,
// "scheduleTime", request.getSendTime()
// ));
//
// } catch (Exception e) {
// log.error("创建邮件发送任务失败", e);
// return ResponseResult.error("创建任务失败: " + e.getMessage());
// }
return
null
;
}
}
yd-email-
service/src/main/java/com/yd/email/service/service/impl/
EmailServiceImpl.java
→
yd-email-
api/src/main/java/com/yd/email/api/service/impl/Api
EmailServiceImpl.java
View file @
ed904f15
package
com
.
yd
.
email
.
service
.
service
.
impl
;
package
com
.
yd
.
email
.
api
.
service
.
impl
;
import
com.yd.email.
service.service.
EmailService
;
import
com.yd.email.
api.service.Api
EmailService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Value
;
...
...
@@ -23,7 +23,7 @@ import java.util.Properties;
*/
@Service
@Slf4j
public
class
EmailServiceImpl
implements
EmailService
{
public
class
ApiEmailServiceImpl
implements
Api
EmailService
{
@Value
(
"${spring.mail.host}"
)
// 从配置文件中注入邮件服务器主机地址
private
String
host
;
...
...
@@ -41,6 +41,7 @@ public class EmailServiceImpl implements EmailService {
// private MailRecipientMapper mailRecipientMapper;
// 发送邮件的主要方法
@Override
public
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/impl/XxlJobServiceImpl.java
0 → 100644
View file @
ed904f15
package
com
.
yd
.
email
.
api
.
service
.
impl
;
import
com.yd.email.api.service.XxlJobService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.web.client.RestTemplate
;
import
java.util.Calendar
;
import
java.util.Date
;
@Service
@Slf4j
public
class
XxlJobServiceImpl
implements
XxlJobService
{
// 从配置文件中注入XXL-Job管理端的地址
@Value
(
"${xxl.job.admin.addresses}"
)
private
String
adminAddresses
;
// 从配置文件中注入执行器的应用名称
@Value
(
"${xxl.job.executor.appname}"
)
private
String
appName
;
// 自动注入Spring的RestTemplate用于HTTP请求
@Autowired
private
RestTemplate
restTemplate
;
/**
* 添加定时任务
* @param taskBizId 邮件任务ID
* @param scheduleTime 计划执行时间
* @return 返回创建的jobId
*/
@Override
public
String
addScheduleJob
(
String
taskBizId
,
Date
scheduleTime
)
{
// 使用try-catch捕获可能出现的异常
try
{
// 将Date时间转换为Cron表达式(在指定时间执行一次)
String
cronExpression
=
convertDateToCron
(
scheduleTime
);
// 创建MultiValueMap用于存储HTTP请求参数
MultiValueMap
<
String
,
String
>
params
=
new
LinkedMultiValueMap
<>();
// 设置执行器组ID,默认为1
params
.
add
(
"jobGroup"
,
"1"
);
// 设置任务描述,包含任务ID用于标识
params
.
add
(
"jobDesc"
,
"邮件发送任务-"
+
taskBizId
);
// 设置任务作者
params
.
add
(
"author"
,
"system"
);
// 设置调度类型为CRON表达式
params
.
add
(
"scheduleType"
,
"CRON"
);
// 设置CRON表达式
params
.
add
(
"scheduleConf"
,
cronExpression
);
// 设置任务模式为BEAN模式
params
.
add
(
"glueType"
,
"BEAN"
);
// 设置执行器处理器名称(对应@XxlJob注解的值)
params
.
add
(
"executorHandler"
,
"mailSendJobHandler"
);
// 设置任务参数(传递邮件任务ID)
params
.
add
(
"executorParam"
,
taskBizId
);
// 设置路由策略为第一个
params
.
add
(
"executorRouteStrategy"
,
"FIRST"
);
// 设置调度过期策略为忽略
params
.
add
(
"misfireStrategy"
,
"DO_NOTHING"
);
// 设置阻塞处理策略为串行执行
params
.
add
(
"executorBlockStrategy"
,
"SERIAL_EXECUTION"
);
// 构建完整的API请求URL
String
url
=
adminAddresses
+
"/jobinfo/add"
;
// 发送POST请求到XXL-Job管理端创建任务
ResponseEntity
<
String
>
response
=
restTemplate
.
postForEntity
(
url
,
params
,
String
.
class
);
// 检查HTTP响应状态码是否为2xx成功
if
(
response
.
getStatusCode
().
is2xxSuccessful
())
{
// 记录成功日志
log
.
info
(
"创建XXL-Job任务成功, taskId: {}"
,
taskBizId
);
// 从响应体中提取jobId
return
extractJobId
(
response
.
getBody
());
}
else
{
// 如果HTTP请求失败,抛出运行时异常
throw
new
RuntimeException
(
"XXL-Job API调用失败: "
+
response
.
getStatusCode
());
}
}
catch
(
Exception
e
)
{
// 捕获所有异常并记录错误日志
log
.
error
(
"创建XXL-Job任务失败"
,
e
);
// 抛出包装后的运行时异常
throw
new
RuntimeException
(
"创建定时任务失败: "
+
e
.
getMessage
());
}
}
/**
* 将Date转换为Cron表达式(只执行一次)
* @param date 需要转换的日期时间
* @return 返回对应的Cron表达式
*/
private
String
convertDateToCron
(
Date
date
)
{
// 创建Calendar实例用于时间解析
Calendar
calendar
=
Calendar
.
getInstance
();
// 设置Calendar的时间为传入的Date
calendar
.
setTime
(
date
);
// 获取秒数(0-59)
int
second
=
calendar
.
get
(
Calendar
.
SECOND
);
// 获取分钟数(0-59)
int
minute
=
calendar
.
get
(
Calendar
.
MINUTE
);
// 获取小时数(24小时制,0-23)
int
hour
=
calendar
.
get
(
Calendar
.
HOUR_OF_DAY
);
// 获取日期(1-31)
int
day
=
calendar
.
get
(
Calendar
.
DAY_OF_MONTH
);
// 获取月份(Calendar的月份从0开始,所以需要+1)
int
month
=
calendar
.
get
(
Calendar
.
MONTH
)
+
1
;
// 获取年份
int
year
=
calendar
.
get
(
Calendar
.
YEAR
);
// 格式化Cron表达式:秒 分 时 日 月 周 年
// 注意:Cron表达式通常不包含年份,但这里为了单次执行包含了年份
return
String
.
format
(
"%d %d %d %d %d ? %d"
,
second
,
minute
,
hour
,
day
,
month
,
year
);
}
/**
* 从XXL-Job的响应体中提取jobId
* @param responseBody HTTP响应体内容
* @return 返回提取的jobId
*/
private
String
extractJobId
(
String
responseBody
)
{
// 注意:这里需要根据XXL-Job API的实际返回格式进行解析
// 目前使用时间戳生成临时jobId,实际应该解析JSON响应
// XXL-Job通常返回JSON格式:{"code":200,"msg":null,"content":123}
// 其中content就是jobId
// 临时方案:生成基于时间戳的jobId
return
"job_"
+
System
.
currentTimeMillis
();
}
}
\ No newline at end of file
yd-email-feign/src/main/java/com/yd/email/feign/client/ApiEmailSendFeignClient.java
0 → 100644
View file @
ed904f15
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/enums/EmailTaskStatusEnum.java
0 → 100644
View file @
ed904f15
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 @
ed904f15
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 @
ed904f15
package
com
.
yd
.
email
.
feign
.
request
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
@Data
public
class
ApiSendEmailRequest
{
/**
* 发件人邮箱(单个)
*/
@NotBlank
(
message
=
"发件人邮箱不能为空"
)
private
String
sendEmail
;
/**
* 邮件主题
*/
@NotBlank
(
message
=
"邮件主题不能为空"
)
private
String
subject
;
}
yd-email-feign/src/main/java/com/yd/email/feign/response/ApiSendEmailResponse.java
0 → 100644
View file @
ed904f15
package
com
.
yd
.
email
.
feign
.
response
;
import
lombok.Data
;
@Data
public
class
ApiSendEmailResponse
{
}
yd-email-service/src/main/java/com/yd/email/service/handler/MailSendJobHandler.java
deleted
100644 → 0
View file @
e9aa8ae5
package
com
.
yd
.
email
.
service
.
handler
;
import
com.xxl.job.core.biz.model.ReturnT
;
import
com.xxl.job.core.handler.IJobHandler
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
@Component
@Slf4j
public
class
MailSendJobHandler
extends
IJobHandler
{
@Autowired
private
MailService
mailService
;
@Autowired
private
MailTaskMapper
mailTaskMapper
;
@Autowired
private
MailRecipientMapper
mailRecipientMapper
;
@Override
public
ReturnT
<
String
>
execute
(
String
param
)
throws
Exception
{
log
.
info
(
"开始执行邮件发送任务,参数: {}"
,
param
);
Long
taskId
=
Long
.
parseLong
(
param
);
MailTask
mailTask
=
mailTaskMapper
.
selectById
(
taskId
);
if
(
mailTask
==
null
)
{
return
new
ReturnT
<>(
ReturnT
.
FAIL_CODE
,
"邮件任务不存在"
);
}
// 更新任务状态为发送中
mailTask
.
setStatus
(
1
);
mailTaskMapper
.
updateById
(
mailTask
);
try
{
// 查询所有收件人
List
<
MailRecipient
>
recipients
=
mailRecipientMapper
.
selectByTaskId
(
taskId
);
int
successCount
=
0
;
int
failCount
=
0
;
for
(
MailRecipient
recipient
:
recipients
)
{
try
{
List
<
String
>
ccList
=
recipient
.
getCcAddresses
()
!=
null
?
Arrays
.
asList
(
recipient
.
getCcAddresses
().
split
(
","
))
:
new
ArrayList
<>();
mailService
.
sendMail
(
mailTask
.
getFromAddress
(),
recipient
.
getToAddress
(),
ccList
,
mailTask
.
getSubject
(),
mailTask
.
getContent
(),
mailTask
.
getAttachmentPath
()
);
// 更新发送状态
recipient
.
setSendStatus
(
1
);
recipient
.
setSendTime
(
new
Date
());
mailRecipientMapper
.
updateById
(
recipient
);
successCount
++;
}
catch
(
Exception
e
)
{
log
.
error
(
"发送邮件失败: {}"
,
recipient
.
getToAddress
(),
e
);
recipient
.
setSendStatus
(
2
);
recipient
.
setErrorMsg
(
e
.
getMessage
());
mailRecipientMapper
.
updateById
(
recipient
);
failCount
++;
}
}
// 更新任务状态
mailTask
.
setStatus
(
failCount
==
0
?
2
:
3
);
// 全部成功为2,有失败为3
mailTaskMapper
.
updateById
(
mailTask
);
log
.
info
(
"邮件发送任务完成: 成功{}个, 失败{}个"
,
successCount
,
failCount
);
return
new
ReturnT
<>(
"发送完成: 成功"
+
successCount
+
"个, 失败"
+
failCount
+
"个"
);
}
catch
(
Exception
e
)
{
log
.
error
(
"邮件发送任务执行异常"
,
e
);
mailTask
.
setStatus
(
3
);
mailTaskMapper
.
updateById
(
mailTask
);
return
new
ReturnT
<>(
ReturnT
.
FAIL_CODE
,
"任务执行异常: "
+
e
.
getMessage
());
}
}
}
\ No newline at end of file
yd-email-service/src/main/java/com/yd/email/service/model/EmailTask.java
View file @
ed904f15
...
...
@@ -49,6 +49,12 @@ public class EmailTask implements Serializable {
private
String
senderBizId
;
/**
* 发件人邮箱(单个)
*/
@TableField
(
"send_email"
)
private
String
sendEmail
;
/**
* 邮件主题
*/
@TableField
(
"subject"
)
...
...
@@ -85,6 +91,12 @@ public class EmailTask implements Serializable {
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 @
ed904f15
...
...
@@ -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/EmailService.java
deleted
100644 → 0
View file @
e9aa8ae5
package
com
.
yd
.
email
.
service
.
service
;
public
interface
EmailService
{
}
yd-email-service/src/main/java/com/yd/email/service/service/IEmailTaskRecipientsService.java
View file @
ed904f15
...
...
@@ -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 @
ed904f15
...
...
@@ -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 @
ed904f15
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 @
ed904f15
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