#!/usr/bin/env bash set -euo pipefail ROOT="$(cd "$(dirname "$0")" && pwd)" REPO="${REPO:-$HOME/projects/cloudflare_temp_email}" WORKER_DIR="$REPO/worker" # shellcheck disable=SC1091 source "$ROOT/secrets.env" DOMAIN="${DOMAIN:-zhangyunuo.net}" WORKER_NAME="${WORKER_NAME:-temp-email-zhangyunuo}" D1_NAME="${D1_NAME:-temp-email-zhangyunuo}" ADMIN_PASSWORD="${ADMIN_PASSWORD:?ADMIN_PASSWORD missing in secrets.env}" JWT_SECRET="${JWT_SECRET:?JWT_SECRET missing in secrets.env}" cd "$WORKER_DIR" export PATH="$WORKER_DIR/node_modules/.bin:$PATH" if ! command -v wrangler >/dev/null 2>&1; then echo "[!] wrangler 不在 PATH,尝试 pnpm exec" WR="pnpm exec wrangler" else WR="wrangler" fi if [ -z "${CLOUDFLARE_API_TOKEN:-}" ]; then # no token: require interactive oauth session if ! $WR whoami 2>/dev/null | grep -qiE 'Account Name|Account ID|email:'; then echo "[!] 未登录 Cloudflare,且未设置 CLOUDFLARE_API_TOKEN" echo " 方式 A(交互): cd $WORKER_DIR && pnpm exec wrangler login" echo " 方式 B(推荐服务器): export CLOUDFLARE_API_TOKEN=你的token" echo " Token 创建: https://dash.cloudflare.com/profile/api-tokens" echo " 权限至少: Account.D1 Edit + Account.Workers Scripts Edit + Account.Workers KV Storage Edit(可选)" exit 1 fi else echo "[*] 使用 CLOUDFLARE_API_TOKEN 部署" fi echo "[*] 创建/查找 D1: $D1_NAME" CREATE_OUT=$($WR d1 create "$D1_NAME" 2>&1 || true) echo "$CREATE_OUT" DB_ID="" if echo "$CREATE_OUT" | grep -q "database_id"; then DB_ID=$(echo "$CREATE_OUT" | sed -n 's/.*database_id *= *"\([^"]*\)".*/\1/p' | head -1) if [ -z "$DB_ID" ]; then DB_ID=$(echo "$CREATE_OUT" | sed -n 's/.*database_id = \([a-f0-9-]*\).*/\1/p' | head -1) fi fi if [ -z "$DB_ID" ]; then DB_ID=$($WR d1 list --json 2>/dev/null | python3 -c ' import sys, json name = sys.argv[1] data = json.load(sys.stdin) items = data if isinstance(data, list) else data.get("result", data.get("databases", [])) print(next((str(x.get("uuid") or x.get("id") or "") for x in items if x.get("name") == name), ""), end="") ' "$D1_NAME" || true) fi if [ -z "$DB_ID" ]; then echo "[!] 无法解析 database_id,请检查 wrangler 登录权限后重试" exit 1 fi echo "[+] D1 id=$DB_ID" python3 - "$DOMAIN" "$WORKER_NAME" "$D1_NAME" "$DB_ID" "$ADMIN_PASSWORD" "$JWT_SECRET" <<'PY' from pathlib import Path import sys domain, name, db_name, db_id, admin, jwt = sys.argv[1:7] text = f'''name = "{name}" main = "src/worker.ts" compatibility_date = "2025-04-01" compatibility_flags = [ "nodejs_compat" ] keep_vars = true [vars] PREFIX = "" ADMIN_PASSWORDS = ["{admin}"] DEFAULT_DOMAINS = ["{domain}"] DOMAINS = ["{domain}"] JWT_SECRET = "{jwt}" BLACK_LIST = "" ENABLE_USER_CREATE_EMAIL = true ENABLE_USER_DELETE_EMAIL = true ENABLE_AUTO_REPLY = false DEFAULT_LANG = "zh" TITLE = "Temp Mail" [[d1_databases]] binding = "DB" database_name = "{db_name}" database_id = "{db_id}" ''' Path("wrangler.toml").write_text(text, encoding="utf-8") print("wrote wrangler.toml") PY echo "[*] 初始化 schema" $WR d1 execute "$D1_NAME" --remote --file=../db/schema.sql echo "[*] 执行 patches" for f in ../db/*.sql; do base=$(basename "$f") [ "$base" = "schema.sql" ] && continue echo " -> $base" $WR d1 execute "$D1_NAME" --remote --file="$f" || true done echo "[*] 部署 Worker" $WR deploy --minify echo echo "[+] 完成 Worker: $WORKER_NAME" echo "[+] Admin 密码见 $ROOT/secrets.env" echo "[+] 下一步: Cloudflare Email Routing catch-all -> $WORKER_NAME" echo "[+] 注册机配置示例:" cat <.workers.dev", "cloudflare_api_key": "${ADMIN_PASSWORD}", "cloudflare_auth_mode": "x-admin-auth", "cloudflare_path_accounts": "/admin/new_address", "cloudflare_path_messages": "/api/mails", "defaultDomains": "${DOMAIN}" } CFG