diff --git a/connector_wechatemail_fdddf/README.md b/connector_wechatemail_fdddf/README.md new file mode 100644 index 000000000..996a51546 --- /dev/null +++ b/connector_wechatemail_fdddf/README.md @@ -0,0 +1,117 @@ +# 企业微信邮件连接器 +企业微信邮件连接器 可连接企业微信邮件,可实现发送邮件、查询邮件列表及邮件内容等能力。 + +## 逻辑详情 + +### getAccessToken + +获取access_token + +入参:无 +出参:String access_token + +### getUnreadEmails + +获取指定成员邮箱当前未读邮件数量 + +入参:EmailUnreadRequest request, String token +出参:EmailUnreadResponse + +### readEmail + +获取邮件内容 eml数据 + +入参:EmailReadRequest request, String token +出参:EmailReadResponse + +### getInboxEmails + +获取应用的收件箱邮件列表 + +入参:EmailListRequest request, String token +出参:EmailListResponse + +### parseEml + +解析eml邮件内容 + +入参:String emlContent +出参:ParsedEmail + +#### ParsedEmail +``` +subject: 主题 +from: 发送人 +toRecipients: 收件人 List +sendDate: 发送时间 +attachments: 附件列表 List +``` + +#### EmlAttachment +``` +fileName: 文件名 +mimeType: 文件类型 +content: base64编码的文件内容 +``` + +示例: + +``` +ParsedEmail{subject='Re: 测试带附件邮件', from=xxxx@126.com', toRecipients=[youjianzhushou@xxxx.com], sentDate=2024-09-29, body='Thanks mike, I’m black + +> On Sep 29, 2024, at 23:15, 邮件助手 wrote: +> +> 测试带附件邮件内容<20240928160103-Sqcf8q2k.jpg> + +', attachments=[]} + +``` + +### sendNormalEmail + +发送普通邮件 + +入参:EmailRequest request, String token +出参:WeChatResponse + +### sendMeetingEmail + +发送会议邮件 + +入参:EmailMeetingRequest request, String token +出参:WeChatResponse + +### sendScheduleEmail + +发送日程邮件 + +入参:EmailScheduleRequest request, String token +出参:WeChatResponse + + +### getUserIdByMobile + +根据手机号获取userid + +入参:GetUserIdByMobileRequest request, String token +出参:GetUserIdResponse + +### getUserIdByEmail + +根据邮箱获取userid + +入参:GetUserIdByEmailRequest request, String token +出参:GetUserIdResponse + + +## 使用步骤说明 + +1. 应用集成中导入连接器 “企业微信邮件连接器” +2. 添加连接器,填写参数 cropid、secret , 参考 https://developer.work.weixin.qq.com/document/10013 +3. 逻辑调用示例截图 + + + +## 应用演示链接 + +[使用了本依赖库的制品应用链接] diff --git a/connector_wechatemail_fdddf/jar/nasl-metadata-collector-0.8.0.jar b/connector_wechatemail_fdddf/jar/nasl-metadata-collector-0.8.0.jar new file mode 100644 index 000000000..fffde156d Binary files /dev/null and b/connector_wechatemail_fdddf/jar/nasl-metadata-collector-0.8.0.jar differ diff --git a/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/install.bat b/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/install.bat new file mode 100644 index 000000000..a01a75d94 --- /dev/null +++ b/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/install.bat @@ -0,0 +1 @@ +mvn install:install-file -Dfile="nasl-metadata-maven-plugin-1.3.0.jar" -DpomFile="pom.xml" \ No newline at end of file diff --git a/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/install.sh b/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/install.sh new file mode 100644 index 000000000..a01a75d94 --- /dev/null +++ b/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/install.sh @@ -0,0 +1 @@ +mvn install:install-file -Dfile="nasl-metadata-maven-plugin-1.3.0.jar" -DpomFile="pom.xml" \ No newline at end of file diff --git a/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/nasl-metadata-maven-plugin-1.3.0.jar b/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/nasl-metadata-maven-plugin-1.3.0.jar new file mode 100644 index 000000000..0eaf1ec67 Binary files /dev/null and b/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/nasl-metadata-maven-plugin-1.3.0.jar differ diff --git a/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/pom.xml b/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/pom.xml new file mode 100644 index 000000000..642d8f6b1 --- /dev/null +++ b/connector_wechatemail_fdddf/jar/nasl-metadata-maven-plugin-1.3.0/pom.xml @@ -0,0 +1,74 @@ + + 4.0.0 + + com.netease.lowcode + nasl-metadata-maven-plugin + 1.3.0 + maven-plugin + + Nasl Metadata Maven Plugin + + UTF-8 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven + maven-project + 2.0.10 + + + org.apache.maven.plugin-tools + maven-plugin-annotations + 3.2 + provided + + + org.codehaus.plexus + plexus-compiler-manager + 2.8.4 + + + org.codehaus.plexus + plexus-utils + 3.0.8 + + + org.apache.maven.shared + maven-common-artifact-filters + 3.0.1 + + + + org.apache.maven + maven-aether-provider + 3.3.9 + + + + org.eclipse.aether + aether-api + 1.1.0 + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + 3.2 + + nasl-metadata-maven-plugin + true + + + + + diff --git a/connector_wechatemail_fdddf/pom.xml b/connector_wechatemail_fdddf/pom.xml new file mode 100644 index 000000000..c4d80762c --- /dev/null +++ b/connector_wechatemail_fdddf/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.9.RELEASE + + + + fdddf + connector_wechatemail + 企业微信邮件连接器 + 企业微信邮件连接器 + 1.0.1 + + + 8 + 8 + UTF-8 + 3.3 + + + + + nasl-metadata-collector + com.netease.lowcode + 0.8.0 + true + system + ${project.basedir}/jar/nasl-metadata-collector-0.8.0.jar + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + org.slf4j + slf4j-api + provided + 1.7.30 + + + com.squareup.okhttp3 + okhttp + 3.14.9 + + + + org.apache.httpcomponents + httpclient + 4.5.14 + + + org.apache.httpcomponents + httpcore + 4.4.16 + + + org.apache.httpcomponents + httpmime + 4.5.14 + + + com.alibaba + fastjson + 2.0.53 + + + com.sun.mail + javax.mail + 1.6.2 + + + org.junit.jupiter + junit-jupiter + test + + + + + + com.netease.lowcode + nasl-metadata-maven-plugin + 1.3.0 + + false + + + + + archive + + + + + + + \ No newline at end of file diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/Compose.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/Compose.java new file mode 100644 index 000000000..2d1a25375 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/Compose.java @@ -0,0 +1,44 @@ +package com.fdddf.wechat; + +import com.fdddf.wechat.email.EmailMeetingRequest; +import com.fdddf.wechat.email.EmailRequest; +import com.fdddf.wechat.email.EmailScheduleRequest; + +public class Compose { + public final static String emailUrl = "https://qyapi.weixin.qq.com/cgi-bin/exmail/app/compose_send?access_token="; + + /** + * 发送日程邮件 + * @param request EmailScheduleRequest + * @param token 接口凭证 + * @return + */ + public static WeChatResponse sendScheduleEmail(EmailScheduleRequest request, String token) { + String url = emailUrl + token; + return WeiXinUtil.request(url, token, request, WeChatResponse.class); + } + + /** + * 发送会议邮件 + * @param request EmailMeetingRequest + * @param token 接口凭证 + * @return + */ + public static WeChatResponse sendMeetingEmail(EmailMeetingRequest request, String token) { + String url = emailUrl + token; + return WeiXinUtil.request(url, token, request, WeChatResponse.class); + } + + /** + * 发送普通邮件,支持附件能力 + * @param request EmailRequest + * @param token 接口凭证 + * @return + */ + public static WeChatResponse sendNormalEmail(EmailRequest request, String token) { + String url = emailUrl + token; + request.organizeAttachment(); + return WeiXinUtil.request(url, token, request, WeChatResponse.class); + } + +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/Contact.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/Contact.java new file mode 100644 index 000000000..228c0a084 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/Contact.java @@ -0,0 +1,31 @@ +package com.fdddf.wechat; + +import com.fdddf.wechat.contact.GetUserIdByEmailRequest; +import com.fdddf.wechat.contact.GetUserIdByMobileRequest; +import com.fdddf.wechat.contact.GetUserIdResponse; + +public class Contact { + + /** + * 邮箱获取userid + * @param request GetUserIdByEmailRequest + * @param token String token + * @return + */ + public static GetUserIdResponse getUserIdByEmail(GetUserIdByEmailRequest request, String token) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get_userid_by_email?access_token=" + token; + return WeiXinUtil.request(url, token, request, GetUserIdResponse.class); + } + + /** + * 手机号获取userid + * @param request GetUserIdByMobileRequest + * @param token String token + * @return + */ + public static GetUserIdResponse getUserIdByMobile(GetUserIdByMobileRequest request, String token) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserid?access_token=" + token; + return WeiXinUtil.request(url, token, request, GetUserIdResponse.class); + } + +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/EmlUtil.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/EmlUtil.java new file mode 100644 index 000000000..7e0f3900f --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/EmlUtil.java @@ -0,0 +1,97 @@ +package com.fdddf.wechat; + +import com.fdddf.wechat.eml.EmlAttachment; +import com.fdddf.wechat.eml.ParsedEmail; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.mail.*; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +public class EmlUtil { + private static final Logger LCAP_LOGGER = LoggerFactory.getLogger("LCAP_EXTENSION_LOGGER"); + + /** + * Parse an EML file and return a ParsedEmail object + * @param emlContent The content of the EML file + * @return ParsedEmail + */ + public static ParsedEmail parseEml(String emlContent) + { + try { + InputStream emlStream = new ByteArrayInputStream(emlContent.getBytes()); + + Properties props = new Properties(); + Session session = Session.getDefaultInstance(props, null); + MimeMessage message = new MimeMessage(session, emlStream); + + // Create the ParsedEmail object + ParsedEmail parsedEmail = new ParsedEmail(); + parsedEmail.subject = message.getSubject(); + + // Set the sender (From) + Address[] fromAddresses = message.getFrom(); + if (fromAddresses != null && fromAddresses.length > 0) { + parsedEmail.from = ((InternetAddress) fromAddresses[0]).getAddress(); + } + + // Set the recipients (To) + Address[] toAddresses = message.getRecipients(Message.RecipientType.TO); + List toList = new ArrayList<>(); + if (toAddresses != null) { + for (Address address : toAddresses) { + toList.add(((InternetAddress) address).getAddress()); + } + } + parsedEmail.toRecipients = toList; + parsedEmail.sentDate = message.getSentDate() + .toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + + // Initialize list for attachments + List attachments = new ArrayList<>(); + + // Check if the message has multipart content (for attachments) + if (message.isMimeType("multipart/*")) { + Multipart multipart = (Multipart) message.getContent(); + + // Iterate over all parts + for (int i = 0; i < multipart.getCount(); i++) { + BodyPart bodyPart = multipart.getBodyPart(i); + + // If it's an attachment + if (Part.ATTACHMENT.equalsIgnoreCase(bodyPart.getDisposition())) { + String fileName = bodyPart.getFileName(); + String mimeType = bodyPart.getContentType(); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + byte[] content = outputStream.toByteArray(); + + EmlAttachment attachment = new EmlAttachment(fileName, mimeType, content); + attachments.add(attachment); + } else if (bodyPart.isMimeType("text/plain")) { + // If it's the message body + parsedEmail.body = bodyPart.getContent().toString(); + } + } + } else if (message.isMimeType("text/plain")) { + // If the content is simple text + parsedEmail.body = message.getContent().toString(); + } + parsedEmail.setAttachments(attachments); + return parsedEmail; + + } catch (Exception e) { + LCAP_LOGGER.error("Error parsing EML file: " + e.getMessage()); + return null; + } + } + +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/FileUtil.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/FileUtil.java new file mode 100644 index 000000000..5fab09599 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/FileUtil.java @@ -0,0 +1,82 @@ +package com.fdddf.wechat; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Base64; +import java.util.UUID; + +public class FileUtil { + + private static final Logger LCAP_LOGGER = LoggerFactory.getLogger("LCAP_EXTENSION_LOGGER"); + + public static File downloadFile(String fileUrl, String destinationDirectory) throws IOException { + URL url = new URL(fileUrl); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + + String extension = fileUrl.substring(fileUrl.lastIndexOf(".")); + + // Generate a random file name + String randomFileName = UUID.randomUUID() + extension; + + // Construct the full destination path + String destinationPath = destinationDirectory + File.separator + randomFileName; + + try (InputStream inputStream = connection.getInputStream(); + FileOutputStream outputStream = new FileOutputStream(destinationPath)) { + + byte[] buffer = new byte[4096]; + int bytesRead; + + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + } + + return new File(destinationPath); + } + + public static String fileBase64Content(String fileUrl) { + OkHttpClient client = new OkHttpClient(); + + Request request = new Request.Builder() + .url(fileUrl) + .build(); + + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) { + throw new IOException("Unexpected code " + response); + } + + ResponseBody responseBody = response.body(); + if (responseBody != null) { + byte[] fileBytes = responseBody.bytes(); + return Base64.getEncoder().encodeToString(fileBytes); + } else { + throw new IOException("Response body is null"); + } + } catch (IOException e) { + LCAP_LOGGER.error("Error while sending HTTP request: {}", e.getMessage()); + throw new RuntimeException("Error while sending HTTP request"); + } + } + + public static String getFileName(String url) { + String name = url.substring(url.lastIndexOf("/") + 1); + if (name.contains("?")) { + name = name.substring(0, name.indexOf("?")); + } + return name; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/HttpUtils.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/HttpUtils.java new file mode 100644 index 000000000..4fee934ee --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/HttpUtils.java @@ -0,0 +1,198 @@ +package com.fdddf.wechat; + +import okhttp3.*; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.InputStreamEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.message.BasicHeader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class HttpUtils { + private static final Logger LCAP_LOGGER = LoggerFactory.getLogger("LCAP_EXTENSION_LOGGER"); + + public static String httpGetMethod(String url, Map params) + throws IOException { + OkHttpClient client = new OkHttpClient(); + StringBuilder paramStr = new StringBuilder("?"); + params.forEach((key, value) -> paramStr.append(key).append("=").append(value).append("&")); + paramStr.setLength(paramStr.length() - 1); + + Request request = new Request.Builder().url(url + paramStr.toString()).get().build(); + try (Response response = client.newCall(request).execute()) { + return response.body().string(); + } + } + + public static String httpPostParams(String url, Map params) + throws IOException { + OkHttpClient client = new OkHttpClient(); + StringBuilder paramStr = new StringBuilder("?"); + params.forEach((key, value) -> paramStr.append(key).append("=").append(value).append("&")); + paramStr.setLength(paramStr.length() - 1); + + System.out.println("Testing: " + url + paramStr.toString()); + + Request request = new Request.Builder().url(url + paramStr.toString()) + .post(RequestBody.create(null, new byte[0])) // Replace with an empty body + .build(); + try (Response response = client.newCall(request).execute()) { + return response.body().string(); + } + } + + public static String httpPostStringParamsAndLongParams(String url, Map stringParams, Map longParams) + throws IOException { + OkHttpClient client = new OkHttpClient(); + StringBuilder paramStr = new StringBuilder("?"); + stringParams.forEach((key, value) -> paramStr.append(key).append("=").append(value).append("&")); + longParams.forEach((key, value) -> paramStr.append(key).append("=").append(value).append("&")); + paramStr.setLength(paramStr.length() - 1); + + System.out.println("Testing: " + url + paramStr.toString()); + + Request request = new Request.Builder().url(url + paramStr.toString()) + .post(RequestBody.create(null, new byte[0])) // Replace with an empty body + .build(); + try (Response response = client.newCall(request).execute()) { + return response.body().string(); + } + } + + public static String httpPostMethod(String url, Map params) + throws IOException { + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(60, TimeUnit.SECONDS) + .readTimeout(60, TimeUnit.SECONDS) + .build(); + FormBody.Builder formBody = new FormBody.Builder(); + params.forEach(formBody::add); + + Request request = new Request.Builder().url(url).post(formBody.build()).build(); + try (Response response = client.newCall(request).execute()) { + return response.body().string(); + } + } + + public static String httpPostMethodWithUtf8(String url, Map params) throws IOException { + OkHttpClient client = new OkHttpClient.Builder() + .connectTimeout(60, TimeUnit.SECONDS) + .readTimeout(60, TimeUnit.SECONDS) + .build(); + FormBody.Builder formBody = new FormBody.Builder(); + params.forEach((key, value) -> { + try { + formBody.add(key, URLEncoder.encode(value, StandardCharsets.UTF_8.toString())); + } catch (Exception e) { + LCAP_LOGGER.error("Error encoding value for key: {}", key); + } + }); + + Request request = new Request.Builder().url(url).post(formBody.build()).build(); + try (Response response = client.newCall(request).execute()) { + return response.body().string(); + } + } + + public static String httpPostMethod(String url, Map headers, Map params) + throws IOException { + OkHttpClient client = new OkHttpClient(); + FormBody.Builder formBody = new FormBody.Builder(); + params.forEach(formBody::add); + + Request request = new Request.Builder().url(url) + .headers(Headers.of(headers)) + .post(formBody.build()) + .build(); + try (Response response = client.newCall(request).execute()) { + return response.body().string(); + } + } + + public static Response httpPostResponse(String url, Map headers, String requestBodyContent) throws IOException { + OkHttpClient client = new OkHttpClient(); + MediaType mediaType = MediaType.parse(headers.getOrDefault("Content-Type", "application/json")); + RequestBody requestBody = RequestBody.create(mediaType, requestBodyContent); + + Request request = new Request.Builder().url(url) + .headers(Headers.of(headers)) + .post(requestBody) + .build(); + + return client.newCall(request).execute(); + } + + public static String postMethod(String url, Map headers, InputStream bodyContent) throws IOException { + OkHttpClient client = new OkHttpClient(); + MediaType mediaType = MediaType.parse(headers.getOrDefault("Content-Type", "application/json")); + +// byte[] contentBytes = bodyContent.readAllBytes(); + byte[] contentBytes = toByteArray(bodyContent); + RequestBody requestBody = RequestBody.create(mediaType, contentBytes); + + Request request = new Request.Builder().url(url) + .headers(Headers.of(headers)) + .post(requestBody) + .build(); + + try (Response response = client.newCall(request).execute()) { + return response.body().string(); + } + } + + private static byte[] toByteArray(InputStream inputStream) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[4096]; // Read in chunks of 4KB + + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + + buffer.flush(); + return buffer.toByteArray(); + } + + public static String clientPostMethod(String url, Map headers, InputStream bodyContent) throws IOException { + HttpClient httpClient = HttpClientBuilder.create().build(); + HttpPost method = new HttpPost(url); + + headers.forEach((key, value) -> method.addHeader(new BasicHeader(key, value))); + + if (bodyContent != null) { + method.setEntity(new InputStreamEntity(bodyContent, -1)); + } + + HttpResponse postResponse = httpClient.execute(method); + return getResponsBodyAsString(postResponse.getEntity().getContent()); + } + + public static String clientPostMethod(String url, Map headers) throws IOException { + HttpClient httpClient = HttpClientBuilder.create().build(); + HttpPost method = new HttpPost(url); + headers.forEach((key, value) -> method.addHeader(new BasicHeader(key, value))); + + HttpResponse postResponse = httpClient.execute(method); + return getResponsBodyAsString(postResponse.getEntity().getContent()); + } + + private static String getResponsBodyAsString(InputStream input) throws IOException { + StringBuilder responseBodyString = new StringBuilder(); + try (Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8)) { + char[] buffer = new char[1024]; + int len; + while ((len = reader.read(buffer)) != -1) { + responseBodyString.append(buffer, 0, len); + } + } + return responseBodyString.toString(); + } +} \ No newline at end of file diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/QueryEmail.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/QueryEmail.java new file mode 100644 index 000000000..88bf72257 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/QueryEmail.java @@ -0,0 +1,39 @@ +package com.fdddf.wechat; + +import com.fdddf.wechat.email.*; + +public class QueryEmail { + /** + * 获取应用的收件箱邮件列表 + * @param request EmailListRequest + * @param token 调用接口凭证 + * @return + */ + public static EmailListResponse getInboxEmails(EmailListRequest request, String token) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/exmail/app/get_mail_list?access_token=" + token; + return WeiXinUtil.request(url, token, request, EmailListResponse.class); + } + + /** + * 获取邮件内容 eml数据 + * @param request EmailReadRequest + * @param token 调用接口凭证 + * @return + */ + public static EmailReadResponse readEmail(EmailReadRequest request, String token) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/exmail/app/read_mail?access_token=" + token; + return WeiXinUtil.request(url, token, request, EmailReadResponse.class); + } + + /** + * 获取指定成员邮箱当前未读邮件数量 + * @param request EmailUnreadRequest + * @param token 调用接口凭证 + * @return + */ + public static EmailUnreadResponse getUnreadEmails(EmailUnreadRequest request, String token) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/exmail/mail/get_newcount?access_token=" + token; + return WeiXinUtil.request(url, token, request, EmailUnreadResponse.class); + } + +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/WeChatResponse.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/WeChatResponse.java new file mode 100644 index 000000000..afdb49d8d --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/WeChatResponse.java @@ -0,0 +1,26 @@ +package com.fdddf.wechat; + +import com.fdddf.wechat.implement.IWeixinResponse; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class WeChatResponse implements IWeixinResponse { + + public Integer errcode; + public String errmsg; + + public WeChatResponse() {} + + public WeChatResponse(Integer errcode, String errmsg) { + this.errcode = errcode; + this.errmsg = errmsg; + } + + @Override + public String toString() { + return "WeChatResponse{" + + "errcode=" + errcode + + ", errmsg='" + errmsg + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/WeiXinUtil.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/WeiXinUtil.java new file mode 100644 index 000000000..e61f43789 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/WeiXinUtil.java @@ -0,0 +1,61 @@ +package com.fdddf.wechat; + +import com.alibaba.fastjson.JSONObject; +import com.fdddf.wechat.implement.IWeixinRequest; +import com.fdddf.wechat.implement.IWeixinResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class WeiXinUtil { + private static final Logger LCAP_LOGGER = LoggerFactory.getLogger("LCAP_EXTENSION_LOGGER"); + + /** + * 获取access_token + * @param cropid 企业微信企业id + * @param secret 企业微信应用密钥 + * @return + */ + public static String getAccessToken(String cropid, String secret) { + + Map params = new HashMap<>(); + params.put("corpid", cropid); + params.put("corpsecret", secret); + String token = ""; + try { + String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"; + String responseBody = HttpUtils.httpGetMethod(url, params); + JSONObject tokenBody = JSONObject.parseObject(responseBody); + token = tokenBody.getString("access_token"); + } catch (IOException e) { + LCAP_LOGGER.error("Error while sending HTTP request: {}", e.getMessage()); + throw new RuntimeException("Error while sending HTTP request"); + } + return token; + } + + public static T request(String url, String token, IWeixinRequest request, Class responseClass) { + JSONObject jsonReq = (JSONObject) JSONObject.toJSON(request); + String jsonBody = jsonReq.toJSONString(); + + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/json"); + + try { + okhttp3.Response response = HttpUtils.httpPostResponse(url, headers, jsonBody); + assert response.body() != null; + String responseString = response.body().string(); + + // Parse the response as the class passed in the parameter + return JSONObject.parseObject(responseString, responseClass); + + } catch (IOException e) { + LCAP_LOGGER.error("Error while sending HTTP request: {}", e.getMessage()); + } + return null; + } + +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/WeixinEmailConnector.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/WeixinEmailConnector.java new file mode 100644 index 000000000..d207a8941 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/WeixinEmailConnector.java @@ -0,0 +1,148 @@ +package com.fdddf.wechat; + +import com.fdddf.wechat.contact.GetUserIdByEmailRequest; +import com.fdddf.wechat.contact.GetUserIdByMobileRequest; +import com.fdddf.wechat.contact.GetUserIdResponse; +import com.fdddf.wechat.email.*; +import com.fdddf.wechat.eml.ParsedEmail; +import com.netease.lowcode.core.annotation.NaslConnector; + +@NaslConnector(connectorKind = "weixinEmailConnector") +public class WeixinEmailConnector { + /** + * 企业微信企业id + */ + private String cropid; + /** + * 企业微信应用密钥 + */ + private String secret; + + @NaslConnector.Creator + public WeixinEmailConnector initBean(String cropid, String secret) + { + WeixinEmailConnector connector = new WeixinEmailConnector(); + connector.cropid = cropid; + connector.secret = secret; + return connector; + } + + @NaslConnector.Tester + public Boolean test(String cropid, String secret) { + if (null != cropid && !cropid.isEmpty() && null != secret && !secret.isEmpty()) { + String token = WeiXinUtil.getAccessToken(cropid, secret); + return null != token && !token.isEmpty(); + } + return false; + } + + /////////logics//////// + + /** + * 邮箱获取userid + * @param request GetUserIdByEmailRequest + * @param token String token + * @return + */ + @NaslConnector.Logic + public static GetUserIdResponse getUserIdByEmail(GetUserIdByEmailRequest request, String token) { + return Contact.getUserIdByEmail(request, token); + } + + /** + * 手机号获取userid + * @param request GetUserIdByMobileRequest + * @param token String token + * @return + */ + @NaslConnector.Logic + public static GetUserIdResponse getUserIdByMobile(GetUserIdByMobileRequest request, String token) { + return Contact.getUserIdByMobile(request, token); + } + + /** + * 发送日程邮件 + * @param request EmailScheduleRequest + * @param token 接口凭证 + * @return + */ + @NaslConnector.Logic + public static WeChatResponse sendScheduleEmail(EmailScheduleRequest request, String token) { + return Compose.sendScheduleEmail(request, token); + } + + /** + * 发送会议邮件 + * @param request EmailMeetingRequest + * @param token 接口凭证 + * @return + */ + @NaslConnector.Logic + public static WeChatResponse sendMeetingEmail(EmailMeetingRequest request, String token) { + return Compose.sendMeetingEmail(request, token); + } + + /** + * 发送普通邮件,支持附件能力 + * @param request EmailRequest + * @param token 接口凭证 + * @return + */ + @NaslConnector.Logic + public static WeChatResponse sendNormalEmail(EmailRequest request, String token) { + return Compose.sendNormalEmail(request, token); + } + + /** + * Parse an EML file and return a ParsedEmail object + * @param emlContent The content of the EML file + * @return ParsedEmail + */ + @NaslConnector.Logic + public static ParsedEmail parseEml(String emlContent) { + return EmlUtil.parseEml(emlContent); + } + + /** + * 获取应用的收件箱邮件列表 + * @param request EmailListRequest + * @param token 调用接口凭证 + * @return + */ + @NaslConnector.Logic + public static EmailListResponse getInboxEmails(EmailListRequest request, String token) { + return QueryEmail.getInboxEmails(request, token); + } + + /** + * 获取邮件内容 eml数据 + * @param request EmailReadRequest + * @param token 调用接口凭证 + * @return + */ + @NaslConnector.Logic + public static EmailReadResponse readEmail(EmailReadRequest request, String token) { + return QueryEmail.readEmail(request, token); + } + + /** + * 获取指定成员邮箱当前未读邮件数量 + * @param request EmailUnreadRequest + * @param token 调用接口凭证 + * @return + */ + @NaslConnector.Logic + public static EmailUnreadResponse getUnreadEmails(EmailUnreadRequest request, String token) { + return QueryEmail.getUnreadEmails(request, token); + } + + /** + * 获取access_token + * @return + */ + @NaslConnector.Logic + public String getAccessToken() { + return WeiXinUtil.getAccessToken(cropid, secret); + } + +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/contact/GetUserIdByEmailRequest.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/contact/GetUserIdByEmailRequest.java new file mode 100644 index 000000000..708d85b68 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/contact/GetUserIdByEmailRequest.java @@ -0,0 +1,20 @@ +package com.fdddf.wechat.contact; + +import com.fdddf.wechat.implement.IWeixinRequest; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class GetUserIdByEmailRequest implements IWeixinRequest { + public String email; + /** + * 1-企业邮箱(默认);2-个人邮箱 + */ + public Integer email_type; + + public GetUserIdByEmailRequest() {} + + public GetUserIdByEmailRequest(String email, Integer email_type) { + this.email = email; + this.email_type = email_type; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/contact/GetUserIdByMobileRequest.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/contact/GetUserIdByMobileRequest.java new file mode 100644 index 000000000..c9d9cd04f --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/contact/GetUserIdByMobileRequest.java @@ -0,0 +1,15 @@ +package com.fdddf.wechat.contact; + +import com.fdddf.wechat.implement.IWeixinRequest; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class GetUserIdByMobileRequest implements IWeixinRequest { + public String mobile; + + public GetUserIdByMobileRequest(String mobile) { + this.mobile = mobile; + } + + public GetUserIdByMobileRequest() {} +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/contact/GetUserIdResponse.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/contact/GetUserIdResponse.java new file mode 100644 index 000000000..e42ffeae2 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/contact/GetUserIdResponse.java @@ -0,0 +1,13 @@ +package com.fdddf.wechat.contact; + +import com.fdddf.wechat.implement.IWeixinResponse; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class GetUserIdResponse implements IWeixinResponse { + public Integer errcode; + public String errmsg; + public String userid; + + public GetUserIdResponse() {} +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailAttachment.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailAttachment.java new file mode 100644 index 000000000..3d82b5f69 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailAttachment.java @@ -0,0 +1,22 @@ +package com.fdddf.wechat.email; + +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailAttachment { + /** + * 文件名 + */ + public String file_name; + /** + * 文件内容(base64编码) + */ + public String content; + + public EmailAttachment() {} + + public EmailAttachment(String file_name, String content) { + this.file_name = file_name; + this.content = content; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailItem.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailItem.java new file mode 100644 index 000000000..c7534c865 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailItem.java @@ -0,0 +1,22 @@ +package com.fdddf.wechat.email; + +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailItem { + /** + * 邮件id + */ + public String mail_id; + + public EmailItem() {} + + public EmailItem(String mail_id) { + this.mail_id = mail_id; + } + + public String toString() { + return "mail_id: " + mail_id; + } + +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailListRequest.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailListRequest.java new file mode 100644 index 000000000..a07cd65c8 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailListRequest.java @@ -0,0 +1,33 @@ +package com.fdddf.wechat.email; + +import com.fdddf.wechat.implement.IWeixinRequest; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailListRequest implements IWeixinRequest { + /** + * 开始时间,unix时间戳 + */ + public Long begin_time; + /** + * 结束时间,unix时间戳 + */ + public Long end_time; + /** + * 上一次调用时返回的next_cursor,第一次拉取可以不填 + */ + public String cursor; + /** + * 期望请求的数据量,默认值为100,最大值为1000 + */ + public Integer limit = 100; + + public EmailListRequest() {} + + public EmailListRequest(Long begin_time, Long end_time, String cursor, Integer limit) { + this.begin_time = begin_time; + this.end_time = end_time; + this.cursor = cursor; + this.limit = limit; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailListResponse.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailListResponse.java new file mode 100644 index 000000000..bb5ebdbf3 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailListResponse.java @@ -0,0 +1,44 @@ +package com.fdddf.wechat.email; + +import com.fdddf.wechat.implement.IWeixinResponse; +import com.netease.lowcode.core.annotation.NaslStructure; + +import java.util.List; + +@NaslStructure +public class EmailListResponse implements IWeixinResponse { + public Integer errcode; + public String errmsg; + /** + * 应用邮箱账号中邮件未读数 + */ + public String next_cursor; + /** + * 是否还有更多数据。0-没有 1-有 + */ + public Integer has_more; + public List mail_list; + + public EmailListResponse() {} + + public EmailListResponse(Integer errcode, String errmsg, String next_cursor, Integer has_more, + List mail_list) { + this.errcode = errcode; + this.errmsg = errmsg; + this.next_cursor = next_cursor; + this.has_more = has_more; + this.mail_list = mail_list; + } + + @Override + public String toString() { + return "MailListResponse{" + + "errcode=" + errcode + + ", errmsg='" + errmsg + '\'' + + ", next_cursor='" + next_cursor + '\'' + + ", has_more=" + has_more + + ", mail_list=" + mail_list + + '}'; + } + +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeeting.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeeting.java new file mode 100644 index 000000000..e901affe4 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeeting.java @@ -0,0 +1,28 @@ +package com.fdddf.wechat.email; + +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailMeeting { + /** + * 邮件会议参数 + */ + public EmailMeetingOption option; + /** + * 会议主持人列表 + */ + public EmailMeetingUsers hosts; + /** + * 会议管理员字段, , 仅可指定1人,只支持传userid + */ + public EmailMeetingUsers meeting_admins; + + public EmailMeeting() {} + + public EmailMeeting(EmailMeetingOption option, EmailMeetingUsers hosts, EmailMeetingUsers meeting_admins) + { + this.option = option; + this.hosts = hosts; + this.meeting_admins = meeting_admins; + } +} \ No newline at end of file diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeetingOption.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeetingOption.java new file mode 100644 index 000000000..f9f33d3c7 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeetingOption.java @@ -0,0 +1,59 @@ +package com.fdddf.wechat.email; + +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailMeetingOption { + /** + * 入会密码,仅可输入4-6位纯数字 + */ + public String password; + /** + * 是否自动录制 0:未开启自动录制,1:开启自动本地录制,2:开启自动云录制;默认不开启 + */ + public Integer auto_record; + /** + * 是否开启等候室 + */ + public Boolean enable_waiting_room; + /** + * 否允许成员在主持人进会前加入 + */ + public Boolean allow_enter_before_host; + /** + * 是否限制成员入会 0:所有人可入会 2:仅企业内部用户可入会;默认所有人可入会 + */ + public Integer enter_restraint; + /** + * 是否开启屏幕水印 + */ + public Boolean enable_screen_watermark; + /** + * 成员入会时是否静音 1:开启;0:关闭;2:超过6人后自动开启静音。默认超过6人自动开启静音 + */ + public Integer enable_enter_mute; + /** + * 会议开始时是否提醒 1:不提醒 2:仅提醒主持人 3:提醒所有成员入会; 默认仅提醒主持人 + */ + public Integer remind_scope; + /** + * 水印类型 0:单排水印 1:多排水印;默认单排水印 + */ + public Integer water_mark_type; + + public EmailMeetingOption() {} + + public EmailMeetingOption(String password, Integer auto_record, Boolean enable_waiting_room, Boolean allow_enter_before_host, + Integer enter_restraint, Boolean enable_screen_watermark, Integer enable_enter_mute, + Integer remind_scope, Integer water_mark_type) { + this.password = password; + this.auto_record = auto_record; + this.enable_waiting_room = enable_waiting_room; + this.allow_enter_before_host = allow_enter_before_host; + this.enter_restraint = enter_restraint; + this.enable_screen_watermark = enable_screen_watermark; + this.enable_enter_mute = enable_enter_mute; + this.remind_scope = remind_scope; + this.water_mark_type = water_mark_type; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeetingRequest.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeetingRequest.java new file mode 100644 index 000000000..a6c7a19a2 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeetingRequest.java @@ -0,0 +1,45 @@ +package com.fdddf.wechat.email; + +import com.fdddf.wechat.implement.IWeixinRequest; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailMeetingRequest implements IWeixinRequest { + + /** + * 邮件接收人 + */ + public EmailRecipient to; + /** + * 邮件主题 + */ + public String subject; + /** + * 邮件内容 + */ + public String content; + /** + * 邮件日程 + */ + public EmailSchedule schedule; + /** + * 邮件会议 + */ + public EmailMeeting meeting; + /** + * 是否开启id转换 + */ + public Integer enable_id_trans; + + public EmailMeetingRequest() {} + + public EmailMeetingRequest(EmailRecipient to, String subject, String content, EmailSchedule schedule, + EmailMeeting meeting, Integer enable_id_trans) { + this.to = to; + this.subject = subject; + this.content = content; + this.schedule = schedule; + this.meeting = meeting; + this.enable_id_trans = enable_id_trans; + } +} \ No newline at end of file diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeetingUsers.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeetingUsers.java new file mode 100644 index 000000000..cbda715fb --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailMeetingUsers.java @@ -0,0 +1,19 @@ +package com.fdddf.wechat.email; + +import com.netease.lowcode.core.annotation.NaslStructure; + +import java.util.List; + +@NaslStructure +public class EmailMeetingUsers { + /** + * 用户id列表 + */ + public List userids; + + public EmailMeetingUsers() {} + + public EmailMeetingUsers(List userids) { + this.userids = userids; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailReadRequest.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailReadRequest.java new file mode 100644 index 000000000..20402cfe0 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailReadRequest.java @@ -0,0 +1,20 @@ +package com.fdddf.wechat.email; + +import com.fdddf.wechat.implement.IWeixinRequest; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailReadRequest implements IWeixinRequest{ + + /** + * 邮件id + */ + public String mail_id; + + public EmailReadRequest() {} + + public EmailReadRequest(String mail_id) + { + this.mail_id = mail_id; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailReadResponse.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailReadResponse.java new file mode 100644 index 000000000..47844c375 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailReadResponse.java @@ -0,0 +1,14 @@ +package com.fdddf.wechat.email; + +import com.fdddf.wechat.implement.IWeixinResponse; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailReadResponse implements IWeixinResponse{ + public Integer errcode; + public String errmsg; + /** + * 邮件eml内容 + */ + public String mail_data; +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailRecipient.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailRecipient.java new file mode 100644 index 000000000..812e0bcb5 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailRecipient.java @@ -0,0 +1,18 @@ +package com.fdddf.wechat.email; + +import com.netease.lowcode.core.annotation.NaslStructure; + +import java.util.List; + +@NaslStructure +public class EmailRecipient { + public List emails; + public List userids; + + public EmailRecipient() {} + + public EmailRecipient(List emails, List userids) { + this.emails = emails; + this.userids = userids; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailRequest.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailRequest.java new file mode 100644 index 000000000..13955d9b2 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailRequest.java @@ -0,0 +1,73 @@ +package com.fdddf.wechat.email; + +import com.fdddf.wechat.FileUtil; +import com.fdddf.wechat.implement.IWeixinRequest; +import com.netease.lowcode.core.annotation.NaslStructure; + +import java.util.List; + +@NaslStructure +public class EmailRequest implements IWeixinRequest { + /** + * 收件人 + */ + public EmailRecipient to; + /** + * 抄送人 + */ + public EmailRecipient cc; + /** + * 密送人 + */ + public EmailRecipient bcc; + /** + * 主题 + */ + public String subject; + /** + * 正文 + */ + public String content; + /** + * 附件列表, 可使用 fileUrls + */ + public List attachment_list; + /** + * 是否开启id转译 + */ + public Integer enable_id_trans; + + /** + * 附件地址列表 + */ + public List fileUrls; + + public EmailRequest() {} + + public EmailRequest(EmailRecipient to, EmailRecipient cc, EmailRecipient bcc, String subject, String content, + List attachment_list, int enable_id_trans, List fileUrls) { + this.to = to; + this.cc = cc; + this.bcc = bcc; + this.subject = subject; + this.content = content; + this.attachment_list = attachment_list; + this.enable_id_trans = enable_id_trans; + this.fileUrls = fileUrls; + } + + public void organizeAttachment() { + if (attachment_list == null) { + attachment_list = new java.util.ArrayList<>(); + } + if (fileUrls == null) { + return; + } + for (String fileUrl : fileUrls) { + String fileName = FileUtil.getFileName(fileUrl); + String content = FileUtil.fileBase64Content(fileUrl); + EmailAttachment attachment = new EmailAttachment(fileName, content); + attachment_list.add(attachment); + } + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailSchedule.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailSchedule.java new file mode 100644 index 000000000..22ad66f88 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailSchedule.java @@ -0,0 +1,46 @@ +package com.fdddf.wechat.email; + +import com.alibaba.fastjson.annotation.JSONField; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailSchedule { + /** + * 会议ID (修改/取消会议必须带上schedule_id) + */ + public String schedule_id; + /** + * 会议方法:request-请求(不传schedule_id时是创建会议,传了是修改会议),cancel-取消会议(必须带上schedule_id) 默认为request + */ + @JSONField(name = "method") + public String req_method = "request"; + /** + * 地点 + */ + public String location; + /** + * 会议开始时间,Unix时间戳 + */ + public Integer start_time; + /** + * 会议结束时间,Unix时间戳 + */ + public Integer end_time; + + /** + * 重复和提醒相关字段 + */ + public EmailScheduleReminder reminders; + + public EmailSchedule() {} + + public EmailSchedule(String schedule_id, String req_method, String location, Integer start_time, Integer end_time, + EmailScheduleReminder reminders) { + this.schedule_id = schedule_id; + this.req_method = req_method; + this.location = location; + this.start_time = start_time; + this.end_time = end_time; + this.reminders = reminders; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailScheduleReminder.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailScheduleReminder.java new file mode 100644 index 000000000..344db6d26 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailScheduleReminder.java @@ -0,0 +1,70 @@ +package com.fdddf.wechat.email; + +import com.netease.lowcode.core.annotation.NaslStructure; + +import java.util.List; + +@NaslStructure +public class EmailScheduleReminder { + /** + * 是否有提醒 0-不提醒 1-提醒 + */ + public Integer is_remind; + /** + * 日程开始(start_time)前多少分钟提醒,当is_remind=1时有效。例如:15表示日程开始前15分钟提醒,-15表示日程开始后15分钟提醒 + */ + public Integer remind_before_event_mins; + /** + * 是否重复 0-否 1-是 + */ + public Integer is_repeat; + /** + * 是否自定义重复 0-否 1-是。当is_repeat为1时有效。 + */ + public Integer is_custom_repeat; + public Integer timezone; + /** + * 重复间隔 + */ + public Integer repeat_interval; + /** + * 重复类型,当is_repeat=1时有效。目前支持如下类型:0 - 每日, 1 - 每周, 2 - 每月, 5 - 每年 + */ + public Integer repeat_type; + /** + * 每周周几重复, 取值范围:1 ~ 7,分别表示周一至周日 + */ + public List repeat_day_of_week; + /** + * 每月哪几天重复, 取值范围:1 ~ 31,分别表示1~31号 + */ + public List repeat_day_of_month; + /** + * 每年哪几个月重复, 取值范围:1 ~ 12 + */ + public List repeat_day_of_year; + /** + * 重复结束时刻,Unix时间戳,当is_repeat=1时有效。不填或填0表示一直重复 + */ + public Long repeat_until; + + public EmailScheduleReminder() {} + + public EmailScheduleReminder(Integer is_remind, Integer remind_before_event_mins, Integer is_repeat, + Integer is_custom_repeat, Integer timezone, Integer repeat_interval, Integer repeat_type, + List repeat_day_of_week, List repeat_day_of_month, List repeat_day_of_year, + Long repeat_until) { + this.is_remind = is_remind; + this.remind_before_event_mins = remind_before_event_mins; + this.is_repeat = is_repeat; + this.is_custom_repeat = is_custom_repeat; + this.timezone = timezone; + this.repeat_interval = repeat_interval; + this.repeat_type = repeat_type; + this.repeat_day_of_week = repeat_day_of_week; + this.repeat_day_of_month = repeat_day_of_month; + this.repeat_day_of_year = repeat_day_of_year; + this.repeat_until = repeat_until; + } + +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailScheduleRequest.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailScheduleRequest.java new file mode 100644 index 000000000..34ce57c01 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailScheduleRequest.java @@ -0,0 +1,28 @@ +package com.fdddf.wechat.email; + +import com.fdddf.wechat.implement.IWeixinRequest; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailScheduleRequest implements IWeixinRequest { + + public EmailRecipient to; + public EmailRecipient cc; + public EmailRecipient bcc; + public String subject; + public String content; + public EmailSchedule schedule; + public Integer enable_id_trans; + + public EmailScheduleRequest() {} + + public EmailScheduleRequest(EmailRecipient to, EmailRecipient cc, EmailRecipient bcc, String subject, String content, EmailSchedule schedule, Integer enable_id_trans) { + this.to = to; + this.cc = cc; + this.bcc = bcc; + this.subject = subject; + this.content = content; + this.schedule = schedule; + this.enable_id_trans = enable_id_trans; + } +} \ No newline at end of file diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailUnreadRequest.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailUnreadRequest.java new file mode 100644 index 000000000..a1a2b4875 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailUnreadRequest.java @@ -0,0 +1,15 @@ +package com.fdddf.wechat.email; + +import com.fdddf.wechat.implement.IWeixinRequest; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailUnreadRequest implements IWeixinRequest { + public String userid; + + public EmailUnreadRequest() {} + + public EmailUnreadRequest(String userid) { + this.userid = userid; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailUnreadResponse.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailUnreadResponse.java new file mode 100644 index 000000000..40ed00c70 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/email/EmailUnreadResponse.java @@ -0,0 +1,22 @@ +package com.fdddf.wechat.email; + +import com.fdddf.wechat.implement.IWeixinResponse; +import com.netease.lowcode.core.annotation.NaslStructure; + +@NaslStructure +public class EmailUnreadResponse implements IWeixinResponse { + public Integer errcode; + public String errmsg; + /** + * 成员邮箱中邮件未读数 + */ + public Long count; + + public String toString() { + return "EmailUnreadResponse{" + + "errcode=" + errcode + + ", errmsg='" + errmsg + '\'' + + ", count=" + count + + '}'; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/eml/EmlAttachment.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/eml/EmlAttachment.java new file mode 100644 index 000000000..9fda3263c --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/eml/EmlAttachment.java @@ -0,0 +1,38 @@ +package com.fdddf.wechat.eml; + + +import com.netease.lowcode.core.annotation.NaslStructure; + +import java.util.Base64; + +@NaslStructure +public class EmlAttachment { + /** + * 文件名 + */ + public String fileName; + /** + * 文件类型 + */ + public String mimeType; + /** + * base64编码的文件内容 + */ + public String content; + + public EmlAttachment() {} + + public EmlAttachment(String fileName, String mimeType, byte[] content) { + this.fileName = fileName; + this.mimeType = mimeType; + this.content = Base64.getEncoder().encodeToString(content); + } + + @Override + public String toString() { + return "EmlAttachment{" + + "fileName='" + fileName + '\'' + + ", mimeType='" + mimeType + '\'' + + '}'; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/eml/ParsedEmail.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/eml/ParsedEmail.java new file mode 100644 index 000000000..64fdab830 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/eml/ParsedEmail.java @@ -0,0 +1,57 @@ +package com.fdddf.wechat.eml; + +import com.netease.lowcode.core.annotation.NaslStructure; + +import java.time.LocalDate; +import java.util.List; + +@NaslStructure +public class ParsedEmail { + /** + * 邮件主题 + */ + public String subject; + /** + * 发件人 + */ + public String from; + /** + * 收件人 + */ + public List toRecipients; + /** + * 发送时间 + */ + public LocalDate sentDate; + /** + * 邮件内容 + */ + public String body; + /** + * 附件列表 + */ + public List attachments; + + public List getAttachments() { + return attachments; + } + + public void setAttachments(List attachments) { + this.attachments = attachments; + } + + + public ParsedEmail() {} + + @Override + public String toString() { + return "ParsedEmail{" + + "subject='" + subject + '\'' + + ", from='" + from + '\'' + + ", toRecipients=" + toRecipients + + ", sentDate=" + sentDate + + ", body='" + body + '\'' + + ", attachments=" + attachments + + '}'; + } +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/implement/IWeixinRequest.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/implement/IWeixinRequest.java new file mode 100644 index 000000000..bb150a964 --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/implement/IWeixinRequest.java @@ -0,0 +1,4 @@ +package com.fdddf.wechat.implement; + +public interface IWeixinRequest { +} diff --git a/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/implement/IWeixinResponse.java b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/implement/IWeixinResponse.java new file mode 100644 index 000000000..32b606a9a --- /dev/null +++ b/connector_wechatemail_fdddf/src/main/java/com/fdddf/wechat/implement/IWeixinResponse.java @@ -0,0 +1,4 @@ +package com.fdddf.wechat.implement; + +public interface IWeixinResponse { +} diff --git a/connector_wechatemail_fdddf/src/test/java/com/fdddf/wechat/TestEmail.java b/connector_wechatemail_fdddf/src/test/java/com/fdddf/wechat/TestEmail.java new file mode 100644 index 000000000..cf956787e --- /dev/null +++ b/connector_wechatemail_fdddf/src/test/java/com/fdddf/wechat/TestEmail.java @@ -0,0 +1,183 @@ +package com.fdddf.wechat; + +import com.fdddf.wechat.contact.GetUserIdByEmailRequest; +import com.fdddf.wechat.contact.GetUserIdByMobileRequest; +import com.fdddf.wechat.contact.GetUserIdResponse; +import com.fdddf.wechat.email.*; +import com.fdddf.wechat.eml.ParsedEmail; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class TestEmail { + + String token; + + List emailTo = new ArrayList<>(); + + @Test + void contextLoads() { + } + + @BeforeEach + void init() { + String cropid = System.getenv("cropid"); + String secret = System.getenv("secret"); + token = WeiXinUtil.getAccessToken(cropid, secret); + emailTo.add("viporg@126.com"); + } + + @Test + public void sendNormalEmail() { + EmailRequest request = new EmailRequest( + new EmailRecipient(emailTo, null), + null, + null, + "测试邮件", + "测试邮件内容", + null, + 1, + null + ); + System.out.println("token="+token); + WeChatResponse resp = Compose.sendNormalEmail(request, token); + System.out.println(resp); + assertEquals(resp.errcode, 0); + } + + @Test + public void sendAttachmentEmail() { + List fileUrls = new ArrayList<>(); + fileUrls.add("https://www.zixi.org/assets/uploads/202409/20240928160103-Sqcf8q2k.jpg"); + EmailRequest request = new EmailRequest( + new EmailRecipient(emailTo, null), + null, + null, + "测试带附件邮件", + "测试带附件邮件内容", + null, + 1, + fileUrls + ); + WeChatResponse resp = Compose.sendNormalEmail(request, token); + System.out.println(resp); + assertEquals(resp.errcode, 0); + } + + @Test + public void sendScheduleEmail() { + EmailScheduleReminder reminder = new EmailScheduleReminder(1, 15, 0, 1, 8, 1, 1, null, null, null, null); + + EmailSchedule schedule = new EmailSchedule(null, "request", null, 1727784000, 1727787600, reminder); + + EmailScheduleRequest request = new EmailScheduleRequest( + new EmailRecipient(emailTo, null), + null, + null, + "测试日程邮件", + "测试日程邮件内容", + schedule, + 1 + ); + + WeChatResponse resp = Compose.sendScheduleEmail(request, token); + System.out.println(resp); + assertEquals(resp.errcode, 0); + } + + @Disabled("Meeting Error cannot be fixed yet") + @Test + public void sendMeetingEmail() { + EmailScheduleReminder reminder = new EmailScheduleReminder(1, 15, 0, 1, 8, 1, 1, null, null, null, null); + EmailSchedule schedule = new EmailSchedule(null, "request", null, 1727784000, 1727787600, reminder); + + EmailMeetingOption option = new EmailMeetingOption( + "123123", + 0, + false, + false, + 0, + false, + 1, + 1, + 0); + List userids = new ArrayList<>(); + userids.add("admin@fdddf.com"); + EmailMeetingUsers hosts = new EmailMeetingUsers(userids); + EmailMeetingUsers admins = new EmailMeetingUsers(userids); + EmailMeeting meeting = new EmailMeeting(option, null, admins); + + List to = new ArrayList<>(); + to.add("admin@fdddf.com"); + to.add("service@fdddf.com"); + EmailMeetingRequest request = new EmailMeetingRequest( + new EmailRecipient(to, null), + "测试会议邮件", + "测试会议邮件内容", + schedule, + meeting, + 1 + ); + System.out.println("token="+token); + WeChatResponse resp = Compose.sendMeetingEmail(request, token); + System.out.println(resp); + assertEquals(resp.errcode, 0); + } + + + @Test + public void getInboxEmails() { + EmailListRequest request = new EmailListRequest(1725206311L, 1727624359L, null, 100); + System.out.println("token="+token); + EmailListResponse resp = QueryEmail.getInboxEmails(request, token); + System.out.println(resp); + assertEquals(resp.errcode, 0); + } + + @Test + public void getEmailContent() { + String mail_id = "mlgY3eK56xuPtEgh7UsaWGSF_RzimSh_IPfvXt9B1JDyVIZDIQzZPEKOtGgGPkjV59"; + EmailReadRequest request = new EmailReadRequest(mail_id); + EmailReadResponse resp = QueryEmail.readEmail(request, token); + System.out.println(resp.mail_data); + assertEquals(resp.errcode, 0); + + ParsedEmail email = EmlUtil.parseEml(resp.mail_data); + System.out.println(email); + } + + ///////////////////////contacts + + @Test + public void getUserIdByMobile() { + String mobile = "15591851122"; + GetUserIdByMobileRequest request = new GetUserIdByMobileRequest(mobile); + GetUserIdResponse resp = Contact.getUserIdByMobile(request, token); + System.out.println(resp.userid); + assertNotNull(resp.userid); + } + + @Test + public void getUserIdByEmail() { + String email = "admin@fdddf.com"; + GetUserIdByEmailRequest request = new GetUserIdByEmailRequest(email, 1); + GetUserIdResponse resp = Contact.getUserIdByEmail(request, token); + System.out.println(resp.userid); + assertNotNull(resp.userid); + } + + @Test + public void getUnreadEmails() { + EmailUnreadRequest request = new EmailUnreadRequest("admin@fdddf.com"); + EmailUnreadResponse resp = QueryEmail.getUnreadEmails(request, token); + assertEquals(resp.errcode, 0); + System.out.println(resp); + } + +} diff --git "a/connector_wechatemail_fdddf/\344\276\235\350\265\226\345\272\223\344\275\277\347\224\250\346\226\207\346\241\243\350\257\264\346\230\216.docx" "b/connector_wechatemail_fdddf/\344\276\235\350\265\226\345\272\223\344\275\277\347\224\250\346\226\207\346\241\243\350\257\264\346\230\216.docx" new file mode 100644 index 000000000..524649ccc Binary files /dev/null and "b/connector_wechatemail_fdddf/\344\276\235\350\265\226\345\272\223\344\275\277\347\224\250\346\226\207\346\241\243\350\257\264\346\230\216.docx" differ