# 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`: | 参数名称 | 类型 | 示例值 | 说明 | |----------|------|--------|------| | pageIndex | Integer | 1 | 当前页码 | | pageSize | Integer | 20 | 每页数量 | | total | Long | 150 | 总记录数 | | records | Array\ | - | 邮件列表 | > **注意**: > - 请求和响应统一使用 `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 | 服务器内部错误 |