Compare commits

..

10 Commits

Author SHA1 Message Date
Dream Hunter
e99acdcc6e fix: CI (#471) 2024-11-07 01:11:00 +08:00
Dream Hunter
8f30505706 feat: v0.7.6 (#470) 2024-11-07 01:00:26 +08:00
Dream Hunter
ddfa2c5d03 feat: add ENABLE_CHECK_JUNK_MAIL (#469) 2024-11-07 00:58:15 +08:00
Dream Hunter
49b3f10838 feat: upgrade dependencies && add ci build telegram-frontend.zip (#467) 2024-11-06 23:42:39 +08:00
Dream Hunter
cc9ac67319 feat: upgrade dependencies (#448) 2024-09-27 22:30:37 +08:00
Dream Hunter
7cc2a2b576 feat: doc: add mail id and url in webhook (#444) 2024-09-09 22:49:53 +08:00
Dream Hunter
393c5902c3 feat: add mail id and url in webhook (#443) 2024-09-09 22:29:18 +08:00
Dream Hunter
5ece49a576 feat: telegram Set manually to avoid implicit call in (#442) 2024-09-09 20:59:12 +08:00
dependabot[bot]
de80857e2c build(deps): bump twisted from 24.3.0 to 24.7.0 in /smtp_proxy_server (#385)
Bumps [twisted](https://github.com/twisted/twisted) from 24.3.0 to 24.7.0.
- [Release notes](https://github.com/twisted/twisted/releases)
- [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst)
- [Commits](https://github.com/twisted/twisted/compare/twisted-24.3.0...twisted-24.7.0)

---
updated-dependencies:
- dependency-name: twisted
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-27 01:40:45 +08:00
Dream Hunter
a57a42b2a1 fix: name check bug (#434) 2024-08-25 16:39:55 +08:00
28 changed files with 3291 additions and 2973 deletions

View File

@@ -30,7 +30,13 @@ jobs:
run: cd frontend && pnpm install --no-frozen-lockfile && pnpm build:release
- name: Zip Frontend dist
run: cd frontend/dist/ && zip -r frontend.zip *
run: cd frontend/dist/ && zip -r frontend.zip * && mv frontend.zip ../
- name: Build Telegram Frontend
run: cd frontend && pnpm install --no-frozen-lockfile && pnpm build:telegram:release
- name: Zip Telegram Frontend dist
run: cd frontend/dist/ && zip -r telegram-frontend.zip * && mv telegram-frontend.zip ../
- name: cp wrangler.toml
run: cd worker && cp wrangler.toml.template wrangler.toml
@@ -42,5 +48,6 @@ jobs:
uses: softprops/action-gh-release@v2
with:
files: |
frontend/dist/frontend.zip
frontend/frontend.zip
frontend/telegram-frontend.zip
worker/dist/worker.js

View File

@@ -1,6 +1,16 @@
<!-- markdownlint-disable-file MD004 MD024 MD034 MD036 -->
# CHANGE LOG
## v0.7.6
- feat: 支持提前设置 bot info, 降低 telegram 回调延迟 (#441)
- feat: 增加 telegram mini app 的 build 压缩包
- feat: 增加是否启用垃圾邮件检查 `ENABLE_CHECK_JUNK_MAIL` 配置
## v0.7.5
- fix: 修复 `name` 的校验检查
## v0.7.4
- feat: UI 列表页面增加最小宽度

View File

@@ -1,6 +1,6 @@
{
"name": "cloudflare_temp_email",
"version": "0.7.4",
"version": "0.7.6",
"private": true,
"type": "module",
"scripts": {
@@ -9,6 +9,7 @@
"build:release": "vite build -m example --emptyOutDir",
"build:pages": "vite build -m pages --emptyOutDir",
"build:telegram": "VITE_IS_TELEGRAM=true vite build -m prod --emptyOutDir",
"build:telegram:release": "VITE_IS_TELEGRAM=true vite build -m example --emptyOutDir",
"preview": "vite preview",
"deploy:telegram": "npm run build:telegram && wrangler pages deploy ./dist --branch production",
"deploy:actions:telegram": "npm run build:telegram && wrangler pages deploy ./dist",
@@ -18,32 +19,32 @@
},
"dependencies": {
"@simplewebauthn/browser": "^10.0.0",
"@unhead/vue": "^1.9.16",
"@unhead/vue": "^1.11.11",
"@vicons/material": "^0.12.0",
"@vueuse/core": "^10.11.1",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.7.3",
"axios": "^1.7.7",
"jszip": "^3.10.1",
"mail-parser-wasm": "^0.1.8",
"naive-ui": "^2.39.0",
"postal-mime": "^2.2.7",
"naive-ui": "^2.40.1",
"postal-mime": "^2.3.2",
"vooks": "^0.2.12",
"vue": "^3.4.37",
"vue": "^3.5.12",
"vue-clipboard3": "^2.0.0",
"vue-i18n": "^9.13.1",
"vue-router": "^4.4.3"
"vue-i18n": "^9.14.1",
"vue-router": "^4.4.5"
},
"devDependencies": {
"@vicons/fa": "^0.12.0",
"@vitejs/plugin-vue": "^5.1.2",
"unplugin-auto-import": "^0.18.2",
"@vitejs/plugin-vue": "^5.1.4",
"unplugin-auto-import": "^0.18.3",
"unplugin-vue-components": "^0.27.4",
"vite": "^5.4.0",
"vite": "^5.4.10",
"vite-plugin-pwa": "^0.19.8",
"vite-plugin-top-level-await": "^1.4.4",
"vite-plugin-wasm": "^3.3.0",
"workbox-window": "^7.1.0",
"wrangler": "^3.70.0"
"workbox-window": "^7.3.0",
"wrangler": "^3.84.1"
}
}

2807
frontend/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
<script setup>
import { defineAsyncComponent } from 'vue'
import { defineAsyncComponent, onMounted, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRoute } from 'vue-router'
import { useGlobalState } from '../store'
import { api } from '../api'
@@ -17,6 +18,7 @@ import About from './common/About.vue';
const SendMail = defineAsyncComponent(() => import('./index/SendMail.vue'));
const { settings, openSettings, indexTab, globalTabplacement } = useGlobalState()
const message = useMessage()
const route = useRoute()
const { t } = useI18n({
messages: {
@@ -30,6 +32,7 @@ const { t } = useI18n({
s3Attachment: 'S3 Attachment',
saveToS3Success: 'save to s3 success',
webhookSettings: 'Webhook Settings',
query: 'Query',
},
zh: {
mailbox: '收件箱',
@@ -41,11 +44,17 @@ const { t } = useI18n({
s3Attachment: 'S3附件',
saveToS3Success: '保存到s3成功',
webhookSettings: 'Webhook 设置',
query: '查询',
}
}
});
const fetchMailData = async (limit, offset) => {
if (mailIdQuery.value > 0) {
const singleMail = await api.fetch(`/api/mail/${mailIdQuery.value}`);
if (singleMail) return { results: [singleMail], count: 1 };
return { results: [], count: 0 };
}
return await api.fetch(`/api/mails?limit=${limit}&offset=${offset}`);
};
@@ -80,6 +89,30 @@ const saveToS3 = async (mail_id, filename, blob) => {
message.error(error.message || "save to s3 error");
}
}
const mailBoxKey = ref("")
const mailIdQuery = ref("")
const showMailIdQuery = ref(false)
const queryMail = () => {
mailBoxKey.value = Date.now();
}
watch(route, () => {
if (!route.query.mail_id) {
showMailIdQuery.value = false;
mailIdQuery.value = "";
queryMail();
}
})
onMounted(() => {
if (route.query.mail_id) {
showMailIdQuery.value = true;
mailIdQuery.value = route.query.mail_id;
queryMail();
}
})
</script>
<template>
@@ -87,9 +120,17 @@ const saveToS3 = async (mail_id, filename, blob) => {
<AddressBar />
<n-tabs v-if="settings.address" type="card" v-model:value="indexTab" :placement="globalTabplacement">
<n-tab-pane name="mailbox" :tab="t('mailbox')">
<MailBox :showEMailTo="false" :showReply="true" :showSaveS3="openSettings.isS3Enabled" :saveToS3="saveToS3"
:enableUserDeleteEmail="openSettings.enableUserDeleteEmail" :fetchMailData="fetchMailData"
:deleteMail="deleteMail" />
<div v-if="showMailIdQuery" style="margin-bottom: 10px;">
<n-input-group>
<n-input v-model:value="mailIdQuery" />
<n-button @click="queryMail" type="primary" tertiary>
{{ t('query') }}
</n-button>
</n-input-group>
</div>
<MailBox :key="mailBoxKey" :showEMailTo="false" :showReply="true" :showSaveS3="openSettings.isS3Enabled"
:saveToS3="saveToS3" :enableUserDeleteEmail="openSettings.enableUserDeleteEmail"
:fetchMailData="fetchMailData" :deleteMail="deleteMail" />
</n-tab-pane>
<n-tab-pane name="sendbox" :tab="t('sendbox')">
<SendBox :fetchMailData="fetchSenboxData" :enableUserDeleteEmail="openSettings.enableUserDeleteEmail"

View File

@@ -1,6 +1,6 @@
{
"name": "temp-email-pages",
"version": "0.7.4",
"version": "0.7.6",
"description": "",
"main": "index.js",
"scripts": {
@@ -11,6 +11,6 @@
"author": "",
"license": "ISC",
"devDependencies": {
"wrangler": "^3.71.0"
"wrangler": "^3.84.1"
}
}

View File

@@ -1,5 +1,5 @@
aiosmtpd==1.4.6
pydantic-settings==2.2.1
requests==2.32.0
twisted==24.3.0
twisted==24.7.0
httpx==0.27.0

View File

@@ -61,8 +61,8 @@ pnpm run deploy
```toml
name = "cloudflare_temp_email"
main = "src/worker.ts"
compatibility_date = "2023-08-14"
node_compat = true
compatibility_date = "2024-09-23"
compatibility_flags = [ "nodejs_compat" ]
# enable cron if you want set auto clean up
# [triggers]
@@ -124,8 +124,14 @@ ENABLE_AUTO_REPLY = false
# CF_TURNSTILE_SECRET_KEY = ""
# telegram bot
# TG_MAX_ADDRESS = 5
# telegram bot info, predefined bot info can reduce latency of the webhook
# TG_BOT_INFO = "{}"
# global forward address list, if set, all emails will be forwarded to these addresses
# FORWARD_ADDRESS_LIST = ["xxx@xxx.com"]
# Frontend URL
# FRONTEND_URL = "https://xxxx.xxx"
# Enable check junk mail
# ENABLE_CHECK_JUNK_MAIL = false
[[d1_databases]]
binding = "DB"

View File

@@ -25,7 +25,9 @@ wrangler kv:namespace create DEV
```toml
name = "cloudflare_temp_email"
main = "src/worker.ts"
compatibility_date = "2023-12-01"
compatibility_date = "2024-09-23"
compatibility_flags = [ "nodejs_compat" ]
# 如果你想使用自定义域名,你需要添加 routes 配置
# routes = [
# { pattern = "temp-email-api.xxxxx.xyz", custom_domain = true },
@@ -95,8 +97,14 @@ ENABLE_AUTO_REPLY = false
# CF_TURNSTILE_SECRET_KEY = ""
# telegram bot 最多绑定邮箱数量
# TG_MAX_ADDRESS = 5
# telegram BOT_INFO预定义的 BOT_INFO 可以降低 webhook 的延迟
# TG_BOT_INFO = "{}"
# 全局转发地址列表,如果不配置则不启用,启用后所有邮件都会转发到列表中的地址
# FORWARD_ADDRESS_LIST = ["xxx@xxx.com"]
# 前端地址,用于发送 webhook 的邮件 url
# FRONTEND_URL = "https://xxxx.xxx"
# 是否启用垃圾邮件检查
# ENABLE_CHECK_JUNK_MAIL = false
# D1 数据库的名称和 ID 可以在 cloudflare 控制台查看
[[d1_databases]]

View File

@@ -25,3 +25,20 @@
## 某个邮箱配置 webhook
![telegram](/feature/address-webhook.png)
## webhook 数据格式
要获取 url 需要配置 worker 的 `FRONTEND_URL` 为你的前端地址,或者你可以通过 `id` 自己拼接 url = `${FRONTEND_URL}?mail_id=${id}`
```json
{
"id": "${id}",
"url": "${url}",
"from": "${from}",
"to": "${to}",
"subject": "${subject}",
"raw": "${raw}",
"parsedText": "${parsedText}",
"parsedHtml": "${parsedHtml}",
}
```

View File

@@ -1,12 +1,12 @@
{
"name": "temp-mail-docs",
"private": true,
"version": "0.7.4",
"version": "0.7.6",
"type": "module",
"devDependencies": {
"@types/node": "^22.3.0",
"vitepress": "^1.3.2",
"wrangler": "^3.71.0"
"@types/node": "^22.9.0",
"vitepress": "^1.5.0",
"wrangler": "^3.84.1"
},
"scripts": {
"dev": "vitepress dev docs",

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cloudflare_temp_email",
"version": "0.7.4",
"version": "0.7.6",
"private": true,
"type": "module",
"scripts": {
@@ -11,21 +11,21 @@
"build": "wrangler deploy --dry-run --outdir dist --minify"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20240806.0",
"@cloudflare/workers-types": "^4.20241022.0",
"@eslint/js": "8.56.0",
"@simplewebauthn/types": "^10.0.0",
"eslint": "8.56.0",
"globals": "^15.9.0",
"globals": "^15.12.0",
"typescript-eslint": "^7.18.0",
"wrangler": "^3.70.0"
"wrangler": "^3.84.1"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.629.0",
"@aws-sdk/s3-request-presigner": "^3.629.0",
"@aws-sdk/client-s3": "^3.685.0",
"@aws-sdk/s3-request-presigner": "^3.685.0",
"@simplewebauthn/server": "^10.0.1",
"hono": "^4.5.5",
"hono": "^4.6.9",
"mimetext": "^3.0.24",
"postal-mime": "^2.2.7",
"postal-mime": "^2.3.2",
"resend": "^3.5.0",
"telegraf": "4.16.3"
},

1809
worker/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -22,12 +22,14 @@ async function saveWebhookSettings(c: Context<HonoCustomType>): Promise<Response
async function testWebhookSettings(c: Context<HonoCustomType>): Promise<Response> {
const settings = await c.req.json<WebhookSettings>();
// random raw email
const raw = await c.env.DB.prepare(
`SELECT raw FROM raw_mails ORDER BY RANDOM() LIMIT 1`
).first<string>("raw");
const { id: mailId, raw } = await c.env.DB.prepare(
`SELECT id, raw FROM raw_mails ORDER BY RANDOM() LIMIT 1`
).first<{ id: string, raw: string }>() || {};
const parsedEmail = await commonParseMail(raw);
const res = await sendWebhook(settings, {
id: mailId || "0",
url: c.env.FRONTEND_URL ? `${c.env.FRONTEND_URL}?mail_id=${mailId}` : "",
from: parsedEmail?.sender || "test@test.com",
to: "admin@test.com",
subject: parsedEmail?.subject || "test subject",

View File

@@ -40,7 +40,8 @@ export default {
"S3_ENABLED": isS3Enabled(c),
"VERSION": CONSTANTS.VERSION,
"DISABLE_SHOW_GITHUB": !getBooleanValue(c.env.DISABLE_SHOW_GITHUB),
"DISABLE_ADMIN_PASSWORD_CHECK": getBooleanValue(c.env.DISABLE_ADMIN_PASSWORD_CHECK)
"DISABLE_ADMIN_PASSWORD_CHECK": getBooleanValue(c.env.DISABLE_ADMIN_PASSWORD_CHECK),
"ENABLE_CHECK_JUNK_MAIL": getBooleanValue(c.env.ENABLE_CHECK_JUNK_MAIL),
})
}
}

View File

@@ -134,15 +134,16 @@ const checkNameBlockList = async (
c: Context<HonoCustomType>, name: string
): Promise<void> => {
// check name block list
const blockList = [] as string[];
try {
const value = await getJsonSetting(c, CONSTANTS.ADDRESS_BLOCK_LIST_KEY);
const blockList = (value || []) as string[];
if (blockList.some((item) => name.includes(item))) {
throw new Error(`Name[${name}]is blocked`);
}
blockList.push(...(value || []));
} catch (error) {
console.error(error);
}
if (blockList.some((item) => name.includes(item))) {
throw new Error(`Name[${name}]is blocked`);
}
}
export const cleanup = async (
@@ -259,7 +260,8 @@ export const commonParseMail = async (raw_mail: string | undefined | null): Prom
sender: string,
subject: string,
text: string,
html: string
html: string,
headers?: Record<string, string>[]
} | undefined> => {
if (!raw_mail) {
return undefined;
@@ -286,6 +288,7 @@ export const commonParseMail = async (raw_mail: string | undefined | null): Prom
subject: parsedEmail.subject || "",
text: parsedEmail.text || "",
html: parsedEmail.html || "",
headers: parsedEmail.headers || [],
};
}
catch (e) {
@@ -338,6 +341,7 @@ export async function sendWebhook(settings: WebhookSettings, formatMap: WebhookM
);
/* eslint-enable no-useless-escape */
}
console.log("send webhook", settings.url, settings.method, settings.headers, body);
const response = await fetch(settings.url, {
method: settings.method,
headers: JSON.parse(settings.headers),
@@ -353,7 +357,8 @@ export async function sendWebhook(settings: WebhookSettings, formatMap: WebhookM
export async function triggerWebhook(
c: Context<HonoCustomType>,
address: string,
raw_mail: string
raw_mail: string,
message_id: string | null
): Promise<void> {
if (!c.env.KV || !getBooleanValue(c.env.ENABLE_WEBHOOK)) {
return
@@ -381,8 +386,14 @@ export async function triggerWebhook(
if (webhookList.length === 0) {
return
}
const mailId = await c.env.DB.prepare(
`SELECT id FROM raw_mails where address = ? and message_id = ?`
).bind(address, message_id).first<string>("id");
const parsedEmail = await commonParseMail(raw_mail);
const webhookMail = {
id: mailId || "",
url: c.env.FRONTEND_URL ? `${c.env.FRONTEND_URL}?mail_id=${mailId}` : "",
from: parsedEmail?.sender || "",
to: address,
subject: parsedEmail?.subject || "",

View File

@@ -1,5 +1,5 @@
export const CONSTANTS = {
VERSION: 'v0.7.4',
VERSION: 'v0.7.6',
// DB settings
ADDRESS_BLOCK_LIST_KEY: 'address_block_list',

View File

@@ -0,0 +1,44 @@
import { Bindings } from "../types";
import { getBooleanValue } from "../utils";
import { commonParseMail } from "../common";
export const check_if_junk_mail = async (
env: Bindings, address: string,
raw_mail: string, message_id: string | null
): Promise<boolean> => {
if (!getBooleanValue(env.ENABLE_CHECK_JUNK_MAIL)) {
return false;
}
const parsedEmail = await commonParseMail(raw_mail);
if (!parsedEmail?.headers) return false;
const headers = parsedEmail.headers;
for (const header of headers) {
if (!header["key"]) continue;
if (!header["value"]) continue;
// check spf
if (header["key"].toLowerCase() == "received-spf"
&&
!header["value"].toLowerCase().includes("pass")
) {
return true;
}
// check dkim and dmarc
if (header["key"].toLowerCase() == "authentication-results") {
if (header["value"].toLowerCase().includes("dkim=")
&&
!header["value"].toLowerCase().includes("dkim=pass")
) {
return true;
}
if (header["value"].toLowerCase().includes("dmarc=")
&&
!header["value"].toLowerCase().includes("dmarc=pass")
) {
return true;
}
}
}
return false;
}

View File

@@ -6,6 +6,7 @@ import { Bindings, HonoCustomType } from "../types";
import { auto_reply } from "./auto_reply";
import { isBlocked } from "./black_list";
import { triggerWebhook } from "../common";
import { check_if_junk_mail } from "./check_junk";
async function email(message: ForwardableEmailMessage, env: Bindings, ctx: ExecutionContext) {
@@ -15,6 +16,19 @@ async function email(message: ForwardableEmailMessage, env: Bindings, ctx: Execu
return;
}
const rawEmail = await new Response(message.raw).text();
// check if junk mail
try {
const is_junk = await check_if_junk_mail(env, message.to, rawEmail, message.headers.get("Message-ID"));
if (is_junk) {
message.setReject("Junk mail");
console.log(`Junk mail from ${message.from} to ${message.to}`);
return;
}
} catch (error) {
console.log("check junk mail error", error);
}
const message_id = message.headers.get("Message-ID");
// save email
const { success } = await env.DB.prepare(
@@ -50,7 +64,7 @@ async function email(message: ForwardableEmailMessage, env: Bindings, ctx: Execu
try {
await triggerWebhook(
{ env: env } as Context<HonoCustomType>,
message.to, rawEmail
message.to, rawEmail, message_id
);
} catch (error) {
console.log("send webhook error", error);

View File

@@ -32,6 +32,15 @@ api.get('/api/mails', async (c) => {
);
})
api.get('/api/mail/:mail_id', async (c) => {
const { address } = c.get("jwtPayload")
const { mail_id } = c.req.param();
const result = await c.env.DB.prepare(
`SELECT * FROM raw_mails where id = ? and address = ?`
).bind(mail_id, address).first();
return c.json(result);
})
api.delete('/api/mails/:id', async (c) => {
if (!getBooleanValue(c.env.ENABLE_USER_DELETE_EMAIL)) {
return c.text("User delete email is disabled", 403)

View File

@@ -36,12 +36,14 @@ async function testWebhookSettings(c: Context<HonoCustomType>): Promise<Response
const settings = await c.req.json<WebhookSettings>();
const { address } = c.get("jwtPayload");
// random raw email
const raw = await c.env.DB.prepare(
`SELECT raw FROM raw_mails WHERE address = ? ORDER BY RANDOM() LIMIT 1`
).bind(address).first<string>("raw");
const { id: mailId, raw } = await c.env.DB.prepare(
`SELECT id, raw FROM raw_mails WHERE address = ? ORDER BY RANDOM() LIMIT 1`
).bind(address).first<{ id: string, raw: string }>() || {};
const parsedEmail = await commonParseMail(raw);
const res = await sendWebhook(settings, {
id: mailId || "0",
url: c.env.FRONTEND_URL ? `${c.env.FRONTEND_URL}?mail_id=${mailId}` : "",
from: parsedEmail?.sender || "test@test.com",
to: address,
subject: parsedEmail?.subject || "test subject",

View File

@@ -22,6 +22,8 @@ export class AdminWebhookSettings {
}
export type WebhookMail = {
id: string;
url?: string;
from: string;
to: string;
subject: string;
@@ -128,6 +130,8 @@ export class WebhookSettings {
"Content-Type": "application/json"
}, null, 2)
body: string = JSON.stringify({
"id": "${id}",
"url": "${url}",
"from": "${from}",
"to": "${to}",
"subject": "${subject}",

View File

@@ -4,11 +4,12 @@ import { Telegraf, Context as TgContext, Markup } from "telegraf";
import { callbackQuery } from "telegraf/filters";
import { CONSTANTS } from "../constants";
import { getDomains, getStringValue } from '../utils';
import { getDomains, getJsonObjectValue, getStringValue } from '../utils';
import { HonoCustomType } from "../types";
import { TelegramSettings } from "./settings";
import { bindTelegramAddress, deleteTelegramAddress, jwtListToAddressData, tgUserNewAddress, unbindTelegramAddress, unbindTelegramByAddress } from "./common";
import { commonParseMail } from "../common";
import { UserFromGetMe } from "telegraf/types";
const COMMANDS = [
@@ -44,6 +45,10 @@ const COMMANDS = [
export function newTelegramBot(c: Context<HonoCustomType>, token: string): Telegraf {
const bot = new Telegraf(token);
const botInfo = getJsonObjectValue<UserFromGetMe>(c.env.TG_BOT_INFO);
if (botInfo) {
bot.botInfo = botInfo;
}
bot.use(async (ctx, next) => {
// check if in private chat

View File

@@ -42,6 +42,8 @@ export type Bindings = {
DISABLE_SHOW_GITHUB: string | boolean | undefined
FORWARD_ADDRESS_LIST: string | string[] | undefined
ENABLE_CHECK_JUNK_MAIL: string | boolean | undefined
// s3 config
S3_ENDPOINT: string | undefined
S3_ACCESS_KEY_ID: string | undefined
@@ -60,6 +62,10 @@ export type Bindings = {
// telegram config
TELEGRAM_BOT_TOKEN: string
TG_MAX_ADDRESS: number | undefined
TG_BOT_INFO: string | object | undefined
// webhook config
FRONTEND_URL: string | undefined
}
type JwtPayload = {

View File

@@ -2,6 +2,26 @@ import { Context } from "hono";
import { createMimeMessage } from "mimetext";
import { HonoCustomType, UserRole } from "./types";
export const getJsonObjectValue = <T = any>(
value: string | any
): T | null => {
if (value == undefined || value == null) {
return null;
}
if (typeof value === "object") {
return value as T;
}
if (typeof value !== "string") {
return null;
}
try {
return JSON.parse(value) as T;
} catch (e) {
console.error(`GetJsonValue: Failed to parse ${value}`, e);
}
return null;
}
export const getJsonSetting = async <T = any>(
c: Context<HonoCustomType>, key: string
): Promise<T | null> => {

View File

@@ -55,6 +55,12 @@ app.use('/*', async (c, next) => {
return c.text("Webhook is disabled", 403);
}
}
if (!c.env.DB) {
return c.text("DB is not available", 400);
}
if (!c.env.JWT_SECRET) {
return c.text("JWT_SECRET is not set", 400);
}
await next()
});

View File

@@ -1,7 +1,7 @@
name = "cloudflare_temp_email"
main = "src/worker.ts"
compatibility_date = "2023-12-01"
node_compat = true
compatibility_date = "2024-09-23"
compatibility_flags = [ "nodejs_compat" ]
# if you want use custom_domain, you need to add routes
# routes = [
# { pattern = "temp-email-api.xxxxx.xyz", custom_domain = true },
@@ -66,8 +66,14 @@ ENABLE_AUTO_REPLY = false
# CF_TURNSTILE_SECRET_KEY = ""
# telegram bot
# TG_MAX_ADDRESS = 5
# telegram bot info, predefined bot info can reduce latency of the webhook
# TG_BOT_INFO = "{}"
# global forward address list, if set, all emails will be forwarded to these addresses
# FORWARD_ADDRESS_LIST = ["xxx@xxx.com"]
# Frontend URL
# FRONTEND_URL = "https://xxxx.xxx"
# Enable check junk mail
# ENABLE_CHECK_JUNK_MAIL = false
[[d1_databases]]
binding = "DB"