Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
cmeeting
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
翟斌
cmeeting
Commits
6b22ba70
提交
6b22ba70
authored
6月 26, 2026
作者:
刘振萌
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
邮箱变更
父级
620577dc
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
116 行增加
和
230 行删除
+116
-230
pom.xml
+5
-49
src/main/java/com/cmeeting/email/EmailSender.java
+87
-152
src/main/java/com/cmeeting/job/CmeetingJob.java
+0
-4
src/main/java/com/cmeeting/job/FileProcessTask.java
+19
-19
src/main/resources/application.yml
+5
-6
没有找到文件。
pom.xml
浏览文件 @
6b22ba70
...
@@ -17,7 +17,6 @@
...
@@ -17,7 +17,6 @@
</properties>
</properties>
<dependencyManagement>
<dependencyManagement>
<dependencies>
<dependencies>
<!-- Microsoft Graph SDK -->
<dependency>
<dependency>
<groupId>
com.fasterxml.jackson.core
</groupId>
<groupId>
com.fasterxml.jackson.core
</groupId>
...
@@ -61,29 +60,6 @@
...
@@ -61,29 +60,6 @@
<version>
3.1
</version>
<version>
3.1
</version>
</dependency>
</dependency>
<dependency>
<dependency>
<groupId>
com.microsoft.graph
</groupId>
<artifactId>
microsoft-graph-auth
</artifactId>
<version>
0.3.0
</version>
</dependency>
<dependency>
<!-- Include the sdk as a dependency -->
<groupId>
com.microsoft.graph
</groupId>
<artifactId>
microsoft-graph-core
</artifactId>
<version>
2.0.14
</version>
</dependency>
<dependency>
<!-- Include the sdk as a dependency -->
<groupId>
com.microsoft.graph
</groupId>
<artifactId>
microsoft-graph
</artifactId>
<version>
5.42.0
</version>
</dependency>
<dependency>
<groupId>
com.azure
</groupId>
<artifactId>
azure-identity
</artifactId>
<version>
1.3.3
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
<artifactId>
spring-boot-starter-web
</artifactId>
<version>
2.5.15
</version>
<version>
2.5.15
</version>
...
@@ -154,19 +130,6 @@
...
@@ -154,19 +130,6 @@
<artifactId>
javax.mail
</artifactId>
<artifactId>
javax.mail
</artifactId>
<version>
1.6.2
</version>
<version>
1.6.2
</version>
</dependency>
</dependency>
<!-- Microsoft Graph SDK -->
<dependency>
<groupId>
com.microsoft.graph
</groupId>
<artifactId>
microsoft-graph-auth
</artifactId>
<version>
0.3.0
</version>
</dependency>
<dependency>
<!-- Include the sdk as a dependency -->
<groupId>
com.microsoft.graph
</groupId>
<artifactId>
microsoft-graph-core
</artifactId>
<version>
2.0.14
</version>
</dependency>
<!-- MSAL认证库 -->
<!-- MSAL认证库 -->
...
@@ -218,18 +181,6 @@
...
@@ -218,18 +181,6 @@
<version>
4.9.3
</version>
<!-- 使用最新版本 -->
<version>
4.9.3
</version>
<!-- 使用最新版本 -->
</dependency>
</dependency>
<dependency>
<dependency>
<groupId>
com.azure
</groupId>
<artifactId>
azure-identity
</artifactId>
<version>
1.3.3
</version>
</dependency>
<!-- 确保所有Azure库版本一致 -->
<dependency>
<groupId>
com.azure
</groupId>
<artifactId>
azure-core
</artifactId>
<version>
1.34.0
</version>
</dependency>
<dependency>
<groupId>
mysql
</groupId>
<groupId>
mysql
</groupId>
<artifactId>
mysql-connector-java
</artifactId>
<artifactId>
mysql-connector-java
</artifactId>
<version>
5.1.49
</version>
<!-- 请使用适合您MySQL版本的驱动 -->
<version>
5.1.49
</version>
<!-- 请使用适合您MySQL版本的驱动 -->
...
@@ -253,6 +204,11 @@
...
@@ -253,6 +204,11 @@
<version>
2.13.0
</version>
<version>
2.13.0
</version>
</dependency>
</dependency>
<dependency>
<dependency>
<groupId>
com.fasterxml.jackson.dataformat
</groupId>
<artifactId>
jackson-dataformat-xml
</artifactId>
<version>
2.13.0
</version>
</dependency>
<dependency>
<groupId>
com.fasterxml.jackson.module
</groupId>
<groupId>
com.fasterxml.jackson.module
</groupId>
<artifactId>
jackson-module-parameter-names
</artifactId>
<artifactId>
jackson-module-parameter-names
</artifactId>
<version>
2.13.0
</version>
<version>
2.13.0
</version>
...
...
src/main/java/com/cmeeting/email/EmailSender.java
浏览文件 @
6b22ba70
package
com
.
cmeeting
.
email
;
package
com
.
cmeeting
.
email
;
import
cn.hutool.json.JSONUtil
;
import
cn.hutool.json.JSONUtil
;
import
com.azure.core.credential.AccessToken
;
import
com.azure.core.credential.TokenRequestContext
;
import
com.azure.identity.ClientSecretCredential
;
import
com.azure.identity.ClientSecretCredentialBuilder
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.cmeeting.ad.service.UserService
;
import
com.cmeeting.ad.vo.UserVo
;
import
com.cmeeting.exception.RobotBaseException
;
import
com.cmeeting.log.service.ProcessLogService
;
import
com.cmeeting.log.service.ProcessLogService
;
import
com.cmeeting.pojo.MeetEmailTemplate
;
import
com.cmeeting.pojo.MeetEmailTemplate
;
import
com.cmeeting.service.MeetEmailTemplateService
;
import
com.cmeeting.service.MeetEmailTemplateService
;
import
com.cmeeting.util.AESUtils
;
import
com.cmeeting.util.AESUtils
;
import
com.cmeeting.util.RSAUtils
;
import
com.cmeeting.util.RedisUtils
;
import
com.cmeeting.vo.EmailPush
;
import
com.cmeeting.vo.EmailPush
;
import
com.cmeeting.vo.StatisticsEmailPush
;
import
com.cmeeting.vo.StatisticsEmailPush
;
import
com.microsoft.graph.authentication.TokenCredentialAuthProvider
;
import
com.microsoft.graph.models.*
;
import
com.microsoft.graph.models.Message
;
import
com.microsoft.graph.requests.AttachmentCollectionPage
;
import
com.microsoft.graph.requests.AttachmentCollectionResponse
;
import
com.microsoft.graph.requests.GraphServiceClient
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
okhttp3.Request
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
javax.activation.DataHandler
;
import
javax.activation.DataHandler
;
import
javax.activation.DataSource
;
import
javax.activation.FileDataSource
;
import
javax.annotation.Resource
;
import
javax.mail.*
;
import
javax.mail.*
;
import
javax.mail.internet.*
;
import
javax.mail.internet.*
;
import
java
.io.Fil
e
;
import
java
x.mail.util.ByteArrayDataSourc
e
;
import
java.io.PrintWriter
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.io.StringWriter
;
import
java.net.URLEncoder
;
import
java.net.URLEncoder
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.text.MessageFormat
;
import
java.text.MessageFormat
;
import
java.time.ZonedDateTime
;
import
java.time.ZonedDateTime
;
import
java
.util.*
;
import
java
x.annotation.Resource
;
import
java.util.
List
;
import
java.util.
Properties
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.atomic.AtomicInteger
;
@Slf4j
@Slf4j
...
@@ -53,16 +32,16 @@ import java.util.concurrent.atomic.AtomicInteger;
...
@@ -53,16 +32,16 @@ import java.util.concurrent.atomic.AtomicInteger;
public
class
EmailSender
{
public
class
EmailSender
{
@Value
(
"${email.sender}"
)
@Value
(
"${email.sender}"
)
private
String
SENDER
;
private
String
SENDER
;
@Value
(
"${email.sender-pwd}"
)
private
String
SENDER_PWD
;
@Value
(
"${email.smtp-host}"
)
private
String
SMTP_HOST
;
@Value
(
"${email.smtp-port}"
)
private
int
SMTP_PORT
;
@Value
(
"${email.push-switch}"
)
@Value
(
"${email.push-switch}"
)
private
Boolean
pushSwitch
;
private
Boolean
pushSwitch
;
@Value
(
"${email.environment}"
)
@Value
(
"${email.environment}"
)
private
String
environment
;
private
String
environment
;
@Value
(
"${email.microsoft.clientId}"
)
private
String
clientId
;
@Value
(
"${email.microsoft.clientSecret}"
)
private
String
clientSecret
;
@Value
(
"${email.microsoft.tenantId}"
)
private
String
tenantId
;
@Value
(
"${aec.key}"
)
@Value
(
"${aec.key}"
)
private
String
aseKey
;
private
String
aseKey
;
@Resource
@Resource
...
@@ -72,12 +51,25 @@ public class EmailSender {
...
@@ -72,12 +51,25 @@ public class EmailSender {
private
static
final
Integer
MAX_RETRY
=
3
;
private
static
final
Integer
MAX_RETRY
=
3
;
/**
private
Session
createMailSession
()
{
* 发送邮件,带附件
Properties
props
=
new
Properties
();
*
props
.
put
(
"mail.smtp.host"
,
SMTP_HOST
);
* @param emailPushBuilder
props
.
put
(
"mail.smtp.port"
,
String
.
valueOf
(
SMTP_PORT
));
* @return
props
.
put
(
"mail.smtp.auth"
,
"true"
);
*/
props
.
put
(
"mail.smtp.ssl.enable"
,
"true"
);
props
.
put
(
"mail.smtp.ssl.protocols"
,
"TLSv1.2"
);
props
.
put
(
"mail.smtp.connectiontimeout"
,
"30000"
);
props
.
put
(
"mail.smtp.timeout"
,
"60000"
);
props
.
put
(
"mail.smtp.writetimeout"
,
"60000"
);
return
Session
.
getInstance
(
props
,
new
Authenticator
()
{
@Override
protected
PasswordAuthentication
getPasswordAuthentication
()
{
return
new
PasswordAuthentication
(
SENDER
,
SENDER_PWD
);
}
});
}
public
Boolean
sendEmailWithAttachment
(
EmailPush
emailPushBuilder
)
{
public
Boolean
sendEmailWithAttachment
(
EmailPush
emailPushBuilder
)
{
log
.
info
(
"sendEmailWithAttachment start, sender -> {}"
,
SENDER
);
log
.
info
(
"sendEmailWithAttachment start, sender -> {}"
,
SENDER
);
...
@@ -86,7 +78,7 @@ public class EmailSender {
...
@@ -86,7 +78,7 @@ public class EmailSender {
throw
new
RuntimeException
(
"【邮箱推送】:应用未开启邮件推送功能"
);
throw
new
RuntimeException
(
"【邮箱推送】:应用未开启邮件推送功能"
);
}
}
AtomicInteger
retryCount
=
new
AtomicInteger
(
0
);
AtomicInteger
retryCount
=
new
AtomicInteger
(
0
);
B
oolean
isSent
=
false
;
b
oolean
isSent
=
false
;
String
toEmail
=
emailPushBuilder
.
getToEmail
();
String
toEmail
=
emailPushBuilder
.
getToEmail
();
String
subject
=
emailPushBuilder
.
getSubject
();
String
subject
=
emailPushBuilder
.
getSubject
();
String
meetingRecordId
=
emailPushBuilder
.
getMeetingRecordId
();
String
meetingRecordId
=
emailPushBuilder
.
getMeetingRecordId
();
...
@@ -96,110 +88,80 @@ public class EmailSender {
...
@@ -96,110 +88,80 @@ public class EmailSender {
String
toUserCode
=
emailPushBuilder
.
getToUserCode
();
String
toUserCode
=
emailPushBuilder
.
getToUserCode
();
String
toUser
=
emailPushBuilder
.
getToUser
();
String
toUser
=
emailPushBuilder
.
getToUser
();
Boolean
emailPushAccess
=
emailPushBuilder
.
getEmailPushAccess
();
Boolean
emailPushAccess
=
emailPushBuilder
.
getEmailPushAccess
();
//用户自定义邮件推送许可
if
(
emailPushAccess
)
{
if
(
emailPushAccess
)
{
log
.
info
(
"用户允许邮件推送,准备推送邮件至{}------"
,
emailPushBuilder
.
getToEmail
());
log
.
info
(
"用户允许邮件推送,准备推送邮件至{}------"
,
emailPushBuilder
.
getToEmail
());
}
else
{
}
else
{
log
.
info
(
"用户关闭了邮件推送,推送终止------"
);
log
.
info
(
"用户关闭了邮件推送,推送终止------"
);
processLogService
.
log
(
meetingId
,
subMeetingId
,
"用户关闭了邮件推送,推送终止"
);
processLogService
.
log
(
meetingId
,
subMeetingId
,
"用户关闭了邮件推送,推送终止"
);
throw
new
RuntimeException
(
"用户关闭了邮件推送,推送终止"
);
throw
new
RuntimeException
(
"用户关闭了邮件推送,推送终止"
);
}
}
if
(
StringUtils
.
isEmpty
(
toEmail
))
{
if
(
StringUtils
.
isEmpty
(
toEmail
))
{
log
.
error
(
"收件邮箱为空,推送失败"
);
log
.
error
(
"收件邮箱为空,推送失败"
);
processLogService
.
log
(
meetingId
,
subMeetingId
,
"收件邮箱为空,推送失败。environment->"
+
environment
+
",realEmail->"
+
emailPushBuilder
.
getToEmail
());
processLogService
.
log
(
meetingId
,
subMeetingId
,
"收件邮箱为空,推送失败。environment->"
+
environment
+
",realEmail->"
+
emailPushBuilder
.
getToEmail
());
throw
new
RuntimeException
(
"收件邮箱为空,推送失败"
);
throw
new
RuntimeException
(
"收件邮箱为空,推送失败"
);
}
}
log
.
info
(
"准备开始邮件推送..."
);
log
.
info
(
"准备开始邮件推送..."
);
while
(
retryCount
.
intValue
()
<
MAX_RETRY
&&
isSent
!=
null
&&
!
isSent
)
{
while
(
retryCount
.
intValue
()
<
MAX_RETRY
&&
!
isSent
)
{
try
{
try
{
ClientSecretCredential
clientSecretCredential
=
new
ClientSecretCredentialBuilder
()
Session
session
=
createMailSession
();
.
clientId
(
RSAUtils
.
decrypt
(
clientId
))
MimeMessage
message
=
new
MimeMessage
(
session
);
.
clientSecret
(
RSAUtils
.
decrypt
(
clientSecret
))
message
.
setFrom
(
new
InternetAddress
(
SENDER
));
.
tenantId
(
RSAUtils
.
decrypt
(
tenantId
))
message
.
setRecipient
(
Message
.
RecipientType
.
TO
,
new
InternetAddress
(
toEmail
));
.
build
();
message
.
setSubject
(
subject
+
"会议纪要"
,
"UTF-8"
);
try
{
TokenRequestContext
context
=
new
TokenRequestContext
()
.
addScopes
(
"https://graph.microsoft.com/.default"
);
AccessToken
token
=
clientSecretCredential
.
getToken
(
context
).
block
();
System
.
out
.
println
(
token
!=
null
?
token
.
getToken
()
:
null
);
}
catch
(
Exception
e
)
{
log
.
error
(
"获取访问令牌失败: {}"
,
e
.
getMessage
());
}
final
TokenCredentialAuthProvider
tokenCredAuthProvider
=
new
TokenCredentialAuthProvider
(
Arrays
.
asList
(
"https://graph.microsoft.com/.default"
),
clientSecretCredential
);
System
.
out
.
println
(
"First Step Reached. "
);
GraphServiceClient
<
Request
>
graphClient
=
GraphServiceClient
.
builder
().
authenticationProvider
(
tokenCredAuthProvider
).
buildClient
();
com
.
microsoft
.
graph
.
models
.
Message
message
=
new
Message
();
message
.
subject
=
subject
+
"会议纪要"
;
ItemBody
body
=
new
ItemBody
();
body
.
contentType
=
BodyType
.
HTML
;
if
(
StringUtils
.
isEmpty
(
toUserCode
))
{
if
(
StringUtils
.
isEmpty
(
toUserCode
))
{
isSent
=
false
;
processLogService
.
log
(
meetingId
,
subMeetingId
,
"【邮件推送异常】:收件人工号不能为空"
);
processLogService
.
log
(
meetingId
,
subMeetingId
,
"【邮件推送异常】:收件人工号不能为空"
);
continue
;
continue
;
}
}
// HTML body content from template
MimeBodyPart
bodyPart
=
new
MimeBodyPart
();
MeetEmailTemplate
one
=
meetEmailTemplateService
.
getOne
(
new
LambdaQueryWrapper
<
MeetEmailTemplate
>()
MeetEmailTemplate
one
=
meetEmailTemplateService
.
getOne
(
new
LambdaQueryWrapper
<
MeetEmailTemplate
>()
.
orderByDesc
(
MeetEmailTemplate:
:
getCreateTime
)
.
orderByDesc
(
MeetEmailTemplate:
:
getCreateTime
)
.
select
(
MeetEmailTemplate:
:
getContent
).
last
(
"limit 1"
));
.
select
(
MeetEmailTemplate:
:
getContent
).
last
(
"limit 1"
));
String
emailContentTemplate
=
one
.
getContent
();
String
emailContentTemplate
=
one
.
getContent
();
long
expireTimestamp
=
ZonedDateTime
.
now
().
plusDays
(
1
).
toInstant
().
toEpochMilli
();
long
expireTimestamp
=
ZonedDateTime
.
now
().
plusDays
(
1
).
toInstant
().
toEpochMilli
();
UserVo
.
Auth
auth
=
new
UserVo
.
Auth
();
com
.
cmeeting
.
ad
.
vo
.
UserVo
.
Auth
auth
=
new
com
.
cmeeting
.
ad
.
vo
.
UserVo
.
Auth
();
auth
.
setId
(
toUserCode
);
auth
.
setId
(
toUserCode
);
auth
.
setNick
(
toUser
);
auth
.
setNick
(
toUser
);
auth
.
setExpireDate
(
expireTimestamp
);
auth
.
setExpireDate
(
expireTimestamp
);
String
s
=
JSONUtil
.
toJsonStr
(
auth
);
String
s
=
JSONUtil
.
toJsonStr
(
auth
);
String
encrypt
=
AESUtils
.
encrypt
(
s
,
aseKey
);
String
encrypt
=
AESUtils
.
encrypt
(
s
,
aseKey
);
body
.
content
=
MessageFormat
.
format
(
emailContentTemplate
,
URLEncoder
.
encode
(
encrypt
,
StandardCharsets
.
UTF_8
.
name
()),
String
.
valueOf
(
meetingInstanceId
));
String
htmlContent
=
MessageFormat
.
format
(
emailContentTemplate
,
URLEncoder
.
encode
(
encrypt
,
StandardCharsets
.
UTF_8
.
name
()),
String
.
valueOf
(
meetingInstanceId
));
bodyPart
.
setContent
(
htmlContent
,
"text/html; charset=utf-8"
);
// Build attachments
Multipart
multipart
=
new
MimeMultipart
();
multipart
.
addBodyPart
(
bodyPart
);
message
.
body
=
body
;
LinkedList
<
Recipient
>
toRecipientsList
=
new
LinkedList
<>();
Recipient
toRecipients
=
new
Recipient
();
EmailAddress
emailAddress
=
new
EmailAddress
();
emailAddress
.
address
=
toEmail
;
toRecipients
.
emailAddress
=
emailAddress
;
toRecipientsList
.
add
(
toRecipients
);
message
.
toRecipients
=
toRecipientsList
;
//构建附件
LinkedList
<
Attachment
>
attachmentsList
=
new
LinkedList
<>();
for
(
EmailPush
.
Attachment
attachment
:
emailPushBuilder
.
getAttachments
())
{
for
(
EmailPush
.
Attachment
attachment
:
emailPushBuilder
.
getAttachments
())
{
FileAttachment
attachments
=
new
FileAttachment
();
MimeBodyPart
attachPart
=
new
MimeBodyPart
();
if
(
attachment
.
getName
().
endsWith
(
".pdf"
))
{
String
fileName
=
attachment
.
getName
();
attachments
.
name
=
attachment
.
getName
();
String
contentType
;
attachments
.
contentType
=
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
;
if
(
fileName
.
endsWith
(
".pdf"
))
{
contentType
=
"application/pdf"
;
}
else
{
}
else
{
attachments
.
name
=
attachment
.
getName
()
+
".docx"
;
fileName
+=
".docx"
;
attachments
.
contentType
=
"application/pdf
"
;
contentType
=
"application/vnd.openxmlformats-officedocument.wordprocessingml.document
"
;
}
}
attach
ments
.
oDataType
=
"#microsoft.graph.fileAttachment"
;
attach
Part
.
setDataHandler
(
new
DataHandler
(
new
ByteArrayDataSource
(
attachment
.
getBytes
(),
contentType
)))
;
attach
ments
.
contentBytes
=
attachment
.
getBytes
(
);
attach
Part
.
setFileName
(
MimeUtility
.
encodeText
(
fileName
,
"UTF-8"
,
"B"
)
);
attachmentsList
.
add
(
attachments
);
multipart
.
addBodyPart
(
attachPart
);
}
}
AttachmentCollectionResponse
attachmentCollectionResponse
=
new
AttachmentCollectionResponse
();
message
.
setContent
(
multipart
);
attachmentCollectionResponse
.
value
=
attachmentsList
;
Transport
.
send
(
message
);
AttachmentCollectionPage
attachmentCollectionPage
=
new
AttachmentCollectionPage
(
attachmentCollectionResponse
,
null
);
message
.
attachments
=
attachmentCollectionPage
;
//以指定用户邮箱发送邮件
graphClient
.
users
(
SENDER
)
.
sendMail
(
UserSendMailParameterSet
.
newBuilder
().
withMessage
(
message
).
withSaveToSentItems
(
true
).
build
())
.
buildRequest
()
.
post
();
log
.
info
(
"邮件已成功发送: meetingRecordId->{}"
,
meetingRecordId
);
log
.
info
(
"邮件已成功发送: meetingRecordId->{}"
,
meetingRecordId
);
isSent
=
true
;
isSent
=
true
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
retryCount
.
getAndIncrement
();
retryCount
.
getAndIncrement
();
// 异常处理
StringWriter
sw
=
new
StringWriter
();
StringWriter
sw
=
new
StringWriter
();
PrintWriter
pw
=
new
PrintWriter
(
sw
);
PrintWriter
pw
=
new
PrintWriter
(
sw
);
e
.
printStackTrace
(
pw
);
e
.
printStackTrace
(
pw
);
...
@@ -208,7 +170,6 @@ public class EmailSender {
...
@@ -208,7 +170,6 @@ public class EmailSender {
log
.
error
(
"邮件发送达到最大重试次数: meetingId->{}"
,
meetingId
);
log
.
error
(
"邮件发送达到最大重试次数: meetingId->{}"
,
meetingId
);
throw
new
RuntimeException
(
e
);
throw
new
RuntimeException
(
e
);
}
}
// 指数退避
try
{
try
{
Thread
.
sleep
((
long
)
Math
.
pow
(
2
,
retryCount
.
intValue
())
*
1000
);
Thread
.
sleep
((
long
)
Math
.
pow
(
2
,
retryCount
.
intValue
())
*
1000
);
}
catch
(
InterruptedException
ie
)
{
}
catch
(
InterruptedException
ie
)
{
...
@@ -227,65 +188,41 @@ public class EmailSender {
...
@@ -227,65 +188,41 @@ public class EmailSender {
boolean
isSent
=
false
;
boolean
isSent
=
false
;
while
(
retryCount
.
intValue
()
<
MAX_RETRY
&&
!
isSent
)
{
while
(
retryCount
.
intValue
()
<
MAX_RETRY
&&
!
isSent
)
{
try
{
try
{
ClientSecretCredential
clientSecretCredential
=
new
ClientSecretCredentialBuilder
()
Session
session
=
createMailSession
();
.
clientId
(
RSAUtils
.
decrypt
(
clientId
))
MimeMessage
message
=
new
MimeMessage
(
session
);
.
clientSecret
(
RSAUtils
.
decrypt
(
clientSecret
))
message
.
setFrom
(
new
InternetAddress
(
SENDER
));
.
tenantId
(
RSAUtils
.
decrypt
(
tenantId
))
message
.
setSubject
(
emailPushBuilder
.
getSubject
(),
"UTF-8"
);
.
build
();
try
{
// HTML body
TokenRequestContext
context
=
new
TokenRequestContext
().
addScopes
(
"https://graph.microsoft.com/.default"
);
MimeBodyPart
bodyPart
=
new
MimeBodyPart
();
AccessToken
token
=
clientSecretCredential
.
getToken
(
context
).
block
();
bodyPart
.
setContent
(
emailPushBuilder
.
getContent
(),
"text/html; charset=utf-8"
);
System
.
out
.
println
(
token
!=
null
?
token
.
getToken
()
:
null
);
}
catch
(
Exception
e
)
{
log
.
error
(
"统计邮件获取访问令牌失败: {}"
,
e
.
getMessage
());
}
final
TokenCredentialAuthProvider
tokenCredAuthProvider
=
new
TokenCredentialAuthProvider
(
Collections
.
singletonList
(
"https://graph.microsoft.com/.default"
),
clientSecretCredential
);
System
.
out
.
println
(
"First Step Reached. "
);
GraphServiceClient
<
Request
>
graphClient
=
GraphServiceClient
.
builder
().
authenticationProvider
(
tokenCredAuthProvider
).
buildClient
();
com
.
microsoft
.
graph
.
models
.
Message
message
=
new
Message
();
// Recipients
message
.
subject
=
emailPushBuilder
.
getSubject
();
ItemBody
body
=
new
ItemBody
();
body
.
contentType
=
BodyType
.
HTML
;
body
.
content
=
emailPushBuilder
.
getContent
();
message
.
body
=
body
;
LinkedList
<
Recipient
>
toRecipientsList
=
new
LinkedList
<>();
for
(
StatisticsEmailPush
.
ToEmail
toEmail
:
emailPushBuilder
.
getToEmails
())
{
for
(
StatisticsEmailPush
.
ToEmail
toEmail
:
emailPushBuilder
.
getToEmails
())
{
Recipient
toRecipients
=
new
Recipient
();
message
.
addRecipient
(
Message
.
RecipientType
.
TO
,
EmailAddress
emailAddress
=
new
EmailAddress
();
new
InternetAddress
(
toEmail
.
getEmail
(),
toEmail
.
getUser
()));
emailAddress
.
address
=
toEmail
.
getEmail
();
emailAddress
.
name
=
toEmail
.
getUser
();
toRecipients
.
emailAddress
=
emailAddress
;
toRecipientsList
.
add
(
toRecipients
);
}
}
message
.
toRecipients
=
toRecipientsList
;
//构建附件
// Attachments
LinkedList
<
Attachment
>
attachmentsList
=
new
LinkedList
<>();
Multipart
multipart
=
new
MimeMultipart
();
multipart
.
addBodyPart
(
bodyPart
);
for
(
StatisticsEmailPush
.
Attachment
attachment
:
emailPushBuilder
.
getAttachments
())
{
for
(
StatisticsEmailPush
.
Attachment
attachment
:
emailPushBuilder
.
getAttachments
())
{
FileAttachment
attachments
=
new
FileAttachmen
t
();
MimeBodyPart
attachPart
=
new
MimeBodyPar
t
();
attachments
.
n
ame
=
attachment
.
getName
()
+
".xlsx"
;
String
fileN
ame
=
attachment
.
getName
()
+
".xlsx"
;
attachments
.
oDataType
=
"#microsoft.graph.fileAttachmen
t"
;
String
contentType
=
"application/vnd.openxmlformats-officedocument.spreadsheetml.shee
t"
;
attach
ments
.
contentType
=
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
;
attach
Part
.
setDataHandler
(
new
DataHandler
(
new
ByteArrayDataSource
(
attachment
.
getBytes
(),
contentType
)))
;
attach
ments
.
contentBytes
=
attachment
.
getBytes
(
);
attach
Part
.
setFileName
(
MimeUtility
.
encodeText
(
fileName
,
"UTF-8"
,
"B"
)
);
attachmentsList
.
add
(
attachments
);
multipart
.
addBodyPart
(
attachPart
);
}
}
AttachmentCollectionResponse
attachmentCollectionResponse
=
new
AttachmentCollectionResponse
(
);
message
.
setContent
(
multipart
);
attachmentCollectionResponse
.
value
=
attachmentsList
;
Transport
.
send
(
message
)
;
message
.
attachments
=
new
AttachmentCollectionPage
(
attachmentCollectionResponse
,
null
);
//以指定用户邮箱发送邮件
graphClient
.
users
(
SENDER
)
.
sendMail
(
UserSendMailParameterSet
.
newBuilder
().
withMessage
(
message
).
withSaveToSentItems
(
true
).
build
())
.
buildRequest
()
.
post
();
log
.
info
(
"统计邮件已成功发送"
);
log
.
info
(
"统计邮件已成功发送"
);
isSent
=
true
;
isSent
=
true
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
retryCount
.
getAndIncrement
();
retryCount
.
getAndIncrement
();
// 异常处理
StringWriter
sw
=
new
StringWriter
();
StringWriter
sw
=
new
StringWriter
();
PrintWriter
pw
=
new
PrintWriter
(
sw
);
PrintWriter
pw
=
new
PrintWriter
(
sw
);
e
.
printStackTrace
(
pw
);
e
.
printStackTrace
(
pw
);
...
@@ -293,7 +230,6 @@ public class EmailSender {
...
@@ -293,7 +230,6 @@ public class EmailSender {
log
.
error
(
"统计邮件发送达到最大重试次数"
);
log
.
error
(
"统计邮件发送达到最大重试次数"
);
throw
new
RuntimeException
(
e
);
throw
new
RuntimeException
(
e
);
}
}
// 指数退避
try
{
try
{
Thread
.
sleep
((
long
)
Math
.
pow
(
2
,
retryCount
.
intValue
())
*
1000
);
Thread
.
sleep
((
long
)
Math
.
pow
(
2
,
retryCount
.
intValue
())
*
1000
);
}
catch
(
InterruptedException
ie
)
{
}
catch
(
InterruptedException
ie
)
{
...
@@ -303,4 +239,4 @@ public class EmailSender {
...
@@ -303,4 +239,4 @@ public class EmailSender {
}
}
}
}
}
}
}
}
\ No newline at end of file
src/main/java/com/cmeeting/job/CmeetingJob.java
浏览文件 @
6b22ba70
...
@@ -3,10 +3,6 @@ package com.cmeeting.job;
...
@@ -3,10 +3,6 @@ package com.cmeeting.job;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.hutool.core.thread.ThreadUtil
;
import
cn.hutool.core.thread.ThreadUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.azure.core.credential.AccessToken
;
import
com.azure.core.credential.TokenRequestContext
;
import
com.azure.identity.ClientSecretCredential
;
import
com.azure.identity.ClientSecretCredentialBuilder
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.cmeeting.config.StatisticsEmailPushProperties
;
import
com.cmeeting.config.StatisticsEmailPushProperties
;
import
com.cmeeting.constant.DeptCollect
;
import
com.cmeeting.constant.DeptCollect
;
...
...
src/main/java/com/cmeeting/job/FileProcessTask.java
浏览文件 @
6b22ba70
...
@@ -367,25 +367,25 @@ public class FileProcessTask {
...
@@ -367,25 +367,25 @@ public class FileProcessTask {
"text/plain; charset=utf-8"
,
// MIME类型
"text/plain; charset=utf-8"
,
// MIME类型
recordData
.
getBytes
(
StandardCharsets
.
UTF_8
)
// 字节内容
recordData
.
getBytes
(
StandardCharsets
.
UTF_8
)
// 字节内容
);
);
//将转录文件存到知识向量库
//
//将转录文件存到知识向量库
Map
<
String
,
String
>
otherParams
=
new
HashMap
<>();
//
Map<String, String> otherParams = new HashMap<>();
otherParams
.
put
(
"userId"
,
toUserCode
);
//
otherParams.put("userId", toUserCode);
otherParams
.
put
(
"tenantId"
,
permTenantId
);
//
otherParams.put("tenantId", permTenantId);
otherParams
.
put
(
"layout"
,
"V1"
);
//
otherParams.put("layout", "V1");
String
responseData
=
HttpClientKnowledgePlatformUtil
.
sendPostByFormDataFiles
(
userAdminConfig
.
getDocDomain
()
+
KnowledgePlatformRouteConstant
.
DOC
.
SIMPLE_DOC_UPLOAD_URL
,
Arrays
.
asList
(
multipartFile
),
otherParams
,
null
);
//
String responseData = HttpClientKnowledgePlatformUtil.sendPostByFormDataFiles(userAdminConfig.getDocDomain() + KnowledgePlatformRouteConstant.DOC.SIMPLE_DOC_UPLOAD_URL, Arrays.asList(multipartFile), otherParams, null);
if
(
StringUtils
.
isNotBlank
(
responseData
))
{
//
if (StringUtils.isNotBlank(responseData)) {
R
result
=
JSON
.
parseObject
(
responseData
,
R
.
class
);
//
R result = JSON.parseObject(responseData, R.class);
List
<
DocResultDto
>
docResultDtoList
=
JSON
.
parseObject
(
JSONObject
.
toJSONString
(
result
.
getData
()),
new
TypeReference
<
List
<
DocResultDto
>>()
{
//
List<DocResultDto> docResultDtoList = JSON.parseObject(JSONObject.toJSONString(result.getData()), new TypeReference<List<DocResultDto>>() {
});
//
});
DocResultDto
docResultDto
=
docResultDtoList
.
get
(
0
);
//
DocResultDto docResultDto = docResultDtoList.get(0);
// String previewPath = docResultDto.getPreviewPath();
//
//
String previewPath = docResultDto.getPreviewPath();
// recordContentPath = previewPath.replaceAll(fileDownloadPath,"");
//
//
recordContentPath = previewPath.replaceAll(fileDownloadPath,"");
meetingInfo
.
setTransDocId
(
docResultDto
.
getId
());
//
meetingInfo.setTransDocId(docResultDto.getId());
}
else
{
//
} else {
processLogService
.
log
(
meetingId
,
subMeetingId
,
"填充会议纪要失败,上传转录文件到向量知识库失败"
);
//
processLogService.log(meetingId, subMeetingId, "填充会议纪要失败,上传转录文件到向量知识库失败");
// throw new RuntimeException("填充会议纪要失败");
//
//
throw new RuntimeException("填充会议纪要失败");
meetingInfo
.
setTransDocId
(
""
);
//
meetingInfo.setTransDocId("");
}
//
}
// 将转录文件保存到MinIO
// 将转录文件保存到MinIO
String
encryptedRecordData
=
AESUtils
.
encrypt
(
recordData
,
aesKey
);
String
encryptedRecordData
=
AESUtils
.
encrypt
(
recordData
,
aesKey
);
...
...
src/main/resources/application.yml
浏览文件 @
6b22ba70
...
@@ -34,7 +34,9 @@ CORP_SECRET: 7YLePWG7rJqkQFnAB4FeylqAXpmu7q5qv_NOeSGNbm0
...
@@ -34,7 +34,9 @@ CORP_SECRET: 7YLePWG7rJqkQFnAB4FeylqAXpmu7q5qv_NOeSGNbm0
############################################################## email
############################################################## email
EMAIL_SENDER
:
cmeeting_assistant@cimc.com
EMAIL_SENDER
:
cmeeting_assistant@cimc.com
EMAIL_SMTP_HOST
:
smtp.office365.com
EMAIL_SENDER_PWD
:
4Zno69350R7Hwrj8
EMAIL_SMTP_HOST
:
mail.ksomail.com
EMAIL_SMTP_PORT
:
465
############################################################## permission
############################################################## permission
PERMISSION_APPLiCATION_ID
:
1945681039926104064
PERMISSION_APPLiCATION_ID
:
1945681039926104064
...
@@ -106,14 +108,11 @@ tencent:
...
@@ -106,14 +108,11 @@ tencent:
email
:
email
:
sender
:
${EMAIL_SENDER}
sender
:
${EMAIL_SENDER}
#
sender-pwd: ${EMAIL_SENDER_PWD}
sender-pwd
:
${EMAIL_SENDER_PWD}
smtp-host
:
${EMAIL_SMTP_HOST}
smtp-host
:
${EMAIL_SMTP_HOST}
smtp-port
:
${EMAIL_SMTP_PORT}
push-switch
:
true
#邮件推送总开关,高优先级
push-switch
:
true
#邮件推送总开关,高优先级
environment
:
prod
#test推给本公司人员,prod推给用户
environment
:
prod
#test推给本公司人员,prod推给用户
microsoft
:
clientId
:
'
rNvsNtIQTUAD7aYik9/1LDpfO+XbM4nuPkpf131H8vHfJg7Uj7HxJJcHFbtmO4uWagelhTsOTSx2PDqjeuqiYw=='
clientSecret
:
'
DERmPlHbjiN4rjIFHvpe+OypNRCuSwLe/MBy56EFtI7FkzHfOnVjMdCTRG/CmybBBfha6geFbijC6ymeMVSSeg=='
tenantId
:
'
dFSC/Jg4ibKnmKWCofo1KfR5IdsvHEHYiAE0iehpiyj0rzes8BRBzvQAu2rjG8SAm8VQetE+sLNvxObI8vq5iA=='
llm
:
llm
:
api-addr
:
${LLM_API_ADDR}
api-addr
:
${LLM_API_ADDR}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论