提交 0a34c27f 作者: zhaibin

定时拉取已结束会议获取录制文件

父级 69b04a25
......@@ -7,18 +7,34 @@
<groupId>org.example</groupId>
<artifactId>tencent_callback</artifactId>
<version>1.0-SNAPSHOT</version>
<!--<profiles>
<profile>
<id>allow-snapshots</id>
<activation><activeByDefault>true</activeByDefault></activation>
<repositories>
<repository>
<id>snapshots-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<releases><enabled>false</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
</profile>
</profiles>-->
<!-- <activeProfiles>
<activeProfile>central</activeProfile>
<activeProfile>allow-snapshots</activeProfile>
</activeProfiles>-->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 统一指定所有Azure库的版本 -->
<azure.version>1.10.0</azure.version>
<microsoft.graph.version>5.70.0</microsoft.graph.version>
<jackson.version>2.13.0</jackson.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Microsoft Graph SDK -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
......@@ -48,6 +64,38 @@
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</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>
<artifactId>spring-boot-starter-web</artifactId>
......@@ -115,18 +163,8 @@
<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>${microsoft.graph.version}</version>
</dependency>
<!-- MSAL认证库 -->
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>msal4j</artifactId>
<version>1.19.1</version>
</dependency>
<dependency>
<groupId>com.microsoft.ews-java-api</groupId>
......@@ -234,7 +272,7 @@
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20240303</version> <!-- 使用最新版本 -->
<version>20231013</version> <!-- 使用最新版本 -->
</dependency>
<!-- Jackson 核心模块 -->
<dependency>
......@@ -247,7 +285,28 @@
<artifactId>jackson-module-parameter-names</artifactId>
<version>2.13.0</version>
</dependency>
<!-- Markdown 处理 -->
<dependency>
<groupId>com.vladsch.flexmark</groupId>
<artifactId>flexmark-all</artifactId>
<version>0.62.2</version>
</dependency>
<!-- Word 文档操作 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.17.1</version> <!-- 可升级至最新稳定版 -->
</dependency>
</dependencies>
</project>
\ No newline at end of file
......@@ -3,23 +3,25 @@ package com.cmeeting;
import com.azure.core.credential.TokenRequestContext;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.nimbusds.jose.shaded.gson.Gson;
import okhttp3.*;
import com.google.gson.JsonObject;
import java.io.IOException;
public class GraphApiWithOkHttp {
static String CLIENT_ID = "d65aa91b-05f4-42b2-9/**/02f-4d82ea5a2b93";
static String CLIENT_ID = "d65aa91b-05f4-42b2-902f-4d82ea5a2b93";
static String TENANT_ID = "74cc8acf-aacc-4514-9bbb-dc27ce3096bb"; // or "common" for multi-tenant apps
static String CLIENT_SECRET = "~N98Q~83v6dViQFIofwr0fRn4J5VEZ2tvwOz.bPX";
private static final String USER_EMAIL = "binzhai321@outlook.com"; // 发送邮件的用户
private static final String USER_EMAIL = "biinizhai321@outlook.com"; // 发送邮件的用户
public static void main(String[] args) throws IOException {
/**中集:
* c06fe7cf-2a89-4099-9805-ce03031938f8
* wsu8Q~GxYxPLf2akioQZDRG8NR1EzCAHIAQRVc6u
* 18653b3e-03c7-499e-8baf-42ef06a814ef
*/
ClientSecretCredential credential = new ClientSecretCredentialBuilder()
.clientId("d65aa91b-05f4-42b2-902f-4d82ea5a2b93")
.clientSecret("~N98Q~83v6dViQFIofwr0fRn4J5VEZ2tvwOz.bPX")
.tenantId("74cc8acf-aacc-4514-9bbb-dc27ce3096bb")
.clientId(CLIENT_ID)
.clientSecret(CLIENT_SECRET)
.tenantId(TENANT_ID)
.build();
// 1. 获取 Access Token
......@@ -32,7 +34,7 @@ public class GraphApiWithOkHttp {
String token1 ="EwBYBMl6BAAUBKgm8k1UswUNwklmy2v7U/S+1fEAAUa0jd3QNQBdqTy9ZwEaLPqqapU5zHFRz4XvGqbI7jN7x01mEvBtCSFgYtNiSOEb5s1UwLxl6HwlHFqfJsqDsoCicvnlqCWjsaR/4wPZgXxd+pBhHRSPl+tJcSzz2NJB+dy81wHcSaU4bRxCIgoU7MtrW2ak9DhGisnK4/vxHkzxuIjHe9IDOZBzwzAtTZhycWRoAtuQrC1iu/kuKGJaU9noNjsOwfHUaXRz68g6niSdPT8P6zOa2vlOHjhXh478ms1PhqKeTkS+nkTurT2Gc5qRJviICiiAlK4BlxV70tOA6xEtl2ApXOrfFr+rlv4pASmPewtbdkTHnpP3H0R9L0kQZgAAEF4HO14XaFxPCdIqniVBvSkgA75wLsTuUZragTXGu71SV7ccLi26nZ+9KZlulf8dAlj/NEdheqtdEHb+BOLknQoXFEJ0UNj6PLkczzHfV3Yr5zlXJICwb3yI9vrFTUCb555ux/P904vXCY900UNgX81gBIYJQIJtOCURDAcHWtxyWvfNlkr17fKgnX5KdDyec6JK9tgzPi62LlqhDcoR/W/4MTCZhfJRlZgdYkI52pQSbDJItR6W7xfZguXPgKRHVcZJTzlybtOW0kbrfv96CKrryKzGeRjZyEcov1U3VjAoBUllgi3+LdIFK86aojMuBP+v5PvRq81qZS2q5roIRJD5zydu1selrpwhrZjm2nupDxHGjvfj2TVZJlz1zGYsVYrSRz2+st+2UbZagR1fbPRX2GilTfDyN05HV//LrfdrddbffMImxY2M8D9iQZFSjBYSFa20S9Vs9/yj08M9ljwiJifHGjX2o/arR63SWe3pbga26EC+j8JaBemhAhPsu91xW4o7+j/xEUadXR2NDbuogMq+MeINKe3PqAAFeTva1ZWZF5p3oGVIQKL4pcQFA9xEwopoN+vSeHDuAOvTFQ/4PukxicJdFTiaZquGeQMF0sLFvLdddpvS3Xaf17fPxjMUlMGcjYQ8gK5XG5wzjR8Up4MZZyX3xiK/hccGOp5pwi8WAN5cVmTKZOSXTkHUGEQT4rcGUYTPduHYMjjrVpzffpnmqfO92VA7a7fuYqXKp3NPikv17s6PTVr6b4+24AP8u3MEhDHU2YjaMuFR3jBUYLxtm443Gn58MC7oYrmQIVN2VYJrxADgStqpE+3nUCyKajmF0q5U+LUI1cCYnOKgmAkrpN71qlB9GeQLLQDJytG2sg64NG/h3CN1SseudSYtmqM3XUURSsztB9dNL7xmHQAcEBYMVjec5N5jHLhIs48rxAqI/WAJ/2RFKWgJIeCUJ8v4oQYEI9lAlWgReVhrjcNxRsbuVDFFwU7cTSeY9bJzxSX5kWJ8TXr/Q/SELEViUVCz10Cw/sOtm4urke538R4yXlR1wfMk3S86xlOfc3HJ6Iz7hi1h2fovWA9T1ceFWQM=";
// 2. 使用 OkHttp 发送邮件
sendEmail(token1);
sendEmail(token);
}
......@@ -52,7 +54,7 @@ public class GraphApiWithOkHttp {
" \"toRecipients\": [\n" +
" {\n" +
" \"emailAddress\": {\n" +
" \"address\": \"mengfan@itcast.cn\"\n" +
" \"address\": \"binzhai321@outlook.com\"\n" +
" }\n" +
" }\n" +
" ]\n" +
......@@ -62,7 +64,7 @@ public class GraphApiWithOkHttp {
// 构建请求
Request request = new Request.Builder()
.url("https://graph.microsoft.com/v1.0/users/" + USER_EMAIL + "/sendMail")
.post(RequestBody.create(emailJson, MediaType.parse("application/json")))
.post(RequestBody.create(MediaType.parse("application/json"), emailJson))
.addHeader("authorization", "Bearer " + accessToken)
.addHeader("Content-Type", "application/json")
.build();
......@@ -77,4 +79,4 @@ public class GraphApiWithOkHttp {
}
}
}
}
\ No newline at end of file
}
package com.cmeeting;
import com.azure.core.credential.AccessToken;
import com.azure.core.credential.TokenRequestContext;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.microsoft.graph.authentication.IAuthenticationProvider;
import com.microsoft.graph.requests.AttachmentCollectionPage;
import com.microsoft.graph.requests.AttachmentCollectionResponse;
import com.microsoft.graph.requests.GraphServiceClient;
import com.microsoft.graph.models.*;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Base64;
import java.util.LinkedList;
public class OutlookTest {
// 创建日志记录器
private static final Logger logger = LoggerFactory.getLogger(OutlookTest.class);
public static void main(String[] args) throws Exception {
// Azure AD 应用程序的客户端凭证
String clientId = "d65aa91b-05f4-42b2-902f-4d82ea5a2b93";
String clientSecret = "~N98Q~83v6dViQFIofwr0fRn4J5VEZ2tvwOz.bPX";
String tenantId = "74cc8acf-aacc-4514-9bbb-dc27ce3096bb";
String scope = "https://graph.microsoft.com/.default";
// 使用 ClientSecretCredential 获取 token
ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.clientId(clientId).tenantId(tenantId).clientSecret(clientSecret).build();
if (null == scope || null == clientSecretCredential) {
throw new Exception("Unexpected error");
}
// 创建身份验证提供者
IAuthenticationProvider authProvider = request -> {
// 创建 TokenRequestContext 对象并指定所需的范围
TokenRequestContext requestContext = new TokenRequestContext();
requestContext.addScopes("https://graph.microsoft.com/.default"); // 这里指定需要的范围
// 获取访问令牌
String accessToken = clientSecretCredential.getToken(requestContext).block().getToken();
// SDK 会自动将令牌添加到请求头中,您不需要手动操作 request 对象
return null;
};
// 创建 Graph 客户端
GraphServiceClient<Request> graphClient = GraphServiceClient
.builder()
.authenticationProvider(authProvider)
.buildClient();
// 打印访问令牌
printAccessToken(clientSecretCredential);
/* // 启用调试日志
GraphServiceClient<okhttp3.Request> graphClient = GraphServiceClient
.builder()
.authenticationProvider(tokenCredAuthProvider)
.httpClient(createHttpClient()) // 设置启用调试日志的 HTTP 客户端
.buildClient();*/
// 调用 Graph API 发送邮件
test(graphClient);
}
static void printAccessToken(ClientSecretCredential clientSecretCredential) {
try {
TokenRequestContext requestContext = new TokenRequestContext();
requestContext.addScopes("https://graph.microsoft.com/.default");
// 获取访问令牌
AccessToken accessToken = clientSecretCredential.getToken(requestContext).block();
if (accessToken != null && !accessToken.getToken().isEmpty()) {
System.out.println("Access Token: " + accessToken.getToken());
System.out.println("Expires On: " + accessToken.getExpiresAt().toEpochSecond());
} else {
System.out.println("Failed to retrieve access token.");
}
} catch (Exception e) {
System.err.println("Error while retrieving access token: " + e.getMessage());
}
}
public static void test(GraphServiceClient<okhttp3.Request> graphClient) throws IOException {
try {
// 创建邮件对象
Message message = new Message();
message.subject = "Meet for lunch?";
ItemBody body = new ItemBody();
body.contentType = BodyType.TEXT;
body.content = "The new cafeteria is open.";
message.body = body;
// 设置收件人
LinkedList<Recipient> toRecipientsList = new LinkedList<>();
Recipient toRecipients = new Recipient();
EmailAddress emailAddress = new EmailAddress();
emailAddress.address = "binzhai321@outlook.com";
toRecipients.emailAddress = emailAddress;
toRecipientsList.add(toRecipients);
message.toRecipients = toRecipientsList;
// 创建附件
LinkedList<Attachment> attachmentsList = new LinkedList<>();
FileAttachment attachments = new FileAttachment();
attachments.name = "1111.txt";
attachments.oDataType = "#microsoft.graph.fileAttachment";
attachments.contentType = "text/plain";
attachments.contentBytes = Base64.getDecoder().decode("SGVsbG8gV29ybGQh");
attachmentsList.add(attachments);
AttachmentCollectionResponse attachmentCollectionResponse = new AttachmentCollectionResponse();
attachmentCollectionResponse.value = attachmentsList;
AttachmentCollectionPage attachmentCollectionPage = new AttachmentCollectionPage(attachmentCollectionResponse, null);
message.attachments = attachmentCollectionPage;
// 发送邮件
graphClient.users("binzhai321@outlook.com")
.sendMail(UserSendMailParameterSet.newBuilder()
.withMessage(message)
.withSaveToSentItems(null)
.build())
.buildRequest()
.post();
System.out.println("Email sent successfully!");
} catch (Exception e) {
System.err.println("Error occurred: " + e.getMessage());
if (e instanceof com.microsoft.graph.http.GraphServiceException) {
com.microsoft.graph.http.GraphServiceException graphException = (com.microsoft.graph.http.GraphServiceException) e;
System.err.println("Error code: " + graphException.getServiceError().code);
System.err.println("Error message: " + graphException.getServiceError().message);
}
e.printStackTrace();
}
}
private static OkHttpClient createHttpClient() {
return new OkHttpClient.Builder()
.addInterceptor(chain -> {
okhttp3.Request originalRequest = chain.request();
// 打印原始请求头
System.out.println("Original Request Headers: " + originalRequest.headers());
// 确保 Authorization 头未被覆盖
okhttp3.Request modifiedRequest = originalRequest.newBuilder()
.headers(originalRequest.headers()) // 保留原始请求头
.build();
return chain.proceed(modifiedRequest);
})
.build();
}
}
package com.cmeeting;
import com.azure.core.credential.TokenRequestContext;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.http.GraphServiceException;
import com.microsoft.graph.models.Message;
import com.microsoft.graph.requests.GraphServiceClient;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import com.microsoft.graph.models.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
public class SendMailExample {
private static final Logger logger = LoggerFactory.getLogger(OutlookTest.class);
public static void main(String[] args) {
// 1. Azure AD 配置
final String clientId = "d65aa91b-05f4-42b2-902f-4d82ea5a2b93";
final String tenantId = "74cc8acf-aacc-4514-9bbb-dc27ce3096bb";
final String clientSecret = "~N98Q~83v6dViQFIofwr0fRn4J5VEZ2tvwOz.bPX";
// 2. 创建认证凭据
ClientSecretCredential credential = new ClientSecretCredentialBuilder()
.clientId(clientId)
.tenantId(tenantId)
.clientSecret(clientSecret)
.build();
String token = credential.getToken(
new TokenRequestContext()
.addScopes("https://graph.microsoft.com/.default"))
.block().getToken();
System.out.println("获取到的令牌:"+ token);
// 3. 初始化认证提供者
TokenCredentialAuthProvider authProvider = new TokenCredentialAuthProvider(
Collections.singletonList("https://graph.microsoft.com/.default"),
credential);
// 4. 创建 Graph 客户端
GraphServiceClient<Request> graphClient = GraphServiceClient.builder()
.authenticationProvider(authProvider)
.httpClient(createHttpClient())
.buildClient();
// 5. 构建邮件内容
Message message = new Message();
message.subject = "Test from Java 8";
ItemBody body = new ItemBody();
body.contentType = BodyType.TEXT;
body.content = "This works with Java 8!";
message.body = body;
EmailAddress emailAddress = new EmailAddress();
emailAddress.address = "binzhai321@outlook.com";
Recipient recipient = new Recipient();
recipient.emailAddress = emailAddress;
message.toRecipients = Collections.singletonList(recipient);
// 最兼容的发送方式
try {
// 创建参数集
UserSendMailParameterSet parameterSet = UserSendMailParameterSet.newBuilder()
.withMessage(message)
.withSaveToSentItems(true)
.build();
// 指定目标用户的 ID 或邮箱地址
String userId = "binzhai321@outlook.com";
// 发送邮件
graphClient.users(userId)
.sendMail(parameterSet)
.buildRequest()
.post();
System.out.println("Email sent successfully!");
} catch (GraphServiceException e) {
System.err.println("Error code: " + e.getServiceError().code);
System.err.println("Error message: " + e.getServiceError().message);
System.err.println("Headers: " + e.getRequestHeaders());
System.out.println(e.getMessage());
e.printStackTrace();
}
}
private static OkHttpClient createHttpClient() {
return new OkHttpClient.Builder()
.addInterceptor(chain -> {
okhttp3.Request request = chain.request();
// 打印请求信息
System.out.println("--> " + request.method() + " " + request.url());
if (request.body() != null) {
System.out.println("Request Body: " + request.body().toString());
}
if (request.headers() != null) {
System.out.println("Request Headers: " + request.headers().toString());
}
okhttp3.Response response = chain.proceed(request);
// 打印响应信息
if (response.body() != null) {
String responseBody = response.body().string();
System.out.println("<-- " + response.code() + " " + response.message() + " " + response.request().url());
System.out.println("Response Body: " + responseBody);
// 重新包装响应体
response = response.newBuilder()
.body(okhttp3.ResponseBody.create(responseBody, okhttp3.MediaType.parse("application/json")))
.build();
}
return response;
})
.build();
}
}
\ No newline at end of file
......@@ -3,8 +3,10 @@ package com.cmeeting;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class TencentMeetingCallbackApplication {
public static void main(String[] args) {
SpringApplication.run(TencentMeetingCallbackApplication.class, args);
......
......@@ -200,6 +200,9 @@ public class UnifiedController {
* @return
*/
private String getMeetingHost(String meetingCode) {
/**
* 腾讯会议参数
*/
Client client = new Client.Builder()
.withAppId("211153201").withSdkId("28370276340")
.withSecret("BKOMDZVbvh0iT7k6UHsSizAWBCOVDtT6", "3Y1j0mzNp7KChKFJGyaEnZHLobFoAQ8eLwfaMx8nLbtXAerO")
......@@ -293,7 +296,6 @@ public class UnifiedController {
// 创建预约会议(传入 wid 作为主持人)
private static Map<String, String> createMeeting(String wid, String weComToken) throws IOException {
String url = "https://qyapi.weixin.qq.com/cgi-bin/meeting/create?access_token=" + weComToken;
JSONObject body = new JSONObject()
.put("admin_userid", wid) // 主持人 userid
.put("title", "自动创建会议")
......@@ -319,10 +321,8 @@ public class UnifiedController {
return result;
}
}
public List<UserId> mergeUserLists(List<WeComUser> weComUsersIsRepeat0, List<TencentMeetingUser> tencentUsersIsRepeat0) {
List<UserId> userIds = new ArrayList<>();
// 1. 首先构建姓名到TencentMeetingUser的映射(提高查找效率)
Map<String, TencentMeetingUser> tencentUserMap = tencentUsersIsRepeat0.stream()
.collect(Collectors.toMap(
......@@ -335,7 +335,6 @@ public class UnifiedController {
UserId userId = new UserId();
userId.setUserName(weComUser.getUserName());
userId.setWid(weComUser.getUserId()); // 始终设置WeCom userid
// 检查是否存在同名Tencent用户
TencentMeetingUser tencentUser = tencentUserMap.get(weComUser.getUserName());
if (tencentUser != null) {
......
......@@ -24,7 +24,9 @@ import static com.cmeeting.WeComAndTencentMeeting.*;
@RequestMapping("/wecom")
public class WeComcontroller {
private static final String BASE_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist";
private static final String ACCESS_TOKEN = "wyYAmCbeVIPvj_Gpdd8ixp_td_hPv2OtTU8gpTGSpB7TaftbpNps5fc_JdCRzpgy_tUv-aGueJpRV6XJeYAG-rqkzCfDV-rcpJbqB0LypjvJUtxPeTmPqEtQuCMwH6euGGVaJZXoc33ATrS70U0T4_4WIrATqpsN2Ed2XsNGyN5N6aG8mq6AyLMG9TokVWx1qd2qF1zVTwve6aqRMWHwXg";
//动态获取token
@Autowired
private WeComService weComService;
......
package com.cmeeting.email;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.microsoft.graph.authentication.IAuthenticationProvider;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.*;
import com.microsoft.graph.requests.GraphServiceClient;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.Response;
import java.io.*;
import java.io.File;
import java.util.Arrays;
import java.util.LinkedList;
public class AzureADEmailSender {
public static void main(String[] args) throws IOException {
//d65aa91b-05f4-42b2-902f-4d82ea5a2b93
//~N98Q~83v6dViQFIofwr0fRn4J5VEZ2tvwOz.bPX
//74cc8acf-aacc-4514-9bbb-dc27ce3096bb
/**中集
* c06fe7cf-2a89-4099-9805-ce03031938f8
* wsu8Q~GxYxPLf2akioQZDRG8NR1EzCAHIAQRVc6u
* 18653b3e-03c7-499e-8baf-42ef06a814ef
*/
ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.clientId("d65aa91b-05f4-42b2-902f-4d82ea5a2b93")
.clientSecret("~N98Q~83v6dViQFIofwr0fRn4J5VEZ2tvwOz.bPX")
.tenantId("74cc8acf-aacc-4514-9bbb-dc27ce3096bb")
.build();
final TokenCredentialAuthProvider tokenCredAuthProvider = new TokenCredentialAuthProvider(Arrays.asList("https://graph.microsoft.com/.default"), clientSecretCredential);
System.out.println("First Step Reached. ");
buildDraftMessage(tokenCredAuthProvider);
}
private static final long MB = 1024 * 1024;
//binzhai321@outlook.com
//cmeeting_assistant@cimc.com
private static final String SENDER_MAIL = "binzhai321@outlook.com";
private static final String RECIPIENT_MAIL = "binzhai321@outlook.com";
public static void buildDraftMessage(TokenCredentialAuthProvider authProvider) throws IOException {
GraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();
Message message = new Message();
message.subject = "Did you see last night's game?";
ItemBody body = new ItemBody();
body.contentType = BodyType.HTML;
body.content = "They were <b>awesome</b>!";
message.body = body;
LinkedList<Recipient> toRecipientsList = new LinkedList<Recipient>();
Recipient toRecipients = new Recipient();
EmailAddress emailAddress = new EmailAddress();
emailAddress.address = RECIPIENT_MAIL;
toRecipients.emailAddress = emailAddress;
toRecipientsList.add(toRecipients);
message.toRecipients = toRecipientsList;
//构建草稿
Message post = graphClient.users(SENDER_MAIL).messages()
.buildRequest()
.post(message);
//构建附件
buildAttach(authProvider, post);
//发送草稿邮件
graphClient.users(SENDER_MAIL).messages(post.id)
.send()
.buildRequest()
.post();
}
private static void buildAttach(IAuthenticationProvider authProvider, Message message) throws IOException {
File file = new File("path");
FileInputStream fileInputStream = new FileInputStream(file);
int available = fileInputStream.available();
if (available >= 3 * MB) {
//附件大于3M,使用大附件专用发送方法
bigAttach(authProvider, message, file);
} else {
//附件小于3M,使用普通发送方法
commonAttach(authProvider, message, fileInputStream);
}
}
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024 * 4];
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
return output.toByteArray();
}
private static void commonAttach(IAuthenticationProvider authProvider, Message message, FileInputStream fileInputStream) throws IOException {
GraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();
FileAttachment attachment = new FileAttachment();
attachment.oDataType = "#microsoft.graph.fileAttachment";
attachment.name = "smile.pdf";
attachment.contentBytes = toByteArray(fileInputStream);
graphClient.users(SENDER_MAIL).messages(message.id).attachments()
.buildRequest()
.post(attachment);
}
public static void bigAttach(IAuthenticationProvider authProvider, Message message, File file) throws IOException {
GraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();
FileInputStream fileInputStream = new FileInputStream(file);
int available = fileInputStream.available();
AttachmentItem attachmentItem = new AttachmentItem();
attachmentItem.attachmentType = AttachmentType.FILE;
attachmentItem.name = "flower.pdf";
attachmentItem.size = (long) available;
UploadSession uploadSession = graphClient.users(SENDER_MAIL).messages(message.id).attachments()
.createUploadSession(AttachmentCreateUploadSessionParameterSet
.newBuilder()
.withAttachmentItem(attachmentItem)
.build())
.buildRequest()
.post();
OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.parse("application/octet-stream");
RequestBody body = RequestBody.create(mediaType, file);
okhttp3.Request request = new okhttp3.Request.Builder()
.url(uploadSession.uploadUrl)
.method("PUT", body)
.addHeader("Content-Length", String.valueOf(attachmentItem.size))
.addHeader("Content-Range", "bytes 0-" + (attachmentItem.size - 1) + "/" + attachmentItem.size)
.addHeader("Content-Type", "application/octet-stream")
.build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
}
}
\ No newline at end of file
package com.cmeeting;
package com.cmeeting.email;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;
import java.io.File;
import java.util.Properties;
public class EmailSender {
// 发件人邮箱配置(建议从配置文件读取,此处写死示例)
private static final String FROM_EMAIL = "binzhai321@163.com";
private static final String AUTH_CODE = "RXbRu3AdrCxX57ib"; // 授权码
......@@ -85,4 +85,5 @@ public class EmailSender {
public static boolean sendEmailWithAttachment(String toEmail, String filePath) {
return sendEmailWithAttachment(toEmail, filePath, null, null);
}
}
\ No newline at end of file
package com.cmeeting.email;
import com.azure.core.credential.TokenRequestContext;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import okhttp3.*;
import java.io.IOException;
public class GraphApiWithOkHttp2 {
static String CLIENT_ID = "d65aa91b-05f4-42b2-902f-4d82ea5a2b93";
static String TENANT_ID = "74cc8acf-aacc-4514-9bbb-dc27ce3096bb"; // or "common" for multi-tenant apps
static String CLIENT_SECRET = "~N98Q~83v6dViQFIofwr0fRn4J5VEZ2tvwOz.bPX";
//"cmeeting_assistant@cimc.com"
//"binzhai321@outlook.com"
private static final String USER_EMAIL = "cmeeting_assistant@cimc.com"; // 发送邮件的用户
public static void main(String[] args) throws IOException {
/**中集:
* c06fe7cf-2a89-4099-9805-ce03031938f8
* wsu8Q~GxYxPLf2akioQZDRG8NR1EzCAHIAQRVc6u
* 18653b3e-03c7-499e-8baf-42ef06a814ef
*/
ClientSecretCredential credential = new ClientSecretCredentialBuilder()
.clientId("c06fe7cf-2a89-4099-9805-ce03031938f8")
.clientSecret("wsu8Q~GxYxPLf2akioQZDRG8NR1EzCAHIAQRVc6u")
.tenantId("18653b3e-03c7-499e-8baf-42ef06a814ef")
.build();
// 1. 获取 Access Token
String token = credential.getToken(
new TokenRequestContext()
.addScopes("https://graph.microsoft.com/.default"))
.block().getToken();
System.out.println("获取到的令牌: " + token);
// String token1 ="EwBYBMl6BAAUBKgm8k1UswUNwklmy2v7U/S+1fEAAUa0jd3QNQBdqTy9ZwEaLPqqapU5zHFRz4XvGqbI7jN7x01mEvBtCSFgYtNiSOEb5s1UwLxl6HwlHFqfJsqDsoCicvnlqCWjsaR/4wPZgXxd+pBhHRSPl+tJcSzz2NJB+dy81wHcSaU4bRxCIgoU7MtrW2ak9DhGisnK4/vxHkzxuIjHe9IDOZBzwzAtTZhycWRoAtuQrC1iu/kuKGJaU9noNjsOwfHUaXRz68g6niSdPT8P6zOa2vlOHjhXh478ms1PhqKeTkS+nkTurT2Gc5qRJviICiiAlK4BlxV70tOA6xEtl2ApXOrfFr+rlv4pASmPewtbdkTHnpP3H0R9L0kQZgAAEF4HO14XaFxPCdIqniVBvSkgA75wLsTuUZragTXGu71SV7ccLi26nZ+9KZlulf8dAlj/NEdheqtdEHb+BOLknQoXFEJ0UNj6PLkczzHfV3Yr5zlXJICwb3yI9vrFTUCb555ux/P904vXCY900UNgX81gBIYJQIJtOCURDAcHWtxyWvfNlkr17fKgnX5KdDyec6JK9tgzPi62LlqhDcoR/W/4MTCZhfJRlZgdYkI52pQSbDJItR6W7xfZguXPgKRHVcZJTzlybtOW0kbrfv96CKrryKzGeRjZyEcov1U3VjAoBUllgi3+LdIFK86aojMuBP+v5PvRq81qZS2q5roIRJD5zydu1selrpwhrZjm2nupDxHGjvfj2TVZJlz1zGYsVYrSRz2+st+2UbZagR1fbPRX2GilTfDyN05HV//LrfdrddbffMImxY2M8D9iQZFSjBYSFa20S9Vs9/yj08M9ljwiJifHGjX2o/arR63SWe3pbga26EC+j8JaBemhAhPsu91xW4o7+j/xEUadXR2NDbuogMq+MeINKe3PqAAFeTva1ZWZF5p3oGVIQKL4pcQFA9xEwopoN+vSeHDuAOvTFQ/4PukxicJdFTiaZquGeQMF0sLFvLdddpvS3Xaf17fPxjMUlMGcjYQ8gK5XG5wzjR8Up4MZZyX3xiK/hccGOp5pwi8WAN5cVmTKZOSXTkHUGEQT4rcGUYTPduHYMjjrVpzffpnmqfO92VA7a7fuYqXKp3NPikv17s6PTVr6b4+24AP8u3MEhDHU2YjaMuFR3jBUYLxtm443Gn58MC7oYrmQIVN2VYJrxADgStqpE+3nUCyKajmF0q5U+LUI1cCYnOKgmAkrpN71qlB9GeQLLQDJytG2sg64NG/h3CN1SseudSYtmqM3XUURSsztB9dNL7xmHQAcEBYMVjec5N5jHLhIs48rxAqI/WAJ/2RFKWgJIeCUJ8v4oQYEI9lAlWgReVhrjcNxRsbuVDFFwU7cTSeY9bJzxSX5kWJ8TXr/Q/SELEViUVCz10Cw/sOtm4urke538R4yXlR1wfMk3S86xlOfc3HJ6Iz7hi1h2fovWA9T1ceFWQM=";
// 2. 使用 OkHttp 发送邮件
sendEmail(token);
}
// 使用 Graph API 发送邮件
private static void sendEmail(String accessToken) throws IOException {
OkHttpClient client = new OkHttpClient();
// 构建邮件内容 (JSON 格式)
String emailJson = "{\n" +
" \"message\": {\n" +
" \"subject\": \"Test Email\",\n" +
" \"body\": {\n" +
" \"contentType\": \"Text\",\n" +
" \"content\": \"This is a test email.\"\n" +
" },\n" +
" \"toRecipients\": [\n" +
" {\n" +
" \"emailAddress\": {\n" +
" \"address\": \"binzhai321@outlook.com\"\n" +
" }\n" +
" }\n" +
" ]\n" +
" }\n" +
"}";
// 构建请求
Request request = new Request.Builder()
.url("https://graph.microsoft.com/v1.0/users/" + USER_EMAIL + "/sendMail")
.post(RequestBody.create(MediaType.parse("application/json"), emailJson))
.addHeader("authorization", "Bearer " + accessToken)
.addHeader("Content-Type", "application/json")
.build();
// 发送请求
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
System.out.println("Email sent successfully!");
} else {
System.err.println("Failed to send email: " + response.code() + " - " + response.message());
System.err.println(response.body().string()); // 打印错误详情
}
}
}
}
package com.cmeeting;
package com.cmeeting.email;
import javax.activation.DataHandler;
import javax.activation.DataSource;
......
package com.cmeeting.email;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Preconditions;
import microsoft.exchange.webservices.data.core.ExchangeService;
import microsoft.exchange.webservices.data.core.enumeration.misc.ConnectingIdType;
import microsoft.exchange.webservices.data.core.enumeration.misc.TraceFlags;
import microsoft.exchange.webservices.data.core.enumeration.property.BodyType;
import microsoft.exchange.webservices.data.core.enumeration.property.Importance;
import microsoft.exchange.webservices.data.core.request.HttpWebRequest;
import microsoft.exchange.webservices.data.core.service.item.EmailMessage;
import microsoft.exchange.webservices.data.credential.ExchangeCredentials;
import microsoft.exchange.webservices.data.misc.ImpersonatedUserId;
import microsoft.exchange.webservices.data.property.complex.EmailAddress;
import microsoft.exchange.webservices.data.property.complex.MessageBody;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
public class TestExchangeAndOauth2 {
public static void main(String[] args) throws Exception {
String mailAddress = "cmeeting_assistant@cimc.com";
String tenant_id = "8653b3e-03c7-499e-8baf-42ef06a814ef";
String client_id = "c06fe7cf-2a89-4099-9805-ce03031938f8";
String client_secret = "wsu8Q~GxYxPLf2akioQZDRG8NR1EzCAHIAQRVc6u";//注意不是密钥的id
String scope = "https://outlook.office365.com/.default";
String url = "https://login.microsoftonline.com/" + tenant_id + "/oauth2/v2.0/token";
// String scope = "https://partner.outlook.cn/.default";//中国版(21v世纪互联运营的)的微软邮箱账号需要设置这个地址
// String url = "https://login.partner.microsoftonline.cn/" + tenant_id + "/oauth2/v2.0/token";//中国版(21v世纪互联运营的)的微软邮箱账号需要设置这个地址
HttpClient httpClient = new HttpClient();
PostMethod postMethod = new PostMethod(url);
postMethod.addRequestHeader("accept", "*/*");
postMethod.addRequestHeader("connection", "Keep-Alive");
postMethod.addRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=GBK");
//必须设置下面这个Header
postMethod.addRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.81 Safari/537.36");
//添加请求参数
postMethod.addParameter("grant_type", "client_credentials");
postMethod.addParameter("client_id", client_id);
postMethod.addParameter("client_secret", client_secret);
postMethod.addParameter("scope", scope);
String token = "";
try {
int code = httpClient.executeMethod(postMethod);
String resBody = postMethod.getResponseBodyAsString();
if (code == 200) {
Map<String, Object> map = JSON.parseObject(resBody, Map.class);
token = (String) map.get("access_token");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
postMethod.releaseConnection();
}
ExchangeService service = new ExchangeService();
service.setCredentials(new OAuth2Credentials(token));
service.setTraceEnabled(true);
service.traceMessage(TraceFlags.EwsRequest, "office365");
service.setImpersonatedUserId(new ImpersonatedUserId(ConnectingIdType.SmtpAddress, mailAddress));
service.setUrl(new URI("https://outlook.office365.com/ews/exchange.asmx"));
//service.setUrl(new URI("https://partner.outlook.cn/ews/exchange.asmx"));//中国版(21v世纪互联运营的)的微软邮箱账号需要设置这个地址
service.getHttpHeaders().put("X-AnchorMailbox", mailAddress);
EmailMessage msg = new EmailMessage(service);
msg.setFrom(new EmailAddress("mailAddress", mailAddress));
msg.getToRecipients().add(new EmailAddress("收件人邮箱昵称", "binzhai321@outlook.com"));
msg.setSubject("邮件oauth2测试");
MessageBody messageBody = new MessageBody();
messageBody.setBodyType(BodyType.Text);
messageBody.setText("哈哈哈哈");
msg.setBody(messageBody);
msg.setImportance(Importance.Normal);
msg.send();
}
static class OAuth2Credentials extends ExchangeCredentials {
private String accessToken;
public OAuth2Credentials(String accessToken) {
Preconditions.checkNotNull(accessToken);
this.accessToken = accessToken;
}
@Override
public void prepareWebRequest(HttpWebRequest client)
throws URISyntaxException {
super.prepareWebRequest(client);
if (client.getHeaders() != null) client.getHeaders().put("Authorization", "Bearer " + accessToken);
}
}
}
......@@ -2,10 +2,11 @@ package com.cmeeting.mapper.primary;
import com.cmeeting.pojo.CoreModulePermissions;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface AuthMapper {
List<CoreModulePermissions> getAuthByTargrtId(String targetId, String teantId);
List<CoreModulePermissions> getAuthByTargrtId(@Param("targetId") String targetId, @Param("tenantId") String tenantId);
}
package com.cmeeting.mapper.secondary;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SysUserSysMapper {
String getCompanyEmail(String wid, String tenantId);
}
package com.cmeeting.pojo;
import java.util.Objects;
/**
* 会议信息实体类
*/
public class MeetingInfo {
/**
* 会议主题
*/
private String subject;
/**
* 会议ID(字符串类型)
*/
private String meetingId;
/**
* 会议号码
*/
private String meetingCode;
/**
* 用户ID
*/
private String userId;
/**
* 用户昵称
*/
private String nickName;
/**
* 会议开始时间(时间戳)
*/
private Long startTime;
/**
* 会议结束时间(时间戳)
*/
private Long endTime;
/**
* 参会人数
*/
private Integer participantsNum;
/**
* 会议总时长(秒)
*/
private Integer meetingDuration;
/**
* 用户参会时长(秒)
*/
private Integer userMeetingDuration;
// 构造方法
public MeetingInfo() {
}
// Getter 和 Setter 方法
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getMeetingId() {
return meetingId;
}
public void setMeetingId(String meetingId) {
this.meetingId = meetingId;
}
public String getMeetingCode() {
return meetingCode;
}
public void setMeetingCode(String meetingCode) {
this.meetingCode = meetingCode;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public Long getStartTime() {
return startTime;
}
public void setStartTime(Long startTime) {
this.startTime = startTime;
}
public Long getEndTime() {
return endTime;
}
public void setEndTime(Long endTime) {
this.endTime = endTime;
}
public Integer getParticipantsNum() {
return participantsNum;
}
public void setParticipantsNum(Integer participantsNum) {
this.participantsNum = participantsNum;
}
public Integer getMeetingDuration() {
return meetingDuration;
}
public void setMeetingDuration(Integer meetingDuration) {
this.meetingDuration = meetingDuration;
}
public Integer getUserMeetingDuration() {
return userMeetingDuration;
}
public void setUserMeetingDuration(Integer userMeetingDuration) {
this.userMeetingDuration = userMeetingDuration;
}
// toString 方法
@Override
public String toString() {
return "MeetingInfo{" +
"subject='" + subject + '\'' +
", meetingId='" + meetingId + '\'' +
", meetingCode='" + meetingCode + '\'' +
", userId='" + userId + '\'' +
", nickName='" + nickName + '\'' +
", startTime=" + startTime +
", endTime=" + endTime +
", participantsNum=" + participantsNum +
", meetingDuration=" + meetingDuration +
", userMeetingDuration=" + userMeetingDuration +
'}';
}
// equals 和 hashCode 方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MeetingInfo that = (MeetingInfo) o;
return Objects.equals(meetingId, that.meetingId);
}
@Override
public int hashCode() {
return Objects.hash(meetingId);
}
}
\ No newline at end of file
package com.cmeeting.util;
import org.apache.poi.xwpf.usermodel.*;
import org.commonmark.node.*;
import org.commonmark.parser.Parser;
import java.io.*;
public class SimpleMarkdownToWord {
public static void convert(String markdownFile, String outputDocx) throws IOException {
// 读取Markdown文件
String content = readFile(markdownFile);
// 初始化Word文档
XWPFDocument doc = new XWPFDocument();
// 解析Markdown并遍历节点
Parser parser = Parser.builder().build();
Node rootNode = parser.parse(content);
rootNode.accept(new AbstractVisitor() {
XWPFParagraph currentPara;
@Override
public void visit(Heading heading) {
// 创建标题段落
currentPara = doc.createParagraph();
XWPFRun run = currentPara.createRun();
run.setText(extractText(heading)); // 提取纯文本
setHeadingStyle(run, heading.getLevel()); // 设置标题样式
}
@Override
public void visit(Paragraph paragraph) {
// 创建普通段落
currentPara = doc.createParagraph();
XWPFRun run = currentPara.createRun();
run.setText(extractText(paragraph)); // 提取纯文本
}
});
// 输出Word文件
try (FileOutputStream out = new FileOutputStream(outputDocx)) {
doc.write(out);
}
}
// 从节点中提取纯文本(忽略格式)
private static String extractText(Node node) {
StringBuilder text = new StringBuilder();
Node child = node.getFirstChild();
while (child != null) {
if (child instanceof Text) {
text.append(((Text) child).getLiteral());
}
child = child.getNext();
}
return text.toString().trim();
}
// 设置标题样式(仅调整字号和加粗)
private static void setHeadingStyle(XWPFRun run, int level) {
run.setBold(true);
switch (level) {
case 1: run.setFontSize(20); break;
case 2: run.setFontSize(18); break;
default: run.setFontSize(16); break;
}
}
// 读取文件工具方法
private static String readFile(String path) throws IOException {
StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
}
return sb.toString();
}
// 测试
public static void main(String[] args) throws IOException {
convert("input.md", "output.docx");
System.out.println("转换完成!");
}
}
......@@ -17,8 +17,9 @@
core_module_permissions
WHERE
target_id = #{targetId}
<if test="teantId != null and teantId != ''">
AND tenant_id = #{teantId}
<if test="tenantId != null and tenantId != ''">
AND tenant_id = #{tenantId}
</if>
</select>
</mapper>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cmeeting.mapper.secondary.SysUserSysMapper">
<select id="getCompanyEmail" resultType="java.lang.String">
SELECT company_email
FROM sys_user_sync
WHERE user_id = #{wid}
AND tenant_id = #{tenantId}
LIMIT 1
</select>
</mapper>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论