init: mipu-open 对外开放项目统一管理仓库
- 添加 mipu-api 作为 git submodule (Claude Code Skill) - 迁移 API 文档源文件到 docs/ 目录统一维护 - 添加 Gitea Actions 工作流:tag推送自动打包docs并发布Release - Skill 运行时自动从 mipu-open Release 下载最新文档 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
400
docs/11-06_mailbox-mail-search.md
Normal file
400
docs/11-06_mailbox-mail-search.md
Normal file
@@ -0,0 +1,400 @@
|
||||
<!-- mipuyun-api-doc: mailbox-mail-search -->
|
||||
# mailbox/mail/search - 搜索邮件
|
||||
|
||||
## 概述
|
||||
|
||||
根据关键词、邮件类型等条件搜索邮件,返回分页结果。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户需要在邮箱中查找特定邮件
|
||||
- 根据关键词、邮件类型等条件筛选邮件
|
||||
- 分页浏览邮件列表
|
||||
|
||||
## 请求说明
|
||||
|
||||
| 项目 | 值 |
|
||||
|------|-----|
|
||||
| **请求地址** | `https://${endpoint}/mailbox/mail/search` |
|
||||
| **请求方法** | POST |
|
||||
|
||||
### Header 参数
|
||||
|
||||
| 参数名称 | 类型 | 是否必选 | 示例值 | 说明 |
|
||||
|----------|------|----------|--------|------|
|
||||
| Content-Type | String | 是 | application/json | 固定值,指定请求体格式为 JSON |
|
||||
| Accept-Encoding | String | 是 | gzip, deflate, br | 必须要填写,否则服务器会拒绝 |
|
||||
| client-key | String | 是 | xxxxx | 联系我们获取生产环境 key |
|
||||
| client-secret | String | 是 | xxxxx | 联系我们获取生产环境 secret |
|
||||
|
||||
### 请求体参数
|
||||
|
||||
| 参数名称 | 类型 | 是否必选 | 示例值 | 说明 |
|
||||
|----------|------|----------|--------|------|
|
||||
| keyword | String | 否 | 机票 | 搜索关键词,支持邮件主题、发件人等 |
|
||||
| mailType | Integer | 否 | 1 | 邮件类型:1-收件,2-发件 |
|
||||
| domainName | String | 否 | example.com | 域名过滤 |
|
||||
| hasAttachment | Boolean | 否 | true | 是否有附件 |
|
||||
| readStatus | Integer | 否 | 0 | 阅读状态:0-未读,1-已读 |
|
||||
| startTime | String | 否 | 2025-01-01T00:00:00Z | 起始时间(ISO 8601格式,**必须使用UTC时区**,以`Z`结尾) |
|
||||
| endTime | String | 否 | 2025-01-31T23:59:59Z | 结束时间(ISO 8601格式,**必须使用UTC时区**,以`Z`结尾) |
|
||||
| airlineCode | String | 否 | CA | 航空代码(如:CA-国航、MU-东航、CZ-南航等) |
|
||||
| pageIndex | Integer | 是 | 1 | 页码,从1开始 |
|
||||
| pageSize | Integer | 是 | 20 | 每页数量,建议10-50,最大100 |
|
||||
| orderBy | String | 否 | sendTime | 排序字段,支持:`sendTime`(发送时间)、`receiveTime`(接收时间)、`subject`(主题) |
|
||||
| orderDirection | String | 否 | DESC | 排序方向:`ASC`=升序,`DESC`=降序 |
|
||||
|
||||
#### 请求体示例
|
||||
|
||||
```json
|
||||
{
|
||||
"keyword": "机票",
|
||||
"mailType": 1,
|
||||
"airlineCode": "CA",
|
||||
"pageIndex": 1,
|
||||
"pageSize": 20,
|
||||
"orderBy": "sendTime",
|
||||
"orderDirection": "DESC"
|
||||
}
|
||||
```
|
||||
|
||||
## 返回参数
|
||||
|
||||
返回分页结果 `PageResult<MailInfo>`:
|
||||
|
||||
| 参数名称 | 类型 | 示例值 | 说明 |
|
||||
|----------|------|--------|------|
|
||||
| pageIndex | Integer | 1 | 当前页码 |
|
||||
| pageSize | Integer | 20 | 每页数量 |
|
||||
| total | Long | 150 | 总记录数 |
|
||||
| records | Array\<MailInfo\> | - | 邮件列表 |
|
||||
|
||||
> **注意**:
|
||||
> - 请求和响应统一使用 `pageIndex`
|
||||
> - 总页数 `totalPages` 字段已移除,前端需自行计算:`totalPages = Math.ceil(total / pageSize)`
|
||||
|
||||
### MailInfo 对象字段
|
||||
|
||||
| 参数名称 | 类型 | 示例值 | 说明 |
|
||||
|----------|------|--------|------|
|
||||
| mailId | String | MSG_001 | 邮件ID |
|
||||
| subject | String | 机票预订确认 | 邮件主题 |
|
||||
| fromAddress | String | airline@example.com | 发件人地址 |
|
||||
| toAddresses | String\[\] | ["user@example.com"] | 收件人列表 |
|
||||
| ccAddresses | String\[\] | ["cc@example.com"] | 抄送列表 |
|
||||
| mailType | Integer | 1 | 邮件类型:1-收件,2-发件 |
|
||||
| mailTypeText | String | 收件 | 类型文本 |
|
||||
| hasAttachment | Boolean | true | 是否有附件 |
|
||||
| attachmentCount | Integer | 2 | 附件数量 |
|
||||
| mailSize | Long | 1024000 | 邮件大小(字节) |
|
||||
| mailSizeText | String | 1.0 MB | 人性化大小 |
|
||||
| readStatus | Integer | 0 | 阅读状态:0-未读,1-已读 |
|
||||
| receiveTime | String | 2025-01-02T10:00:00Z | 接收时间 |
|
||||
| sendTime | String | 2025-01-02T10:00:00Z | 发送时间 |
|
||||
| emlDownloadUrl | String | https://... | 原始EML文件下载地址(临时链接,1小时有效期) |
|
||||
|
||||
## 返回示例
|
||||
|
||||
```json
|
||||
{
|
||||
"pageIndex": 1,
|
||||
"pageSize": 20,
|
||||
"total": 150,
|
||||
"records": [
|
||||
{
|
||||
"mailId": "MSG_001",
|
||||
"subject": "机票预订确认",
|
||||
"fromAddress": "airline@example.com",
|
||||
"toAddresses": ["user@example.com"],
|
||||
"ccAddresses": ["cc@example.com"],
|
||||
"mailType": 1,
|
||||
"mailTypeText": "收件",
|
||||
"hasAttachment": true,
|
||||
"attachmentCount": 2,
|
||||
"mailSize": 1024000,
|
||||
"mailSizeText": "1.0 MB",
|
||||
"readStatus": 0,
|
||||
"receiveTime": "2025-01-02T10:00:00Z",
|
||||
"sendTime": "2025-01-02T10:00:00Z",
|
||||
"emlDownloadUrl": "https://cdn.example.com/download/eml/MSG_001?token=xxx"
|
||||
},
|
||||
{
|
||||
"mailId": "MSG_002",
|
||||
"subject": "航班变更通知",
|
||||
"fromAddress": "airline@example.com",
|
||||
"toAddresses": ["user@example.com"],
|
||||
"ccAddresses": [],
|
||||
"mailType": 1,
|
||||
"mailTypeText": "收件",
|
||||
"hasAttachment": false,
|
||||
"attachmentCount": 0,
|
||||
"mailSize": 51200,
|
||||
"mailSizeText": "50.0 KB",
|
||||
"readStatus": 1,
|
||||
"receiveTime": "2025-01-02T09:00:00Z",
|
||||
"sendTime": "2025-01-02T09:00:00Z",
|
||||
"emlDownloadUrl": "https://cdn.example.com/download/eml/MSG_002?token=yyy"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 时区说明
|
||||
|
||||
### UTC 时区要求
|
||||
|
||||
本接口要求所有时间参数**必须使用 UTC 时区**(协调世界时)。
|
||||
|
||||
**什么是 UTC?**
|
||||
- UTC(Coordinated Universal Time)是世界标准时间,不受夏令时影响
|
||||
- UTC 是全球统一的时间基准,与地理位置无关
|
||||
- 北京时间 = UTC + 8小时,纽约时间 = UTC - 5小时(东部标准时间)
|
||||
|
||||
**为什么使用 UTC?**
|
||||
1. **避免时区混淆**:不同地区的服务器和客户端使用不同时区会导致时间解释错误
|
||||
2. **跨时区一致**:确保全球用户查询结果一致
|
||||
3. **简化逻辑**:无需处理复杂的时区转换和夏令时问题
|
||||
|
||||
**时间格式要求:**
|
||||
```
|
||||
ISO 8601 格式:2025-01-15T00:00:00Z
|
||||
^^^^^^^^^^^ ^^^^^^^ ^ ^
|
||||
日期 时间 时区标识(UTC)
|
||||
```
|
||||
|
||||
### 时间转换示例
|
||||
|
||||
| 本地时间 | UTC 时间(需要发送) | 说明 |
|
||||
|----------|---------------------|------|
|
||||
| 2025-01-15 00:00:00 (北京) | 2025-01-14T16:00:00Z | 北京时间 UTC+8,减8小时 |
|
||||
| 2025-01-15 00:00:00 (纽约) | 2025-01-15T05:00:00Z | 纽约时间 UTC-5,加5小时 |
|
||||
| 2025-01-15 00:00:00 (伦敦) | 2025-01-15T00:00:00Z | 伦敦时间 UTC+0(冬季) |
|
||||
| 2025-01-15 00:00:00 (东京) | 2025-01-14T15:00:00Z | 东京时间 UTC+9,减9小时 |
|
||||
|
||||
> **重要**:发送时间前,请务必将本地时间转换为 UTC 时间!
|
||||
|
||||
### 代码示例
|
||||
|
||||
#### Java 示例
|
||||
|
||||
```java
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import okhttp3.*;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class MailSearchExample {
|
||||
|
||||
private static final String API_ENDPOINT = "https://api.example.com/mailbox/mail/search";
|
||||
private static final String CLIENT_KEY = "your-client-key";
|
||||
private static final String CLIENT_SECRET = "your-client-secret";
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 方式1: 使用当前时间(自动转换为UTC)
|
||||
ZonedDateTime nowUtc = ZonedDateTime.now(ZoneOffset.UTC);
|
||||
ZonedDateTime oneDayAgoUtc = nowUtc.minusDays(1);
|
||||
|
||||
// 方式2: 从本地时间转换到UTC
|
||||
ZonedDateTime localTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
|
||||
ZonedDateTime utcTime = localTime.withZoneSameInstant(ZoneOffset.UTC);
|
||||
|
||||
// 方式3: 指定特定时间(例如:北京时间2025-01-15 00:00:00)
|
||||
ZonedDateTime beijingTime = ZonedDateTime.of(
|
||||
2025, 1, 15, 0, 0, 0, 0,
|
||||
ZoneId.of("Asia/Shanghai")
|
||||
);
|
||||
ZonedDateTime startTimeUtc = beijingTime.withZoneSameInstant(ZoneOffset.UTC);
|
||||
ZonedDateTime endTimeUtc = beijingTime.plusDays(1).minusSeconds(1)
|
||||
.withZoneSameInstant(ZoneOffset.UTC);
|
||||
|
||||
// 格式化为ISO 8601格式(带Z后缀)
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
|
||||
String startTime = startTimeUtc.format(formatter); // 2025-01-14T16:00:00Z
|
||||
String endTime = endTimeUtc.format(formatter); // 2025-01-15T15:59:59Z
|
||||
|
||||
// 构建请求体
|
||||
MailSearchRequest request = new MailSearchRequest();
|
||||
request.setKeyword("机票");
|
||||
request.setMailType(1);
|
||||
request.setStartTime(startTime);
|
||||
request.setEndTime(endTime);
|
||||
request.setPageIndex(1);
|
||||
request.setPageSize(20);
|
||||
|
||||
// 设置排序(按发送时间降序)
|
||||
request.setOrderBy("sendTime");
|
||||
request.setOrderDirection("DESC");
|
||||
|
||||
// 发送请求
|
||||
sendRequest(request);
|
||||
}
|
||||
|
||||
static class MailSearchRequest {
|
||||
private String keyword;
|
||||
private Integer mailType;
|
||||
private String startTime;
|
||||
private String endTime;
|
||||
private Integer pageIndex;
|
||||
private Integer pageSize;
|
||||
private String orderBy;
|
||||
private String orderDirection;
|
||||
|
||||
// getters and setters...
|
||||
}
|
||||
|
||||
private static void sendRequest(MailSearchRequest request) throws Exception {
|
||||
Gson gson = new Gson();
|
||||
String json = gson.toJson(request);
|
||||
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
RequestBody body = RequestBody.create(
|
||||
json,
|
||||
MediaType.parse("application/json; charset=utf-8")
|
||||
);
|
||||
|
||||
Request httpRequest = new Request.Builder()
|
||||
.url(API_ENDPOINT)
|
||||
.post(body)
|
||||
.addHeader("Content-Type", "application/json")
|
||||
.addHeader("Accept-Encoding", "gzip, deflate, br")
|
||||
.addHeader("client-key", CLIENT_KEY)
|
||||
.addHeader("client-secret", CLIENT_SECRET)
|
||||
.build();
|
||||
|
||||
try (Response response = client.newCall(httpRequest).execute()) {
|
||||
System.out.println(response.body().string());
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Python 示例
|
||||
|
||||
```python
|
||||
import requests
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from zoneinfo import ZoneInfo # Python 3.9+
|
||||
import json
|
||||
|
||||
API_ENDPOINT = "https://api.example.com/mailbox/mail/search"
|
||||
CLIENT_KEY = "your-client-key"
|
||||
CLIENT_SECRET = "your-client-secret"
|
||||
|
||||
def search_mails():
|
||||
# 方式1: 使用当前UTC时间
|
||||
now_utc = datetime.now(timezone.utc)
|
||||
one_day_ago_utc = now_utc - timedelta(days=1)
|
||||
|
||||
# 方式2: 从本地时间转换到UTC(例如:北京时间)
|
||||
beijing_tz = ZoneInfo("Asia/Shanghai")
|
||||
local_time = datetime(2025, 1, 15, 0, 0, 0, tzinfo=beijing_tz)
|
||||
start_time_utc = local_time.astimezone(timezone.utc)
|
||||
end_time_utc = (local_time + timedelta(days=1) - timedelta(seconds=1)).astimezone(timezone.utc)
|
||||
|
||||
# 方式3: 直接创建UTC时间
|
||||
start_time_utc = datetime(2025, 1, 14, 16, 0, 0, tzinfo=timezone.utc)
|
||||
end_time_utc = datetime(2025, 1, 15, 15, 59, 59, tzinfo=timezone.utc)
|
||||
|
||||
# 格式化为ISO 8601格式(带Z后缀)
|
||||
start_time = start_time_utc.isoformat()
|
||||
end_time = end_time_utc.isoformat()
|
||||
# 结果: "2025-01-14T16:00:00+00:00" 或 "2025-01-14T16:00:00Z"
|
||||
|
||||
# 确保以Z结尾(某些库可能使用+00:00)
|
||||
if not start_time.endswith('Z'):
|
||||
start_time = start_time.replace('+00:00', 'Z').replace('+00:00:00', 'Z')
|
||||
if not end_time.endswith('Z'):
|
||||
end_time = end_time.replace('+00:00', 'Z').replace('+00:00:00', 'Z')
|
||||
|
||||
# 构建请求体
|
||||
payload = {
|
||||
"keyword": "机票",
|
||||
"mailType": 1,
|
||||
"startTime": start_time, # "2025-01-14T16:00:00Z"
|
||||
"endTime": end_time, # "2025-01-15T15:59:59Z"
|
||||
"pageIndex": 1,
|
||||
"pageSize": 20,
|
||||
"orderBy": "sendTime",
|
||||
"orderDirection": "DESC"
|
||||
}
|
||||
|
||||
# 发送请求
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"client-key": CLIENT_KEY,
|
||||
"client-secret": CLIENT_SECRET
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
API_ENDPOINT,
|
||||
data=json.dumps(payload),
|
||||
headers=headers
|
||||
)
|
||||
|
||||
print(f"Status Code: {response.status_code}")
|
||||
print(f"Response: {response.json()}")
|
||||
|
||||
return response.json()
|
||||
|
||||
# 常用时区转换工具函数
|
||||
def convert_to_utc(local_time_str, local_timezone="Asia/Shanghai"):
|
||||
"""
|
||||
将本地时间字符串转换为UTC时间字符串
|
||||
|
||||
Args:
|
||||
local_time_str: 本地时间,如 "2025-01-15 00:00:00"
|
||||
local_timezone: 本地时区,默认 "Asia/Shanghai"
|
||||
|
||||
Returns:
|
||||
UTC时间字符串,如 "2025-01-14T16:00:00Z"
|
||||
"""
|
||||
local_tz = ZoneInfo(local_timezone)
|
||||
local_dt = datetime.strptime(local_time_str, "%Y-%m-%d %H:%M:%S")
|
||||
local_dt = local_dt.replace(tzinfo=local_tz)
|
||||
utc_dt = local_dt.astimezone(timezone.utc)
|
||||
return utc_dt.isoformat().replace('+00:00', 'Z')
|
||||
|
||||
# 使用示例
|
||||
if __name__ == "__main__":
|
||||
# 北京时间 2025-01-15 00:00:00 转换为 UTC
|
||||
utc_time = convert_to_utc("2025-01-15 00:00:00", "Asia/Shanghai")
|
||||
print(f"UTC Time: {utc_time}") # 输出: 2025-01-14T16:00:00Z
|
||||
|
||||
search_mails()
|
||||
```
|
||||
|
||||
#### cURL 示例
|
||||
|
||||
```bash
|
||||
curl -X POST "https://api.example.com/mailbox/mail/search" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Accept-Encoding: gzip, deflate, br" \
|
||||
-H "client-key: your-client-key" \
|
||||
-H "client-secret: your-client-secret" \
|
||||
-d '{
|
||||
"keyword": "机票",
|
||||
"mailType": 1,
|
||||
"startTime": "2025-01-14T16:00:00Z",
|
||||
"endTime": "2025-01-15T15:59:59Z",
|
||||
"pageIndex": 1,
|
||||
"pageSize": 20,
|
||||
"orderBy": "sendTime",
|
||||
"orderDirection": "DESC"
|
||||
}'
|
||||
```
|
||||
|
||||
## 搜索技巧
|
||||
|
||||
- 支持模糊匹配,关键词可以匹配邮件主题和发件人
|
||||
- mailType 为可选参数,不传则搜索所有类型邮件
|
||||
- 建议 pageSize 设置为 20-50 以获得最佳性能
|
||||
- **时间参数必须使用 UTC 时区**,发送前请确保时间已正确转换
|
||||
|
||||
## 错误码说明
|
||||
|
||||
| 错误码 | 说明 |
|
||||
|--------|------|
|
||||
| 400 | 请求参数错误,pageIndex、pageSize、orderBy 或 orderDirection 不合法 |
|
||||
| 401 | 认证失败,client-key 或 client-secret 无效 |
|
||||
| 500 | 服务器内部错误 |
|
||||
Reference in New Issue
Block a user