diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Events/Exmail/AppEmailChangeEvent.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Events/Exmail/AppEmailChangeEvent.cs
new file mode 100644
index 00000000..5f315c6d
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Events/Exmail/AppEmailChangeEvent.cs
@@ -0,0 +1,21 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Events
+{
+ ///
+ /// 表示 EVENT.app_email_change 事件的数据。
+ /// REF: https://developer.work.weixin.qq.com/document/path/97506
+ ///
+ public class AppEmailChangeEvent : WechatWorkEvent, WechatWorkEvent.Serialization.IXmlSerializable
+ {
+ ///
+ /// 获取或设置操作类型。
+ ///
+ [System.Xml.Serialization.XmlElement("ChangeType")]
+ public string ActionType { get; set; } = default!;
+
+ ///
+ /// 获取或设置新邮件数。
+ ///
+ [System.Xml.Serialization.XmlElement("Amount")]
+ public int MailCount { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinExmailExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinExmailExtensions.cs
index bb18ce1c..97dd56dd 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinExmailExtensions.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinExmailExtensions.cs
@@ -31,6 +31,46 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
}
+
+ ///
+ /// 异步调用 [POST] /cgi-bin/exmail/app/get_mail_list 接口。
+ /// REF: https://developer.work.weixin.qq.com/document/path/97505
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteCgibinExmailAppGetMailListAsync(this WechatWorkClient client, Models.CgibinExmailAppGetMailListRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Post, "cgi-bin", "exmail", "app", "get_mail_list")
+ .SetQueryParam("access_token", request.AccessToken);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 异步调用 [POST] /cgi-bin/exmail/app/read_mail 接口。
+ /// REF: https://developer.work.weixin.qq.com/document/path/97982
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteCgibinExmailAppReadMailAsync(this WechatWorkClient client, Models.CgibinExmailAppReadMailRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Post, "cgi-bin", "exmail", "app", "read_mail")
+ .SetQueryParam("access_token", request.AccessToken);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, data: request, cancellationToken: cancellationToken);
+ }
#endregion
#region Group
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppGetMailListRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppGetMailListRequest.cs
new file mode 100644
index 00000000..1b6a897d
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppGetMailListRequest.cs
@@ -0,0 +1,36 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Models
+{
+ ///
+ /// 表示 [POST] /cgi-bin/exmail/app/get_mail_list 接口的请求。
+ ///
+ public class CgibinExmailAppGetMailListRequest : WechatWorkRequest
+ {
+ ///
+ /// 获取或设置开始时间戳。
+ ///
+ [Newtonsoft.Json.JsonProperty("begin_time")]
+ [System.Text.Json.Serialization.JsonPropertyName("begin_time")]
+ public long? BeginTimestamp { get; set; }
+
+ ///
+ /// 获取或设置结束时间戳。
+ ///
+ [Newtonsoft.Json.JsonProperty("end_time")]
+ [System.Text.Json.Serialization.JsonPropertyName("end_time")]
+ public long? Endimestamp { get; set; }
+
+ ///
+ /// 获取或设置分页每页数量。
+ ///
+ [Newtonsoft.Json.JsonProperty("limit")]
+ [System.Text.Json.Serialization.JsonPropertyName("limit")]
+ public int? Limit { get; set; }
+
+ ///
+ /// 获取或设置翻页标记。
+ ///
+ [Newtonsoft.Json.JsonProperty("cursor")]
+ [System.Text.Json.Serialization.JsonPropertyName("cursor")]
+ public string? Cursor { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppGetMailListResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppGetMailListResponse.cs
new file mode 100644
index 00000000..11472c57
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppGetMailListResponse.cs
@@ -0,0 +1,44 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Models
+{
+ ///
+ /// 表示 [POST] /cgi-bin/exmail/app/get_mail_list 接口的响应。
+ ///
+ public class CgibinExmailAppGetMailListResponse : WechatWorkResponse
+ {
+ public static class Types
+ {
+ public class Mail
+ {
+ ///
+ /// 获取或设置邮件 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("mail_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("mail_id")]
+ public string MailId { get; set; } = default!;
+ }
+ }
+
+ ///
+ /// 获取或设置分组列表。
+ ///
+ [Newtonsoft.Json.JsonProperty("mail_list")]
+ [System.Text.Json.Serialization.JsonPropertyName("mail_list")]
+ public Types.Mail[] MailList { get; set; } = default!;
+
+ ///
+ /// 获取或设置是否还有更多数据。
+ ///
+ [Newtonsoft.Json.JsonProperty("has_more")]
+ [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.NumericalBooleanConverter))]
+ [System.Text.Json.Serialization.JsonPropertyName("has_more")]
+ [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Converters.NumericalBooleanConverter))]
+ public bool HasMore { get; set; }
+
+ ///
+ /// 获取或设置翻页标记。
+ ///
+ [Newtonsoft.Json.JsonProperty("next_cursor")]
+ [System.Text.Json.Serialization.JsonPropertyName("next_cursor")]
+ public string? NextCursor { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppReadMailRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppReadMailRequest.cs
new file mode 100644
index 00000000..63e1c4f0
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppReadMailRequest.cs
@@ -0,0 +1,15 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Models
+{
+ ///
+ /// 表示 [POST] /cgi-bin/exmail/app/read_mail 接口的请求。
+ ///
+ public class CgibinExmailAppReadMailRequest : WechatWorkRequest
+ {
+ ///
+ /// 获取或设置邮件 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("mail_id")]
+ [System.Text.Json.Serialization.JsonPropertyName("mail_id")]
+ public string MailId { get; set; } = string.Empty;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppReadMailResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppReadMailResponse.cs
new file mode 100644
index 00000000..2f789224
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinExmail/App/CgibinExmailAppReadMailResponse.cs
@@ -0,0 +1,15 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Models
+{
+ ///
+ /// 表示 [POST] /cgi-bin/exmail/app/read_mail 接口的响应。
+ ///
+ public class CgibinExmailAppReadMailResponse : WechatWorkResponse
+ {
+ ///
+ /// 获取或设置邮件 EML 内容。
+ ///
+ [Newtonsoft.Json.JsonProperty("mail_data")]
+ [System.Text.Json.Serialization.JsonPropertyName("mail_data")]
+ public string MailData { get; set; } = default!;
+ }
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/EventSamples/Exmail/AppEmailChangeEvent.xml b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/EventSamples/Exmail/AppEmailChangeEvent.xml
new file mode 100644
index 00000000..2da49888
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/EventSamples/Exmail/AppEmailChangeEvent.xml
@@ -0,0 +1,9 @@
+
+
+
+ 1668831860
+
+
+
+
+
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppGetMailListRequest.json b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppGetMailListRequest.json
new file mode 100644
index 00000000..3ede84b9
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppGetMailListRequest.json
@@ -0,0 +1,6 @@
+{
+ "begin_time": 1668441600,
+ "end_time": 1668527999,
+ "cursor": "CURSOR",
+ "limit": 100
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppGetMailListResponse.json b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppGetMailListResponse.json
new file mode 100644
index 00000000..0340de81
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppGetMailListResponse.json
@@ -0,0 +1,11 @@
+{
+ "errcode": 0,
+ "errmsg": "ok",
+ "next_cursor": "NEXT_CURSOR",
+ "has_more": 0,
+ "mail_list": [
+ {
+ "mail_id": "MAIL_ID"
+ }
+ ]
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppReadMailRequest.json b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppReadMailRequest.json
new file mode 100644
index 00000000..979d528b
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppReadMailRequest.json
@@ -0,0 +1,3 @@
+{
+ "mail_id": "MAIL_ID"
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppReadMailResponse.json b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppReadMailResponse.json
new file mode 100644
index 00000000..f86e4efe
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinExmail/App/CgibinExmailAppReadMailResponse.json
@@ -0,0 +1,5 @@
+{
+ "errcode": 0,
+ "errmsg": "ok",
+ "mail_data": "MAIL_DATA"
+}