# 草稿与发送

Source: https://docs.simail.ai/zh/sending/

> 发送、回复、回复全部、转发和草稿；幂等、发送前检查、审批、定时和发送状态。

agent 从不持有发信凭据。每封外发信都提交给 simail 的**放行服务**，那是唯一能发信的组件。它检查邮件、套用组织策略、在策略要求时等人批准，并在信离开前立刻再做一次最终检查。

simail 用于预期中的事务邮件。冷外联和群发不允许；见[可接受使用政策](https://simail.ai/aup)。

## 端点

| 方法与路径 | 权限 |
|---|---|
| `POST /v0/inboxes/{inbox_id}/messages/send` | `message_send` |
| `POST /v0/inboxes/{inbox_id}/messages/{message_id}/reply` | `message_send` |
| `POST /v0/inboxes/{inbox_id}/messages/{message_id}/reply-all` | `message_send` |
| `POST /v0/inboxes/{inbox_id}/messages/{message_id}/forward` | `message_send` |
| `GET`、`POST /v0/inboxes/{inbox_id}/drafts`；`GET`、`PATCH`、`DELETE …/drafts/{draft_id}` | `message_read`、`draft_write` |
| `POST /v0/inboxes/{inbox_id}/drafts/{draft_id}/attachments` | `draft_write` |
| `POST /v0/inboxes/{inbox_id}/drafts/{draft_id}/send` | `message_send` |
| `GET /v0/sends/{send_id}` | `message_read` |
| `DELETE /v0/sends/{send_id}`（取消） | `message_send` |
| `GET /v0/approvals`、`GET /v0/approvals/{approval_id}` | `approval_read` |

## 请求

```http
POST /v0/inboxes/shop-helper@simail.email/messages/send
Authorization: Bearer $SIMAIL_API_KEY
Idempotency-Key: order-1042-shipped
Content-Type: application/json

{
  "to": ["ada@example.com"],
  "subject": "Your order shipped",
  "text": "Hi Ada, your order #1042 shipped today.",
  "labels": ["orders"]
}
```

| 字段 | 说明 |
|---|---|
| `to`、`cc`、`bcc` | 合计最多 50 个收件人；`bcc` 仅在策略允许时 |
| `subject` | |
| `text`、`html` | 至少其一；总是带上 `text` |
| `attachments` | `[{ "filename", "content_type", "content" }]`，`content` 为 base64，或 `{ "draft_attachment_id" }`；最多 32 个 |
| `labels` | 已发送副本上的标签 |
| `send_at` | 最多提前 30 天的 ISO 8601 时间；大约在该时间的 2 分钟内发出 |
| `reply_to` | 忽略：simail 自己设置 Reply-To，以便回复能归线程 |
| `headers` | 拒绝，除了 `X-Simail-Client-Ref` |
| `track_opens` | 忽略：simail 不追踪打开或点击 |

带头里有 CR、LF、NUL 或其他控制字符的字段，以 `422 invalid_header` 拒绝。

### 回复

`reply` 的收件人取自原信的 **From**（从不取 Reply-To）。`reply-all` 加上原来的 To 和 Cc，去掉你自己的地址。主题加上 `Re:` 或 `Fwd:`，线程头由 simail 设置。你可以传 `expected_recipients`；如果和 simail 推导的收件人不同，发送会被拦住，以免一次回复悄悄变成群发。转发发给新收件人，所以转发算首次联系。

### 体积

整封外发信，包括头、正文、附件和编码开销，最多 **5 MiB**（原始附件大约 3.5 MiB），附件最多 **32** 个。更大的信返回 `413 message_too_large`，带 `limit_bytes` 和 `estimated_bytes`。带内联附件的发送请求体限 5 MiB，否则 1 MiB。

## 幂等

完整规则见[幂等与重复](/zh/idempotency/)。简言之：每次发送（`send`、`reply`、`reply-all`、`forward`、草稿 `send`）都**必须**带 `Idempotency-Key`。键的作用域是你的组织和你的 key。同一把键、同一份正文返回原来的结果；同一把键、不同正文返回 `409 idempotency_conflict`。超时后用同一把键重试不会发两次。

## 响应

`202 Accepted`：

```json
{ "send_id": "out_…", "message_id": "msg_…", "thread_id": "thr_…", "status": "pending_approval", "flags": ["first_contact"] }
```

| `status` | 含义 |
|---|---|
| `sent` | 已交给邮件网络 |
| `sending` | 正在发送 |
| `scheduled` | 等待 `send_at` |
| `pending_approval` | 等人（见下） |
| `blocked` | 拒绝；以 `422 send_blocked` 返回，带 `reasons` |

之后的状态在 `GET /v0/sends/{send_id}`：`approved`、`rejected`、`expired`、`cancelled`、`failed`，以及 `outcome_unknown`（可能发出也可能没有；simail 不会自动重发，等投递事件到来再对账）。

信处于 `scheduled`、`pending_approval` 或 `approved` 时，用 `DELETE /v0/sends/{send_id}` 取消。已经在发或已终态时，取消返回 `409 conflict`，`reason` 为 `"already_sending"` 或 `"already_final"`。删除已提交的草稿会先取消它。

## 发送前检查

**拦住的原因**（`reasons`）：`sender_mismatch`、`empty_body`、`placeholder`（例如 `{{`、`[NAME]`、`TODO`、lorem ipsum）、`too_many_recipients`、`body_too_large`、`attachment_too_large`、`attachment_not_allowed`、`invalid_address`、`invalid_header`、`suppressed`（地址硬退信或被投诉）、`blocked_recipient`、`duplicate`、`loop_auto_reply`、`loop_thread`、`loop_peer`、`card_number`、`credential`、`expected_recipients_mismatch`、`thread_locked`、`first_contact_blocked`、`message_too_large`、`principal_revoked`、`policy_changed`、`daily_limit_at_send`、`platform_hard_cap`。

**风险旗标**（`flags`，给审批人看）：`first_contact`、`punycode`、`lookalike_domain`、`cross_thread_echo`（邮件复用了你在其他线程读到的内容）、`has_links`、`has_attachments`、`bcc`、`credential_like`、`large_recipient_set`、`new_recipient_domain`、`recipient_unverified`。

**重复和循环。** 去重窗口内内容相同的信（同一发件人、收件人、主题和正文）返回 `409 duplicate_send`。回复自动回复、退信或其他 simail agent 的信会被拦住，超过往来限额的线程和对端也会，所以两个 agent 不能永远互发。

**最终检查。** 定时、已批准或延迟的信发出之前，simail 重查当前状态：平台或组织暂停、已吊销的 key、已删除或暂停的邮箱、线程锁、抑制和拦截名单、当前策略和今天的限额。不再通过的信被留下或拦住；不会凭过期的批准发出。

## 策略和审批

细节：[审批与发信策略](/zh/approvals/)。策略由人在控制台按组织、pod、邮箱或 key 设置；每一层只能比上一层更严。主要设置：

- `approval.mode`：`none`、`first_contact`、`risky`（任何旗标）、`first_contact_and_risky`、`all`。
- `first_contact`：对还不是该邮箱联系人的收件人，`allow`、`approval` 或 `block`。
- 组织、邮箱、key 和收件人的每日限额，加上每线程每小时限额。
- 是否允许 `bcc`、外发附件和链接。

需要批准时，审批人在控制台（如果接上了，也在 Telegram、Slack 或邮件）看到一张卡：完整收件人列表、主题、正文开头、附件和旗标。批准绑定确切内容：内容变了，批准就不再适用。批准默认 24 小时后过期。agent 可以读审批状态（`GET /v0/approvals`），但永远不能批准。

## 署名和头

外发信署 **simail.ai**：一行页脚 `— Sent by an AI agent via simail.ai`，显示名后加 `" via SiMail"`。信带 `Auto-Submitted` 头，让其他系统知道这是自动的。simail 不加追踪像素，也不加远程图片。

## 投递事件和抑制

投递、退信、投诉和拒绝事件来自发信网络，报告为 `message.delivered`、`message.bounced`、`message.complained` 和 `message.rejected`。硬退信和投诉会把地址加进抑制名单。如果一个组织 7 天硬退信率达到 2%，或投诉率达到 0.1%（至少 50 封之后），该组织的发送暂停（`403 account_suspended`，收信继续），直到人在控制台恢复。
