• 简体中文
  • API 接口 / API Reference

    公开发件接口

    POST /api/{pid}/send

    pid 是发件商创建时随机生成的 5–10 位路由标识。每个发件商有独立的接口地址、独立的密钥与收件域名白名单。

    鉴权

    在以下任一位置携带该发件商的 32 位 API 密钥:

    Authorization: Bearer <api-key>

    或

    x-api-key: <api-key>

    或 query 参数 ?key=<api-key>(不推荐,可能被日志记录)。

    请求体

    字段必填说明
    to是收件人地址
    subject是邮件主题
    text二选一纯文本正文
    html二选一HTML 正文

    text 与 html 至少传一个;都传时客户端按类型展示。

    请求示例

    curl -X POST https://your-app.vercel.app/api/a1b2c3/send \
      -H "Authorization: Bearer AbCdEfGh1234567890AbCdEfGh1234567890" \
      -H "Content-Type: application/json" \
      -d '{
        "to": "someone@example.com",
        "subject": "Hello",
        "text": "Sent via MailPort."
      }'

    成功响应

    {
      "success": true,
      "messageId": "<uuid@example.com>"
    }

    错误响应

    状态码含义
    400缺少必填字段、收件地址格式无效
    401未提供密钥或密钥无效/已禁用
    403收件域名不在该发件商的白名单内
    404pid 不存在或发件商已禁用
    500发送失败,details 为底层错误
    503服务器未配置数据库或主密钥

    所有错误响应格式为 { "error": "...", "details"?: "..." }。

    管理端接口

    所有 /api/admin/** 接口需要登录后的签名 Cookie,未登录返回 401。

    会话

    POST /api/admin/login     body: { "password": "..." }     → { "success": true }  (下发 Cookie)
    POST /api/admin/logout                                      → { "success": true }  (清除 Cookie)

    发件商

    GET    /api/admin/senders                    → { rows: Sender[], total: number }
    POST   /api/admin/senders                    → { sender: Sender, keys: SenderKey[] }
    GET    /api/admin/senders/{id}               → { sender: Sender, keys: SenderKey[] }
    PUT    /api/admin/senders/{id}               → { sender: Sender }
    DELETE /api/admin/senders/{id}               → { success: true }

    新增发件商时会自动生成首个 32 位密钥。删除发件商会级联删除其全部密钥与日志。

    Sender 字段:

    {
      "id": "uuid",
      "pid": "a1b2c3",
      "name": "My blog mailer",
      "type": "smtp",
      "enabled": true,
      "host": "smtp.example.com",
      "port": 465,
      "secure": true,
      "service": null,
      "username": "user@example.com",
      "fromAddress": "noreply@example.com",
      "fromName": "My Blog",
      "allowedDomains": ["example.com"],
      "httpUrl": null,
      "httpMethod": null,
      "httpHeaders": null,
      "httpBody": null,
      "oauthClientId": null,
      "oauthAuthorizedAt": null,
      "createdAt": 1735000000000,
      "updatedAt": 1735000000000
    }

    type 取值:

    值说明必填字段
    smtp账号密码直连 SMTPhost 或 service、username、password
    http转发到自定义 HTTP APIhttpUrl
    outlook_oauth2Outlook OAuth2 授权后 SMTP 发件username、oauthClientId、oauthClientSecret
    gmail_oauth2Gmail OAuth2 授权后 SMTP 发件username、oauthClientId、oauthClientSecret

    smtp 类型的 service 为 nodemailer 预置服务名(如 QQ、Gmail、Outlook),填写后无需再设 host / port。 你可以在这里查看所有支持的运营商。

    接口返回的 password / oauthClientSecret 字段为解密后的明文,仅用于后台回显,请勿记录到外部日志。 oauthRefreshToken 由 OAuth 回调写入,不通过本接口修改。

    密钥

    GET    /api/admin/senders/{id}/keys                → { keys: SenderKey[] }
    POST   /api/admin/senders/{id}/keys  body: { "label"?: "..." }  → { key: SenderKey }
    PATCH  /api/admin/senders/{id}/keys/{keyId} body: { "label"?, "enabled"? } → { key: SenderKey }
    DELETE /api/admin/senders/{id}/keys/{keyId}        → { success: true }

    SenderKey 字段:

    {
      "id": "uuid",
      "senderId": "uuid",
      "key": "32-char-plain-key",
      "label": "production",
      "enabled": true,
      "lastUsedAt": 1735000000000,
      "createdAt": 1735000000000
    }

    日志与统计

    GET /api/admin/senders/{id}/logs?limit=50   → { rows: SendLog[], total: number }
    GET /api/admin/stats                        → { senders, logs: { total, success, failed } }

    测试发信

    POST /api/admin/senders/{id}/test  body: { "to": "..." }  → { success: true, messageId }

    用发件商自身的 SMTP 配置发一封测试邮件,同样受其域名白名单限制。

    健康检查

    GET /api/health → { status, driver, adminConfigured, secretConfigured, timestamp }

    无需鉴权,可用于部署后自检。