# 通知管道

手機連線步驟見[連接 App](connect-app.md)。

## 在控制台設定

1. 開啟**通知**，選擇 Bark、Pushover、Webhook 或 Mailwake App。
2. 填寫下方對應管道的欄位。使用 Mailwake App 時先[配對手機](connect-app.md)，再選定接收手機。
3. 設定預覽、通知語言和重試次數。重試次數為 0 時只嘗試一次。
4. 儲存後明確點選傳送測試通知，檢查手機或 Webhook 接收端，並檢視投遞結果。

這些設定對所有信箱生效。已入隊任務按已有投遞計劃處理，修改後的行為請用一封新郵件驗證。

## 通道設定

透過 `/api/v1/settings/delivery` 攜帶當前 `revision` 設定全域性通道。通道、預覽、重試次數和通知語言對所有信箱生效。憑據加密且只寫；目標保持原值時，省略憑據欄位可保留已存值；修改 Bark 位址須重新輸入裝置 Key。

| 通道       | 引數                                                                                | 憑據                                                    |
| ---------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------- |
| `bark`     | `bark.endpoint`，預設 `https://api.day.app`                                         | `bark.key`                                              |
| `native`   | 預設使用官方生產推播中繼服務；透過 `MAILWAKE_RELAY_URL` 覆蓋；在 App 授權中配對手機 | 本機生成並加密儲存的哨站身分                            |
| `pushover` | 無                                                                                  | `pushover.token`、`pushover.user`                       |
| `webhook`  | HTTPS，可帶查詢引數                                                                 | `webhook.url`、`webhook.secret`（至少 32 個非空白字元） |

Webhook URL 的路徑或查詢引數可能包含憑據，因此整個 URL 只寫。`preview` 僅支援 `off` 或 `subject`；`retry_count` 為 0–9，預設 0；`language` 支援 [9 種語言及其地區別名](api.md#語言與錯誤碼)，預設英文。`subject` 下 Bark/Pushover 內文只顯示主旨；Webhook 保留結構化的 sender 與 subject，message 只顯示主旨。`off` 或主旨為空時，內文使用所選通知語言的“收到新郵件”文案。標題保持 `{显示名称} · {文件夹}`，Bark group 使用同一個截斷後的標題；測試通知文案保持原值。API 輸入 `sender_subject` 返回 400 `config_preview_invalid`。第三方通道從 `subject` 切換為 `off` 時，同一事務清理所有待處理及失敗記錄的寄件者與主旨；後續入隊也遵循已儲存的預覽策略。原生通道始終記錄寄件者與主旨，並保留第三方預覽偏好。

Bark 的郵件通知和測試通知均按 Bark App 的歷史儲存設定保留記錄。

### Webhook 格式

哨站向設定的地址 `POST` JSON，不跟隨重新導向：

```json
{
  "version": 1,
  "id": "3f9c…",
  "test": false,
  "mailbox_id": "mbx_example",
  "account": "工作邮箱",
  "folder": "Clients",
  "sender": "anna@example.org",
  "subject": "Re: Q4 proposal",
  "received_at": "2026-09-28T10:32:00Z",
  "title": "工作邮箱 · Clients",
  "message": "Re: Q4 proposal"
}
```

`mailbox_id` 為穩定信箱 ID，`account` 為入隊時的顯示名稱。Bark、Pushover、Webhook 普通通知在所有支援語言中的標題統一為“{顯示名稱} · {資料夾}”。信箱改名或刪除後，已入隊任務保留原來的來源資訊。測試通知使用獨立文案並省略信箱欄位。

`sender`、`subject` 僅在 `subject` 預覽下出現；`title`、`message` 是已本機化的展示文字，可直接轉發給 ntfy、Gotify 等服務。關閉預覽後仍會傳送顯示名稱和資料夾，請使用適合提供給通知服務商的名稱。

| 請求頭                 | 含義                                                                      |
| ---------------------- | ------------------------------------------------------------------------- |
| `X-Mailwake-Event`     | 事件 ID，與內文 `id` 相同；重試時不變，可用於去重                         |
| `X-Mailwake-Timestamp` | 傳送時的 Unix 秒                                                          |
| `X-Mailwake-Signature` | `sha256=` 加 `HMAC-SHA256(secret, "<timestamp>.<原始正文>")` 的十六進位制 |

接收端用同一金鑰計算簽章並以常量時間比較，同時拒絕時間戳偏差超過 5 分鐘的請求：

```python
import hashlib, hmac, time

def verify(secret: bytes, timestamp: str, body: bytes, signature: str) -> bool:
    expected = "sha256=" + hmac.new(secret, timestamp.encode() + b"." + body, hashlib.sha256).hexdigest()
    return abs(time.time() - int(timestamp)) <= 300 and hmac.compare_digest(expected, signature)
```

返回任意 2xx 視為接收成功；429 與 5xx 按重試設定處理，其他狀態結束本輪並記錄失敗。

儲存通知設定只校驗欄位、地址、配對狀態與設定版本，直接儲存。需要驗證投遞時手動點選傳送測試通知。Native 測試使用推播中繼服務固定內容的免費測試介面，與 App 測試共享額度；正式郵件仍要求 Native Push 權益。
