Open-source Grok free registration CLI, xai_enroller auth pipeline, local auth service, tests and docs.
62 lines
2.5 KiB
JavaScript
62 lines
2.5 KiB
JavaScript
// ============================================================
|
|
// Cloudflare Email Worker — 把收到的邮件 POST 到你的 webhook
|
|
// 用于 grok-free-register 的「自建邮箱模式」(EMAIL_MODE=custom)
|
|
//
|
|
// 链路: 发件方 → Cloudflare Email Routing → 本 Worker → 你的 webhook(email_server.py)
|
|
//
|
|
// ⚠️ 重要(踩过的坑):env.WEBHOOK_URL 必须是【域名】,不能用【裸 IP】!
|
|
// Cloudflare Workers 的 fetch 不允许直接请求裸 IP,会返回
|
|
// "error code: 1003 (Direct IP access not allowed)" 并被静默吞掉
|
|
// —— Worker 看起来成功、你的服务器却收不到任何请求。
|
|
// 做法:给服务器 IP 加一条 DNS A 记录(如 hook.example.com,灰云/DNS-only),
|
|
// WEBHOOK_URL 填 http://hook.example.com:8080/webhook。
|
|
//
|
|
// 部署:
|
|
// npm create cloudflare@latest cf-mail-webhook
|
|
// cd cf-mail-webhook && npm i postal-mime
|
|
// # 用本文件替换 src/index.js
|
|
// npx wrangler secret put WEBHOOK_URL # 输入 http://hook.example.com:8080/webhook
|
|
// npx wrangler secret put WEBHOOK_TOKEN # 可选,鉴权用
|
|
// npx wrangler deploy
|
|
// 然后在 Cloudflare 后台:Email → Email Routing → Routing rules →
|
|
// Catch-all → 动作选「Send to a Worker」→ 选本 Worker。
|
|
// (子域名收信需在 Email Routing 单独启用该子域并配它自己的 catch-all。)
|
|
// ============================================================
|
|
import PostalMime from "postal-mime";
|
|
|
|
function trim(s, max = 20000) {
|
|
if (!s) return "";
|
|
return s.length > max ? s.slice(0, max) + "\n...[truncated]" : s;
|
|
}
|
|
|
|
export default {
|
|
async email(message, env, ctx) {
|
|
if (!env.WEBHOOK_URL) {
|
|
console.error("WEBHOOK_URL 未配置 (npx wrangler secret put WEBHOOK_URL)");
|
|
return;
|
|
}
|
|
const parsed = await PostalMime.parse(message.raw);
|
|
const payload = {
|
|
from: message.from,
|
|
to: message.to,
|
|
subject: parsed.subject || message.headers.get("subject") || "",
|
|
text: trim(parsed.text || ""),
|
|
html: trim(parsed.html || ""),
|
|
};
|
|
|
|
const headers = { "content-type": "application/json" };
|
|
if (env.WEBHOOK_TOKEN) headers["x-webhook-token"] = env.WEBHOOK_TOKEN;
|
|
|
|
const res = await fetch(env.WEBHOOK_URL, {
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify(payload),
|
|
});
|
|
// 日志只保留状态码,避免把 webhook 地址或上游响应写入 Worker 日志。
|
|
console.log(`webhook delivery -> ${res.status}`);
|
|
if (!res.ok) {
|
|
console.error(`webhook delivery failed: ${res.status}`);
|
|
}
|
|
},
|
|
};
|