提交 e2818ed1 作者: duanxincheng

邮件内容管理

父级 c76a5e57
......@@ -40,4 +40,9 @@ public class UserController {
public R tokenAuth(@Validated @RequestBody ApplicationUserVO.LoginDecrypt vo) {
return R.ok(userService.tokenAuth(vo));
}
@PostMapping(value = "/emailAuth")
public R emailAuth(@Validated @RequestBody UserVo.Auth vo) {
return R.ok(userService.emailAuth(vo));
}
}
\ No newline at end of file
package com.cmeeting.ad.filter;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.cmeeting.ad.entity.RobotSecurityUser;
......
......@@ -27,4 +27,6 @@ public interface UserService {
Object list(String search, Integer type, Integer userType, String categoryId, Integer authType);
Object tokenAuth(ApplicationUserVO.LoginDecrypt vo);
Object emailAuth(UserVo.Auth vo);
}
\ No newline at end of file
......@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cmeeting.ad.entity.*;
import com.cmeeting.ad.util.SecurityUtil;
import com.cmeeting.ad.vo.UserVo;
import com.cmeeting.exception.RobotBaseException;
import com.cmeeting.mapper.primary.CommonMapper;
import com.cmeeting.ad.service.ILdapService;
import com.cmeeting.ad.service.ISysTenantService;
......@@ -29,6 +30,8 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
......@@ -228,19 +231,50 @@ public class UserServiceImpl implements UserService {
@Override
public Object tokenAuth(ApplicationUserVO.LoginDecrypt vo) {
String aigcToken = vo.getData();
String url = userAdminConfig.getSystemDomain() + "/cloud/info";
JSONObject object = HttpClientUtils.httpGet(url, aigcToken);
if("0".equals(object.get("code"))){
return null;
}
JSONObject data = object.getJSONObject("data");
RobotSecurityUser robotSecurityUser = JSON.parseObject(data.toJSONString(), RobotSecurityUser.class);
// String aigcToken = vo.getData();
// String url = userAdminConfig.getSystemDomain() + "/cloud/info";
// JSONObject object = HttpClientUtils.httpGet(url, aigcToken);
// if("0".equals(object.get("code"))){
// return null;
// }
// JSONObject data = object.getJSONObject("data");
// RobotSecurityUser robotSecurityUser = JSON.parseObject(data.toJSONString(), RobotSecurityUser.class);
RobotSecurityUser robotSecurityUser = new RobotSecurityUser();
robotSecurityUser.setUsername("00010786");
robotSecurityUser.setNickName("黄飞");
UserVo.Auth authParams = UserVo.Auth.builder().id(robotSecurityUser.getUsername()).nick(robotSecurityUser.getNickName()).build();
String token = auth(authParams);
return token;
}
@Override
public String emailAuth(UserVo.Auth vo) {
String userId = vo.getId();
String nick = vo.getNick();
//时间戳
long expireDateTimestamp = vo.getExpireDate();
ZonedDateTime expireDate = Instant.ofEpochMilli(expireDateTimestamp).atZone(ZoneId.systemDefault());
ZonedDateTime now = ZonedDateTime.now();
if(expireDate.isBefore(now)){
throw new RobotBaseException("认证已过期!", 401);
}
long expireTimeStamp = Duration.between(now, expireDate).getSeconds();
HashMap<String, String> stringStringHashMap = new HashMap<>();
SysTenant sysTenant = iTenantService.getById(permissionTenantId);
stringStringHashMap.put("userId", userId);
stringStringHashMap.put("tenantId", permissionTenantId);
stringStringHashMap.put("language", sysTenant.getLanguage());
stringStringHashMap.put("nick", nick);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userId, permissionTenantId);
usernamePasswordAuthenticationToken.setDetails(stringStringHashMap);
Authentication authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
RobotSecurityUser userDetail = (RobotSecurityUser) authentication.getPrincipal();
String token = jwtUtil.generateToken(userDetail);
redisUtils.set(token, userDetail, expireTimeStamp);
return token;
}
private R loginByAD(ApplicationUserVO.Login login) {
// AD验证
// boolean auth = iLdapService.authenticate(login.getUsername().trim(), login.getPassword().trim());
......
......@@ -2,6 +2,7 @@ package com.cmeeting.ad.util;
import cn.hutool.core.util.StrUtil;
import com.cmeeting.ad.entity.RobotSecurityUser;
import com.cmeeting.exception.RobotBaseException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
......@@ -77,6 +78,9 @@ public class JwtUtil {
*/
public String getToken(HttpServletRequest request) {
String token = request.getHeader(tokenHeader);
if (StrUtil.isBlank(token)) {
throw new RobotBaseException("认证已过期!", 401);
}
if (StrUtil.isNotBlank(token) && token.length() > authTokenStart.length()) {
token = token.substring(authTokenStart.length()).trim();
}
......
......@@ -54,6 +54,8 @@ public class UserVo {
private String nick;
private String path;
private long expireDate;
}
/**
......
package com.cmeeting.controller;
import com.cmeeting.util.R;
import com.cmeeting.util.RedisUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
@RestController
@RequestMapping("/email")
public class EmailController {
@Resource
private RedisUtils redisUtils;
@PostMapping("/saveContentTemplate")
public R saveContentTemplate(@RequestBody Map<String,Object> map){
if(!map.containsKey("template")){
return R.error("保存失败");
}
redisUtils.set("EMAIL_CONTENT_TEMPLATE",map.get("template"));
return R.ok("保存成功");
}
@GetMapping("/getContentTemplate")
public R getTemplate(){
if(!redisUtils.hasKey("EMAIL_CONTENT_TEMPLATE")){
return R.error("邮件通知内容未设置");
}
return R.ok(redisUtils.get("EMAIL_CONTENT_TEMPLATE"));
}
}
......@@ -6,6 +6,7 @@ import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cmeeting.email.EmailSender;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
import com.cmeeting.mapper.primary.UserIdMapper;
import com.cmeeting.pojo.MeetingInfo;
import com.cmeeting.pojo.MeetingRecordTemplate;
import com.cmeeting.service.MeetingInfoService;
......@@ -55,6 +56,8 @@ public class MeetingInfoController {
private EmailSender emailSender;
@Resource
private MeetingRecordTemplateMapper meetingRecordTemplateMapper;
@Resource
private UserIdMapper userIdMapper;
@PostMapping("/updateRecordXml")
public R updateRecordXml(@RequestBody MeetingInfoVO vo) {
......@@ -218,11 +221,18 @@ public class MeetingInfoController {
List<EmailPush.Attachment> attachments = new ArrayList<>();
EmailPush.Attachment attachment = EmailPush.Attachment.builder().name(meetingInfo.getSubject()+"_数据网络中心").bytes(meetingMinutesBytes).build();
attachments.add(attachment);
String hostUid = meetingInfo.getHostUid();
String userCode = userIdMapper.getWidByTid(hostUid);
EmailPush emailPushBuilder = EmailPush.builder()
.toEmail(meetingInfo.getEmail())
.meetingId(meetingInfo.getMeetingId())
.attachments(attachments)
.subject(meetingInfo.getSubject()).build();
.subject(meetingInfo.getSubject())
.meetingInstanceId(meetingInfo.getId())
.subMeetingId(meetingInfo.getSubMeetingId())
.toUserCode(userCode)
.toUser(meetingInfo.getHost())
.build();
emailSender.sendEmailWithAttachment(emailPushBuilder);
return R.ok("发送纪要邮件成功");
} catch (Exception e) {
......
package com.cmeeting.controller;
import com.cmeeting.service.StressTestService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/stressTest")
public class StressTestController {
@Resource
private StressTestService service;
@PostMapping("/minutesGenerate")
public void minutesGenerate(){
service.minutesGenerate();
}
}
......@@ -4,7 +4,10 @@ import com.azure.core.credential.AccessToken;
import com.azure.core.credential.TokenRequestContext;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.cmeeting.ad.service.UserService;
import com.cmeeting.ad.vo.UserVo;
import com.cmeeting.log.service.ProcessLogService;
import com.cmeeting.util.RedisUtils;
import com.cmeeting.vo.EmailPush;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.*;
......@@ -29,6 +32,8 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Base64;
import java.util.LinkedList;
......@@ -51,6 +56,8 @@ public class EmailSender {
private ProcessLogService processLogService;
private static final Integer MAX_RETRY = 3;
@Resource
private RedisUtils redisUtils;
/**
* @param toEmail 收件人
......@@ -178,6 +185,10 @@ public class EmailSender {
// String toEmail = "duanxincheng@chatbot.cn";
String subject = emailPushBuilder.getSubject();
String meetingId = emailPushBuilder.getMeetingId();
String subMeetingId = emailPushBuilder.getSubMeetingId();
Integer meetingInstanceId = emailPushBuilder.getMeetingInstanceId();
String toUserCode = emailPushBuilder.getToUserCode();
String toUser = emailPushBuilder.getToUser();
if(StringUtils.isEmpty(toEmail)){
log.error("收件邮箱为空,推送失败");
processLogService.log(meetingId,null,"收件邮箱为空,推送失败");
......@@ -209,8 +220,22 @@ public class EmailSender {
com.microsoft.graph.models.Message message = new Message();
message.subject = subject + "会议纪要";
ItemBody body = new ItemBody();
body.contentType = BodyType.TEXT;
body.content = "您好:\n\n 附件为您本次会议的会议纪要,烦请下载查看";
body.contentType = BodyType.HTML;
if(redisUtils.hasKey("EMAIL_CONTENT_TEMPLATE")){
if(StringUtils.isEmpty(toUserCode)){
isSent = false;
processLogService.log(meetingId,subMeetingId,"【邮件推送异常】:收件人工号不能为空");
continue;
}
String email_content_template = String.valueOf(redisUtils.get("EMAIL_CONTENT_TEMPLATE"));
long expireTimestamp = ZonedDateTime.now().plusDays(2).toInstant().toEpochMilli();
body.content = MessageFormat.format(email_content_template,meetingInstanceId,toUserCode,String.valueOf(expireTimestamp));
}else{
isSent = false;
processLogService.log(meetingId,subMeetingId,"【邮件推送异常】:邮件模板未设置");
continue;
}
message.body = body;
LinkedList<Recipient> toRecipientsList = new LinkedList<>();
Recipient toRecipients = new Recipient();
......@@ -251,7 +276,7 @@ public class EmailSender {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
processLogService.log(meetingId,null,"【邮件推送异常】:"+sw.toString());
processLogService.log(meetingId,subMeetingId,"【邮件推送异常】:"+sw.toString());
if (retryCount.intValue() > MAX_RETRY) {
log.error("邮件发送达到最大重试次数: meetingId->{}", meetingId);
throw new RuntimeException(e);
......
package com.cmeeting.exception;
import com.cmeeting.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @Classname BExceptionHandler
* @Description 自定义异常处理
* @Author robot
* @Date 2019-03-29 13:23
* @Version 1.0
*/
@Slf4j
@RestControllerAdvice
public class BExceptionHandler {
/**
* 处理自定义异常
*/
@ExceptionHandler(RobotBaseException.class)
public R handlerException(RobotBaseException e) {
return R.error(e.getCode(), e.getMessage());
}
/**
* @Description 请求参数值异常
* @param e
* @return
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public R handlerException(MethodArgumentNotValidException e) {
return R.error(-1, e.getMessage());
}
}
package com.cmeeting.exception;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* @Classname BaseException
* @Description 自定义异常
* @Author robot
* @Date 2019-03-29 13:21
* @Version 1.0
*/
public class RobotBaseException extends RuntimeException implements Serializable {
private static final long serialVersionUID = 1L;
@Setter
@Getter
private String message;
@Setter
@Getter
private int code = 200;
public RobotBaseException(String msg) {
super(msg);
this.message = msg;
}
public RobotBaseException(String msg, Throwable e) {
super(msg, e);
this.message = msg;
}
public RobotBaseException(String msg, int code) {
super(msg);
this.message = msg;
this.code = code;
}
public RobotBaseException(String msg, int code, Throwable e) {
super(msg, e);
this.message = msg;
this.code = code;
}
}
......@@ -220,8 +220,11 @@ public class CmeetingJob {
meetingFiles.add(recordFile);
}
//查出企微id和腾会id的关联关系
List<UserId> userIdRelations = userIdMapper.selectList(null);
Map<String,String> tidWidRelations = userIdRelations.stream().collect(Collectors.toMap(UserId::getTid,UserId::getWid));
// 提交处理任务
producer.submitEmailPushTasks(meetingFiles);
producer.submitEmailPushTasks(meetingFiles,tidWidRelations);
log.info("-------邮件推送重试定时任务结束--------");
} catch (Exception e) {
e.printStackTrace();
......
......@@ -48,6 +48,7 @@ public class EmailPushTask {
private MinioUtils minioUtils;
private EmailSender emailSender;
private MeetingRecordTemplateMapper meetingRecordTemplateMapper;
private Map<String,String> tidWidRelations;
// 实际处理逻辑
public void process() {
......@@ -56,7 +57,13 @@ public class EmailPushTask {
MeetingInfo meetingInfo = meetingInfoMapper.selectOne(new LambdaQueryWrapper<MeetingInfo>()
.eq(MeetingInfo::getMeetingId,meetingId)
.eq(subMeetingId != null, MeetingInfo::getSubMeetingId, subMeetingId));
while (retryCount.intValue() <= MAX_RETRY && !isSuccess) {
String hostUid = meetingInfo.getHostUid();
if(!tidWidRelations.containsKey(hostUid)){
log.error("邮件推送重试失败: 主持人对应关系未配置。meetingId {}", meetingId);
continue;
}
try {
String meetingName;
String xml;
......@@ -100,7 +107,18 @@ public class EmailPushTask {
}finally {
FileUtil.del(dataNetworkMinutesPath);
}
EmailPush emailPushBuilder = EmailPush.builder().toEmail(meetingInfo.getEmail()).meetingId(meetingId).attachments(attachments).subject(meetingInfo.getSubject()).build();
String userCode = tidWidRelations.get(hostUid);
EmailPush emailPushBuilder = EmailPush.builder()
.toEmail(meetingInfo.getEmail())
.meetingId(meetingId)
.attachments(attachments)
.subject(meetingInfo.getSubject())
.meetingInstanceId(meetingInfo.getId())
.subMeetingId(meetingInfo.getSubMeetingId())
.toUserCode(userCode)
.toUser(meetingInfo.getHost())
.build();
isSuccess = emailSender.sendEmailWithAttachment(emailPushBuilder);
} catch (Exception e) {
// 异常处理
......@@ -164,7 +182,8 @@ public class EmailPushTask {
public EmailPushTask(String meetingId, String subMeetingId, String savePath, Map<String, Object> metadata,
MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, EmailSender emailSender, MeetingRecordTemplateMapper meetingRecordTemplateMapper) {
MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, EmailSender emailSender,
MeetingRecordTemplateMapper meetingRecordTemplateMapper,Map<String,String> tidWidRelations) {
this.savePath = savePath;
this.metadata = metadata;
this.meetingId = meetingId;
......@@ -173,5 +192,6 @@ public class EmailPushTask {
this.minioUtils = minioUtils;
this.emailSender = emailSender;
this.meetingRecordTemplateMapper = meetingRecordTemplateMapper;
this.tidWidRelations = tidWidRelations;
}
}
\ No newline at end of file
......@@ -291,7 +291,21 @@ public class FileProcessTask {
isSuccess = false;
continue;
}
EmailPush emailPushBuilder = EmailPush.builder().toEmail(meetingInfo.getEmail()).meetingId(meetingId).attachments(attachments).subject(meetingInfo.getSubject()).build();
if(!tidWidRelations.containsKey(meetingInfo.getHostUid())){
log.error("邮件推送重试失败: 主持人对应关系未配置。meetingId {}", meetingId);
processLogService.log(meetingId,subMeetingId,"邮件推送重试失败: 主持人对应关系未配置。meetingId "+meetingId);
continue;
}
EmailPush emailPushBuilder = EmailPush.builder()
.toEmail(meetingInfo.getEmail())
.meetingId(meetingId)
.attachments(attachments)
.subject(meetingInfo.getSubject())
.meetingInstanceId(meetingInfo.getId())
.subMeetingId(meetingInfo.getSubMeetingId())
.toUserCode(tidWidRelations.get(meetingInfo.getHostUid()))
.toUser(meetingInfo.getHost())
.build();
emailPush(emailPushBuilder);
isSuccess = true;
} catch (Exception e) {
......@@ -477,6 +491,7 @@ public class FileProcessTask {
.set(MeetingInfo::getRecordXml,recordXmlPath)
.set(MeetingInfo::getParticipantUsers,meetingInfo.getParticipantUsers())
.set(MeetingInfo::getIsGenerated,Boolean.TRUE)
.set(MeetingInfo::getTemplateId,meetingRecordTemplate.getId())
);
meetingInfo.setRecordContent(recordContentPath);
meetingInfo.setRecordXml(recordXmlPath);
......
......@@ -107,7 +107,7 @@ public class FileProcessProducer {
}
// 批量提交邮箱推送重试任务
public void submitEmailPushTasks(List<TencentMeetingVO.RecordFile> recordFiles) {
public void submitEmailPushTasks(List<TencentMeetingVO.RecordFile> recordFiles,Map<String,String> tidWidRelations) {
List<Future<?>> futures = new ArrayList<>();
for (TencentMeetingVO.RecordFile recordFile : recordFiles) {
......@@ -120,7 +120,8 @@ public class FileProcessProducer {
meetingInfoMapper,
minioUtils,
emailSender,
meetingRecordTemplateMapper
meetingRecordTemplateMapper,
tidWidRelations
);
// 提交任务到线程池
......
package com.cmeeting.service;
public interface StressTestService {
void minutesGenerate();
}
package com.cmeeting.service.impl;
import com.cmeeting.service.StressTestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class StressTestServiceImpl implements StressTestService {
@Override
public void minutesGenerate() {
}
}
......@@ -18,9 +18,26 @@ import java.util.List;
public class EmailPush {
private String toEmail;
/**
* 收件人工号
*/
private String toUserCode;
/**
* 收件人
*/
private String toUser;
private String subject;
/**
* 会议实例id(表主键)
*/
private Integer meetingInstanceId;
/**
* 会议id号
*/
private String meetingId;
private String subMeetingId;
/**
* 附件
*/
......
......@@ -26,7 +26,7 @@
select * from userid
</select>
<select id="getWidByTid" resultType="java.lang.String">
select wid from userid WHERE Tid = #{operatorUserId}
select wid from userid WHERE tid = #{operatorUserId}
</select>
</mapper>
\ No newline at end of file
......@@ -32,8 +32,9 @@
<select id="getUserEmail" resultType="com.cmeeting.dto.UserDTO">
select t1.user_id as wId,IFNULL(t1.email,t1.company_email) as email
from sys_user_sync t1
where t1.email is not null
or t1.company_email is not null
where (t1.email is not null
or t1.company_email is not null)
AND t1.tenant_id = #{tenantId}
</select>
<select id="getSimpleUserList" resultType="com.cmeeting.ad.entity.SysUserSync">
select t1.user_id as userId,t1.name
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论