Skip to content

Commit 0b14e72

Browse files
committed
feat: sendemail节点新增是否发送飞书选项#AI Commit#
1 parent 686d6bf commit 0b14e72

4 files changed

Lines changed: 154 additions & 176 deletions

File tree

docs/1.23.0/design/sendemail飞书发送_设计.md

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
## 一、设计概述
1313

14-
本设计在DSS工作流sendemail节点现有邮件发送功能的基础上,新增飞书消息发送能力。采用"后置增强"模式,在邮件发送成功后,根据配置和参数决定是否执行飞书发送,对现有代码侵入最小。
14+
本设计在DSS工作流sendemail节点现有邮件发送功能的基础上,新增飞书消息发送能力。采用"后置增强"模式,在邮件发送成功后,根据节点参数和飞书接收者决定是否执行飞书发送,对现有代码侵入最小。
1515

1616
---
1717

@@ -64,14 +64,15 @@ SendEmailRefExecutionOperation.execute(requestRef)
6464
+--> sendEmailAppConnHooks.preSend()
6565
+--> emailSender.send(email) <-- Step 1: 邮件发送
6666
|
67-
+--> if (FeishuConfig.isEnabled
67+
+--> 从runtimeMap读取sendFeishu
68+
+--> if (sendFeishu == true
6869
| && email.getFeishuTo != null
6970
| && email.getFeishuTo.trim.nonEmpty)
7071
| |
7172
| +--> FeishuMessageSender.send(email) <-- Step 2: 飞书发送
7273
| |
7374
| +--> FeishuConfig.validate() <-- 配置校验
74-
| +--> 解析feishuTo(逗号分隔
75+
| +--> 解析feishuTo(分号分隔
7576
| +--> FeishuClient.sendTextMessage() (主题通知)
7677
| +--> uploadAttachment() * N (附件上传)
7778
| | +--> FeishuClient.uploadFile()
@@ -95,20 +96,20 @@ public interface Email {
9596
// ... 原有方法 ...
9697

9798
/**
98-
* 获取飞书接收者open_id列表(逗号分隔
99+
* 获取飞书接收者open_id列表(分号分隔
99100
*/
100101
String getFeishuTo();
101102

102103
/**
103104
* 设置飞书接收者open_id列表
104-
* @param feishuTo 逗号分隔的open_id字符串
105+
* @param feishuTo 分号分隔的open_id字符串
105106
*/
106107
void setFeishuTo(String feishuTo);
107108
}
108109
```
109110

110111
**设计决策**:
111-
- feishuTo与to/cc/bcc字段对齐,采用逗号分隔的字符串格式
112+
- feishuTo与to/cc/bcc字段对齐,采用分号分隔的字符串格式
112113
- 不使用独立的FeishuEmail子接口,避免接口膨胀
113114
- 默认值为null(AbstractEmail中),运行时由AbstractEmailGenerator从runtimeMap读取并设置为空字符串
114115

@@ -132,25 +133,23 @@ class AbstractEmail extends Email {
132133

133134
**文件**: `SendEmailAppConnConfiguration.scala`
134135

135-
**新增配置项**:
136+
**新增系统连接配置项**:
136137

137138
| 配置键 | 类型 | 默认值 | 说明 |
138139
|-------|------|-------|------|
139-
| wds.dss.appconn.feishu.enabled | Boolean | false | 飞书发送全局开关 |
140140
| wds.dss.appconn.feishu.app.id | String | "" | 飞书应用App ID |
141141
| wds.dss.appconn.feishu.app.secret | String | "" | 飞书应用App Secret |
142142
| wds.dss.appconn.feishu.api.base.url | String | https://open.feishu.cn/open-apis | 飞书API基础地址 |
143143

144144
```scala
145-
val FEISHU_ENABLED = CommonVars("wds.dss.appconn.feishu.enabled", false)
146145
val FEISHU_APP_ID = CommonVars("wds.dss.appconn.feishu.app.id", "")
147146
val FEISHU_APP_SECRET = CommonVars("wds.dss.appconn.feishu.app.secret", "")
148147
val FEISHU_API_BASE_URL = CommonVars("wds.dss.appconn.feishu.api.base.url", "https://open.feishu.cn/open-apis")
149148
```
150149

151150
**设计决策**:
152-
- 所有配置项通过CommonVars管理,与现有邮件配置风格一致
153-
- 默认关闭飞书功能,确保升级兼容性
151+
- 连接配置项通过CommonVars管理,与现有邮件配置风格一致
152+
- 是否发送飞书不放在配置文件中,由sendemail节点参数 `sendFeishu` 控制
154153
- 支持自定义api.base.url,便于代理部署场景
155154

156155
### 3.4 FeishuConfig配置校验
@@ -161,24 +160,22 @@ val FEISHU_API_BASE_URL = CommonVars("wds.dss.appconn.feishu.api.base.url", "htt
161160

162161
```scala
163162
object FeishuConfig extends Logging {
164-
def isEnabled: Boolean = SendEmailAppConnConfiguration.FEISHU_ENABLED.getValue
165163
def getAppId: String = SendEmailAppConnConfiguration.FEISHU_APP_ID.getValue
166164
def getAppSecret: String = SendEmailAppConnConfiguration.FEISHU_APP_SECRET.getValue
167165
def getApiBaseUrl: String = SendEmailAppConnConfiguration.FEISHU_API_BASE_URL.getValue
168166

169167
def validate(): Unit = {
170-
if (isEnabled) {
171-
if (getAppId.isEmpty)
172-
throw new IllegalArgumentException("Feishu is enabled but app.id is not configured.")
173-
if (getAppSecret.isEmpty)
174-
throw new IllegalArgumentException("Feishu is enabled but app.secret is not configured.")
175-
}
168+
if (getAppId.isEmpty)
169+
throw new IllegalArgumentException("Feishu app.id is not configured.")
170+
if (getAppSecret.isEmpty)
171+
throw new IllegalArgumentException("Feishu app.secret is not configured.")
176172
}
177173
}
178174
```
179175

180176
**校验逻辑**:
181-
- 仅在enabled=true时校验appId和appSecret
177+
- FeishuConfig只负责连接配置读取和校验,不负责判断节点是否发送飞书
178+
- 仅当节点sendFeishu=true且feishuTo非空、实际进入飞书发送流程时调用validate()
182179
- 校验失败抛出IllegalArgumentException(快速失败,不做静默降级)
183180
- 不校验apiBaseUrl(默认值可用,自定义地址由用户自行保证正确性)
184181

@@ -274,7 +271,7 @@ send(email: Email): Unit
274271
|
275272
+--> 1. 校验feishuTo(null/空/纯空格 -> 跳过)
276273
+--> 2. FeishuConfig.validate()(配置校验)
277-
+--> 3. 解析接收者: feishuTo.split(",").map(_.trim).filter(_.nonEmpty)
274+
+--> 3. 解析接收者: feishuTo.split(";").map(_.trim).filter(_.nonEmpty)
278275
+--> 4. 发送主题文本消息
279276
| for each receiver:
280277
| FeishuClient.sendTextMessage(receiver, "open_id", "[DSS邮件通知] " + subject)
@@ -326,15 +323,21 @@ override def execute(requestRef): ExecutionResponseRef = {
326323
// Step 1: 发送邮件
327324
Utils.tryCatch {
328325
emailSender.send(email)
329-
}(putErrorMsg("发送邮件失败!", _))
326+
} { t =>
327+
return putErrorMsg("发送邮件失败!", t)
328+
}
330329

331330
// Step 2: 发送到飞书(可选)
332-
if (FeishuConfig.isEnabled && email.getFeishuTo != null && email.getFeishuTo.trim.nonEmpty) {
333-
logger.info(s"Feishu sending is enabled and feishuTo is configured: ${email.getFeishuTo}")
331+
val runtimeMap = requestRef.getExecutionRequestRefContext.getRuntimeMap
332+
val sendFeishu = Option(runtimeMap.get("sendFeishu")).exists(_.toString.equalsIgnoreCase("true"))
333+
if (sendFeishu && email.getFeishuTo != null && email.getFeishuTo.trim.nonEmpty) {
334+
logger.info(s"Feishu sending is selected and feishuTo is configured: ${email.getFeishuTo}")
334335
Utils.tryCatch {
335336
FeishuMessageSender.send(email)
336337
logger.info("Feishu sending completed successfully.")
337-
}(putErrorMsg("飞书发送失败!", _))
338+
} { t =>
339+
return putErrorMsg("飞书发送失败!", t)
340+
}
338341
}
339342

340343
new ExecutionResponseRefBuilder().success()
@@ -343,7 +346,7 @@ override def execute(requestRef): ExecutionResponseRef = {
343346

344347
**关键设计决策**:
345348
- 飞书发送在邮件发送之后执行(邮件失败直接return,不走飞书)
346-
- 飞书发送条件:enabled=true AND feishuTo非null AND feishuTo.trim非空
349+
- 飞书发送条件:sendFeishu=true AND feishuTo非null AND feishuTo.trim非空
347350
- 飞书发送失败时,节点标记为失败(不静默忽略)
348351
- 使用Utils.tryCatch包装,保持与邮件发送一致的异常处理风格
349352

@@ -402,13 +405,12 @@ email.setFeishuTo(feishuTo)
402405

403406
| 字段 | 类型 | 默认值 | 说明 |
404407
|------|------|-------|------|
405-
| feishuTo | String | null(AbstractEmail中)/ ""(Generator设置后) | 飞书接收者open_id列表,逗号分隔 |
408+
| feishuTo | String | null(AbstractEmail中)/ ""(Generator设置后) | 飞书接收者open_id列表,分号分隔 |
406409

407410
### 5.2 配置数据模型
408411

409412
| 配置键 | CommonVars变量 | 类型 | 默认值 |
410413
|-------|---------------|------|-------|
411-
| wds.dss.appconn.feishu.enabled | FEISHU_ENABLED | Boolean | false |
412414
| wds.dss.appconn.feishu.app.id | FEISHU_APP_ID | String | "" |
413415
| wds.dss.appconn.feishu.app.secret | FEISHU_APP_SECRET | String | "" |
414416
| wds.dss.appconn.feishu.api.base.url | FEISHU_API_BASE_URL | String | https://open.feishu.cn/open-apis |
@@ -443,8 +445,7 @@ email.setFeishuTo(feishuTo)
443445
`appconn.properties` 中添加以下配置:
444446

445447
```properties
446-
# 飞书发送功能(默认关闭,启用前需配置appId和appSecret)
447-
wds.dss.appconn.feishu.enabled=true
448+
# 飞书连接配置(是否发送飞书由sendemail节点参数sendFeishu控制)
448449
wds.dss.appconn.feishu.app.id=cli_xxxxxxxxxxxx
449450
wds.dss.appconn.feishu.app.secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
450451
# 自定义API地址(可选,默认为飞书官方地址)
@@ -453,10 +454,11 @@ wds.dss.appconn.feishu.app.secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
453454

454455
### 6.3 sendemail节点配置
455456

456-
在工作流sendemail节点的参数中,新增feishuTo字段
457+
在工作流sendemail节点的参数中,新增sendFeishu和feishuTo字段
457458

458459
```
459-
feishuTo=ou_xxxxxxxxxxxxxxxx,ou_yyyyyyyyyyyyyyyy
460+
sendFeishu=true
461+
feishuTo=ou_xxxxxxxxxxxxxxxx;ou_yyyyyyyyyyyyyyyy
460462
```
461463

462464
---
@@ -480,3 +482,5 @@ feishuTo=ou_xxxxxxxxxxxxxxxx,ou_yyyyyyyyyyyyyyyy
480482
| Token安全 | 内存缓存,不持久化到磁盘 |
481483
| 接收者验证 | 依赖飞书平台验证open_id有效性,无效ID返回错误 |
482484
| 网络安全 | 支持HTTPS(默认),支持自定义代理地址 |
485+
486+

0 commit comments

Comments
 (0)