# 审批与发信策略

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

> 发信策略怎样分层合并、什么时候必须由人批准、审批人看到什么，以及 agent 能观察到什么。

每封外发信都由放行服务对照组织的**发信策略**检查。策略决定立刻发出、等一个人批准，还是拦住。人在控制台里改策略（要再次验证）；agent 能看到效果，但不能改。

## 分层：每一层只能更严

策略设在五层，从上往下合并：

**平台 → 组织 → pod → 邮箱 → key**

下一层只能让结果更严，不能更松。「更严」按字段定义，所以合并是可预期的：

| 字段 | 更严是指 |
|---|---|
| `limits.*`、`approval.ttl_minutes`、`attachments.max_total_bytes`、`injection.hold_threshold`、`loop_guard.max_exchanges_*`、`inbound.wake.*` | 更小的数 |
| `dedupe.window_minutes`、`loop_guard.window_hours` | 更大的数 |
| `recipients.allow_bcc`、`attachments.allow_outbound`、`links.allow` | `false` 赢 |
| `content.block_*`、`recipients.block_punycode`、`loop_guard.block_reply_to_auto_submitted`、`llm_injection_scoring`、`branding.footer` | `true` 赢 |
| `approval.mode` | `none` < `first_contact` < `risky` < `first_contact_and_risky` < `all` |
| `first_contact` | `allow` < `approval` < `block` |
| `approval.approvers` | 由组织设置；下层只能减人 |

## 策略文档

```json
{
  "approval": { "mode": "first_contact_and_risky", "channels": ["console", "telegram", "slack", "email_reply"], "ttl_minutes": 1440, "approvers": ["usr_…"] },
  "first_contact": "approval",
  "limits": { "daily_recipients": 100, "inbox_daily_recipients": 200, "key_daily_recipients": 200, "per_thread_per_hour": 10, "per_recipient_per_day": 20, "max_recipients_per_message": 50 },
  "dedupe": { "window_minutes": 1440 },
  "loop_guard": { "block_reply_to_auto_submitted": true, "max_exchanges_per_thread_per_day": 20, "max_exchanges_per_peer_per_day": 40, "window_hours": 24 },
  "content": { "block_credentials": false, "block_card_numbers": true, "block_empty": true, "block_placeholders": true },
  "recipients": { "allow_bcc": false, "block_punycode": false },
  "attachments": { "allow_outbound": true, "max_total_bytes": 3670016 },
  "links": { "allow": true },
  "branding": { "footer": true, "display_name_suffix": true },
  "t0": { "stranger_thread": "approval", "auto_per_thread_per_day": 3, "thread_token_ttl_days": 30 },
  "inbound": { "wake": { "stranger_daily": 50, "per_sender_hourly": 5 } },
  "injection": { "hold_threshold": 0.7 },
  "llm_injection_scoring": false
}
```

这是新组织的默认值。组织能选的最松审批模式是 `first_contact_and_risky`；没有 `none`。

## 什么时候要批准

| `approval.mode` | 人要批准 |
|---|---|
| `first_contact` | 发给还不是该邮箱联系人的人 |
| `risky` | 带任何风险旗标的信 |
| `first_contact_and_risky` | 上面两种都要（默认） |
| `all` | 每一封 |

与模式无关的还有：

- `first_contact: block` 直接拒绝首次联系（`first_contact_blocked`）。
- **陌生人发起的线程**里每一次回复都要批准（`t0.stranger_thread`），除非人把发件人升成联系人。
- 每个线程每天最多 `t0.auto_per_thread_per_day` 封可以不经批准发出；其余等人。
- 复用了 agent 在*其他*线程里读到的内容（`cross_thread_echo`）要批准。这是提示注入外泄的典型形状。
- 转发给新收件人算首次联系。

给审批人看的**风险旗标**：`first_contact`、`punycode`、`lookalike_domain`、`cross_thread_echo`、`has_links`、`has_attachments`、`bcc`、`credential_like`、`large_recipient_set`、`new_recipient_domain`、`recipient_unverified`。

**联系人。** 邮箱先写给某人且对方回了，或人在控制台里提升他们，他们就成为该邮箱的联系人。

## 审批人看到什么、怎样决定

审批卡显示发件人、放行服务将要发送的**每一个信封收件人**、主题、正文开头 2,000 个字符、附件名和大小、风险旗标、提交用的 key，以及控制台里该线程的链接。

审批人可以在这些地方决定：

- **控制台**（审批人、所有者和管理员；5 分钟内再次验证），
- **Telegram** 或 **Slack**，在人于控制台接上之后，
- **邮件**：在审批请求的第一行回复 `APPROVE` 或 `REJECT`（只能来自审批人已验证的地址，并且 DKIM 对齐）。

批准绑定确切内容。请求之后内容变了，批准就不再适用。每次批准只能决定一次。未决定的批准在 `approval.ttl_minutes`（默认 24 小时）后**过期**，信不会发出。

## agent 看到什么

agent 从不批准。他们可以跟踪结果：

- 发送响应说 `status: "pending_approval"`，并带 `flags`；
- `GET /v0/sends/{send_id}` 会变成 `approved`（然后 `sending`、`sent`）、`rejected`、`expired` 或 `cancelled`（[发送](/zh/api/sends/)）；
- `GET /v0/approvals` 和 `GET /v0/approvals/{approval_id}` 只返回元数据（[审批 API](/zh/api/approvals/)）；`approval.requested` 和 `approval.decided` [事件](/zh/event-types/) 报告变化。

等批准的 agent 不要用新的幂等键重发；那会再开一次批准，批准后就是重复的一封。

## 最后检查

批准不是最后一步。已批准或已定时的信离开之前，放行服务重读当前状态：暂停、已吊销的 key、已删除或暂停的邮箱、线程锁、抑制名单和拦截名单、当前策略和今天的限额。不再通过的信会等待或被拦住（`policy_changed`、`principal_revoked` 等）；不会凭过期的批准发出。

## 署名

外发信署 **simail.ai**：一行页脚 `— Sent by an AI agent via simail.ai`，显示名后面加 `" via SiMail"`。在 simail 邮件域上的每个组织都开着。
