一套核心代码、双平台(宝塔 Node / EdgeOne Cloud Functions)部署的多业务 API 中枢。
所有 JSON 接口统一响应包络:
| 字段 | 类型 | 说明 |
|---|---|---|
code | number | 业务码,0 表示成功 |
message | string | 提示信息 |
data | any | 业务数据(失败时为 null) |
serverTime | string | 服务端时间 |
elapsed | string | 处理耗时,如 12ms |
鉴权:Email 两种发信模式鉴权规则不同:① 服务端 SMTP(环境变量)直发,无需鉴权,受收件人白名单约束;② 客户端自定义发件服务(请求体带 smtp 字段),必须配置 EMAIL_KEY 并携带 Email-Key 授权。IP 服务与 /email/health 不鉴权。
CORS:默认允许跨域;OPTIONS 预检直接返回 204。
健康检查:每个服务都提供 <basePath>/health 健康检查,便于探活与自检。
新增服务:服务路由前缀统一为 /<svc>;新增服务 = 写 src/services/<svc>/ + 在 dispatcher 注册 + 加 cloud-functions/<svc>/ 入口。
错误码规则:0=成功;4xx/5xx 为通用码(各服务含义一致);1xxx=IP 专用;2xxx=Email 专用;3xxx+ 预留给未来服务。各服务章节只列其专用码,通用码见下表。
| HTTP | code | 说明 |
|---|---|---|
| 200 | 0 | 成功 |
| 400 | 400 | 请求参数错误(通用) |
| 401 | 401 | 未授权(通用) |
| 403 | 403 | 禁止访问(黑名单 / 白名单,通用) |
| 404 | 404 | 接口不存在(通用) |
| 405 | 405 | 方法不允许(通用) |
| 413 | 413 | 请求体过大(通用) |
| 429 | 429 | 请求过于频繁(通用,仅宝塔侧限流) |
| 500 | 500 | 服务器内部错误(通用) |
| 502 | 502 | 上游服务失败(通用) |
| 503 | 503 | 服务暂不可用(通用,无可用数据源) |
| 变量 | 说明 |
|---|---|
PORT | 监听端口,默认 8103(宝塔侧) |
NODE_ENV | 运行环境 production / development,默认 production |
LOG_LEVEL | 日志级别 DEBUG / INFO / WARN / ERROR,默认 INFO |
RATE_LIMIT_ENABLED | 限流总开关,默认 true(仅显式 false 关闭,且仅宝塔侧生效) |
RATE_LIMIT_WINDOW_MS | 限流计数周期(毫秒),默认 60000 |
RATE_LIMIT_MAX_PER_IP | 单 IP 每周期最大请求数,默认 60 |
RATE_LIMIT_MAX_GLOBAL | 全局每周期最大请求数,默认 600 |
RATE_LIMIT_WHITELIST | 限流白名单(逗号分隔 IP,不受限),默认空 |
RATE_LIMIT_BLACKLIST | 限流黑名单(逗号分隔 IP,直接 403),默认空 |
TRUST_PROXY | 反代层数,Nginx 等反代后设 1(默认 1);直接暴露设 false |
多源聚合 / 单源 / 对比三种模式;支持 IPv4 / IPv6、批量查询与工具端点。
不传 ip 时自动解析请求来源 IP 并返回归属地;按优先级聚合多个数据源。
curl "https://example.com/ip"
{
"code": 0,
"message": "success",
"data": {
"status": "success",
"data": {
"ip": "114.114.114.114",
"version": "v4",
"country": "中国",
"province": "江苏省",
"city": "南京市",
"district": "玄武区",
"isp": "中国电信",
"countryCode": "CN",
"provinceCode": "320000",
"latitude": 32.0584,
"longitude": 118.7965,
"timezone": "Asia/Shanghai"
},
"source": "ip2region"
},
"serverTime": "2026-10-28 12:00:00.000",
"elapsed": "45ms"
}
通过 query 传 ip,支持 IPv4 / IPv6。
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
ip | query | string | 否 | 要查询的 IPv4 / IPv6 |
curl "https://example.com/ip?ip=8.8.8.8"
source=数据源名 → 单源模式;source=all → 并发对比所有已启用源(data.data.sources)。
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
source | query | string | 否 | auto(默认聚合)| 数据源名 | all(对比) 可选:auto / ip2region / czdb / geolite2 / ip2location / ipip / all |
curl "https://example.com/ip?ip=8.8.8.8&source=all"
把 IP 放在路径里。IPv6 的冒号需 URL 编码为 %3A。
curl "https://example.com/ip/2400%3A3200%3A%3A1"
一次查询多个 IP;对比模式(source=all)不支持批量。
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
ips | body | string[] | 是 | IP 数组,最多 100 个 |
source | body | string | 否 | 同 GET 的 source |
curl -X POST "https://example.com/ip" -H "Content-Type: application/json" -d '{"ips":["8.8.8.8","1.1.1.1"]}'
返回各数据源状态、优先级、字段优先级;用于探活与部署自检。
curl "https://example.com/ip/health"
返回纯文本客户端 IP(类似 ipify 的 text 接口)。
curl "https://example.com/ip/ip"
返回精简的国家 / 省 / 市信息。
curl "https://example.com/ip/geo"
返回 { ip, city, region, country },可直接替换 ipify。
curl "https://example.com/ip/json"
返回服务端时间与客户端时区信息。
curl "https://example.com/ip/time"
解析请求 UA(浏览器 / 系统 / 设备等)。
curl "https://example.com/ip/ua"
原样返回请求头,便于调试转发链路(如 CDN / 反代)。
curl "https://example.com/ip/headers"
| HTTP | code | 说明 |
|---|---|---|
| 400 | 1101 | 批量查询数量超限 |
| 500 | 1103 | 指定数据源不可用 |
| 变量 | 说明 |
|---|---|
DATA_DIR | IP 数据文件目录(可选,默认自动探测) |
CZDB_KEY | 纯真 CZDB 密钥 |
ENABLE_IP2REGION / ENABLE_CZDB / ENABLE_GEOLITE2 / ENABLE_IP2LOCATION / ENABLE_IPIP | 各数据源开关,默认全部 true;EO 可只留 ip2region |
RATE_LIMIT_ENABLED | 限流总开关,默认 true(仅宝塔侧生效) |
RATE_LIMIT_WINDOW_MS | 限流计数周期(毫秒),默认 60000 |
RATE_LIMIT_MAX_PER_IP | 单 IP 每周期最大请求数,默认 60 |
RATE_LIMIT_MAX_GLOBAL | 全局每周期最大请求数,默认 600 |
RATE_LIMIT_WHITELIST | 限流白名单(逗号分隔 IP,不受限,默认空) |
RATE_LIMIT_BLACKLIST | 限流黑名单(逗号分隔 IP,直接 403,默认空) |
TRUST_PROXY | 反代层数,Nginx 反代后设 1(默认 1);直接暴露设 false,否则限流按代理 IP 计数 |
直连 SMTP 发送邮件;支持标准写法(text/html)与兼容写法(content + mediaType)。
两种模式:① 服务端 SMTP(环境变量)直发,无需鉴权;② 请求体带 smtp 字段由客户端指定发件服务,需 EMAIL_KEY + Email-Key 授权。发件人取自对应 SMTP 配置。
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
Email-Key | header | string | 否 | 自定义发件模式必填:服务端配置 EMAIL_KEY 后,携带 smtp 的请求须带此头;服务端 SMTP 模式不需要 |
Content-Type | header | string | 否 | 建议 application/json;宝塔侧已兼容无该头或 text/plain |
| 参数 | 位置 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
to | body | string | string[] | 是 | 收件人,别名 toAddress |
subject | body | string | 是 | 邮件标题 |
text | body | string | 否 | 纯文本正文(与 html 至少其一) |
html | body | string | 否 | HTML 正文(与 text 至少其一) |
content | body | string | 否 | 兼容写法正文,配合 mediaType |
mediaType | body | string | 否 | text/plain → text;含 text/html → html |
cc | body | string | string[] | 否 | 抄送 |
bcc | body | string | string[] | 否 | 密送 |
replyTo | body | string | 否 | 回复地址 |
fromName | body | string | 否 | 发件人显示名(昵称),可选。仅改变 From 头显示名,不改变发件地址;服务端模式默认取 SMTP_FROM_NAME,自定义模式默认取 from 的 @ 前部分 |
smtp | body | object | 否 | 自定义发件服务:含 host/from/pass(from 即发件账号,对应环境变量 SMTP_FROM);port 可选,缺省回退服务端 SMTP_PORT(未配则 465,25 被禁)。端口自动识别:465 走隐式 TLS,587/2525 走 STARTTLS(25 已禁用)。国内 163/126 仅支持 465,不支持 587/2525。注:994 非 SMTP 标准端口,请勿使用。携带即进入自定义模式,需 Email-Key 授权 |
# 模式一:传统模式(服务端 SMTP 直发,无需鉴权,受白名单约束)
curl -X POST "https://example.com/email" \
-H "Content-Type: application/json" \
-d '{"to":"a@b.com","subject":"hi","text":"hello"}'
# 模式二:含 cc / bcc / replyTo 完整示例
curl -X POST "https://example.com/email" \
-H "Content-Type: application/json" \
-d '{"to":"a@b.com","cc":"cc@b.com","bcc":"bcc@b.com","replyTo":"reply@b.com","subject":"hi","text":"hello"}'
# 模式三:自定义发件服务(需 EMAIL_KEY + Email-Key),含 from 与 port
curl -X POST "https://example.com/email" \
-H "Content-Type: application/json" \
-H "Email-Key: <你的KEY>" \
-d '{"to":"a@b.com","subject":"hi","text":"hello","smtp":{"host":"smtp.qq.com","port":465,"from":"me@qq.com","pass":"授权码"}}'
# 模式四:环境变量模式 + 自定义发件人显示名(fromName),无需鉴权
curl -X POST "https://example.com/email" \
-H "Content-Type: application/json" \
-d '{"to":"a@b.com","subject":"hi","text":"hello","fromName":"系统通知"}'
{
"code": 0,
"message": "success",
"data": {
"messageId": "<112050c2d1833f74c0a68481db205987@126.com>",
"accepted": [
"a@b.com"
],
"provider": "smtp.126.com:465",
"channel": "smtp",
"sendMs": 573
},
"serverTime": "2026-10-28 12:00:00.000",
"elapsed": "580ms"
}
检查 SMTP 配置是否就绪(不真实发信),兼容 GET。
curl -X POST "https://example.com/email/health"
| HTTP | code | 说明 |
|---|---|---|
| 400 | 2101 | 缺少 to(MISSING_TO) |
| 400 | 2102 | 缺少 subject(MISSING_SUBJECT) |
| 400 | 2103 | text/html 或 content 至少提供一个(MISSING_BODY) |
| 400 | 2104 | 请求体非合法 JSON(INVALID_JSON) |
| 400 | 2105 | 请求体必须是 JSON 对象(INVALID_BODY) |
| 400 | 2106 | 参数不合法(INVALID_PARAM) |
| 400 | 2107 | 收件人数量超限(TOO_MANY_RECIPIENTS) |
| 500 | 2501 | 缺少 SMTP 配置(CONFIG_ERROR) |
| 502 | 2521 | SMTP 发信失败(SMTP_ERROR) |
| 变量 | 说明 |
|---|---|
SMTP_HOST | SMTP 服务器(如 smtp.126.com / smtp.163.com) |
SMTP_PORT | 端口,默认 465;163/126 只能用 465;587/2525 走 STARTTLS |
SMTP_PASS | 授权码(非登录密码) |
SMTP_FROM | 发件邮箱,同时作为 SMTP 登录账号 |
SMTP_FROM_NAME | 发件人显示名(可选,可被请求体 fromName 覆盖) |
SMTP_HELO | EHLO 域名(可选,默认取 SMTP_FROM 的域名) |
SMTP_TIMEOUT_MS | 连接/会话超时(毫秒),默认 15000 |
EMAIL_KEY | 自定义发件模式密钥;配置后,携带 smtp 字段的请求须带 Email-Key。服务端 SMTP 模式无需它 |
WHITELIST_ENABLED / TO_WHITELIST | 收件人白名单(支持 @域名 通配) |
MAX_RECIPIENTS / MAX_BODY_BYTES | 默认 20 人 / 256KB |