feat: add EMAIL_KV_BLACK_LIST (#394)

This commit is contained in:
Dream Hunter
2024-08-11 20:34:10 +08:00
committed by GitHub
parent c733d3bf4d
commit ac31042e69
8 changed files with 48 additions and 8 deletions
+1
View File
@@ -4,6 +4,7 @@
## main(v0.7.1) ## main(v0.7.1)
- fix: 修复用户角色加载失败的问题 - fix: 修复用户角色加载失败的问题
- feat: admin 账号设置增加来源邮件地址黑名单配置
## v0.7.0 ## v0.7.0
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "cloudflare_temp_email", "name": "cloudflare_temp_email",
"version": "0.7.0", "version": "0.7.1",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
+1 -1
View File
@@ -128,7 +128,7 @@ const getUserSettings = async (message) => {
const res = await api.fetch("/user_api/settings") const res = await api.fetch("/user_api/settings")
Object.assign(userSettings.value, res) Object.assign(userSettings.value, res)
} catch (error) { } catch (error) {
message.error(error.message || "error"); message?.error(error.message || "error");
} finally { } finally {
userSettings.value.fetched = true; userSettings.value.fetched = true;
} }
+14 -1
View File
@@ -11,20 +11,24 @@ const message = useMessage()
const { t } = useI18n({ const { t } = useI18n({
messages: { messages: {
en: { en: {
tip: 'You can manually input the following multiple select input',
save: 'Save', save: 'Save',
successTip: 'Save Success', successTip: 'Save Success',
address_block_list: 'Address Block Keywords for Users(Admin can skip)', address_block_list: 'Address Block Keywords for Users(Admin can skip)',
address_block_list_placeholder: 'Please enter the keywords you want to block', address_block_list_placeholder: 'Please enter the keywords you want to block',
send_address_block_list: 'Address Block Keywords for send email', send_address_block_list: 'Address Block Keywords for send email',
verified_address_list: 'Verified Address List(Can send email by cf internal api)', verified_address_list: 'Verified Address List(Can send email by cf internal api)',
fromBlockList: 'Block Keywords for receive email',
}, },
zh: { zh: {
tip: '您可以手动输入以下多选输入框',
save: '保存', save: '保存',
successTip: '保存成功', successTip: '保存成功',
address_block_list: '邮件地址屏蔽关键词(管理员可跳过检查)', address_block_list: '邮件地址屏蔽关键词(管理员可跳过检查)',
address_block_list_placeholder: '请输入您想要屏蔽的关键词', address_block_list_placeholder: '请输入您想要屏蔽的关键词',
send_address_block_list: '发送邮件地址屏蔽关键词', send_address_block_list: '发送邮件地址屏蔽关键词',
verified_address_list: '已验证地址列表(可通过 cf 内部 api 发送邮件)', verified_address_list: '已验证地址列表(可通过 cf 内部 api 发送邮件)',
fromBlockList: '接收邮件地址屏蔽关键词',
} }
} }
}); });
@@ -32,6 +36,7 @@ const { t } = useI18n({
const addressBlockList = ref([]) const addressBlockList = ref([])
const sendAddressBlockList = ref([]) const sendAddressBlockList = ref([])
const verifiedAddressList = ref([]) const verifiedAddressList = ref([])
const fromBlockList = ref([])
const fetchData = async () => { const fetchData = async () => {
try { try {
@@ -39,6 +44,7 @@ const fetchData = async () => {
addressBlockList.value = res.blockList || [] addressBlockList.value = res.blockList || []
sendAddressBlockList.value = res.sendBlockList || [] sendAddressBlockList.value = res.sendBlockList || []
verifiedAddressList.value = res.verifiedAddressList || [] verifiedAddressList.value = res.verifiedAddressList || []
fromBlockList.value = res.fromBlockList || []
} catch (error) { } catch (error) {
message.error(error.message || "error"); message.error(error.message || "error");
} }
@@ -51,7 +57,8 @@ const save = async () => {
body: JSON.stringify({ body: JSON.stringify({
blockList: addressBlockList.value || [], blockList: addressBlockList.value || [],
sendBlockList: sendAddressBlockList.value || [], sendBlockList: sendAddressBlockList.value || [],
verifiedAddressList: verifiedAddressList.value || [] verifiedAddressList: verifiedAddressList.value || [],
fromBlockList: fromBlockList.value || [],
}) })
}) })
message.success(t('successTip')) message.success(t('successTip'))
@@ -69,6 +76,9 @@ onMounted(async () => {
<template> <template>
<div class="center"> <div class="center">
<n-card :bordered="false" embedded style="max-width: 600px;"> <n-card :bordered="false" embedded style="max-width: 600px;">
<n-alert :show-icon="false" style="margin-bottom: 10px;">
{{ t("tip") }}
</n-alert>
<n-form-item-row :label="t('address_block_list')"> <n-form-item-row :label="t('address_block_list')">
<n-select v-model:value="addressBlockList" filterable multiple tag <n-select v-model:value="addressBlockList" filterable multiple tag
:placeholder="t('address_block_list_placeholder')" /> :placeholder="t('address_block_list_placeholder')" />
@@ -81,6 +91,9 @@ onMounted(async () => {
<n-select v-model:value="verifiedAddressList" filterable multiple tag <n-select v-model:value="verifiedAddressList" filterable multiple tag
:placeholder="t('verified_address_list')" /> :placeholder="t('verified_address_list')" />
</n-form-item-row> </n-form-item-row>
<n-form-item-row :label="t('fromBlockList')">
<n-select v-model:value="fromBlockList" filterable multiple tag :placeholder="t('fromBlockList')" />
</n-form-item-row>
<n-button @click="save" type="primary" block :loading="loading"> <n-button @click="save" type="primary" block :loading="loading">
{{ t('save') }} {{ t('save') }}
</n-button> </n-button>
+10 -2
View File
@@ -246,10 +246,12 @@ api.get('/admin/account_settings', async (c) => {
const blockList = await getJsonSetting(c, CONSTANTS.ADDRESS_BLOCK_LIST_KEY); const blockList = await getJsonSetting(c, CONSTANTS.ADDRESS_BLOCK_LIST_KEY);
const sendBlockList = await getJsonSetting(c, CONSTANTS.SEND_BLOCK_LIST_KEY); const sendBlockList = await getJsonSetting(c, CONSTANTS.SEND_BLOCK_LIST_KEY);
const verifiedAddressList = await getJsonSetting(c, CONSTANTS.VERIFIED_ADDRESS_LIST_KEY); const verifiedAddressList = await getJsonSetting(c, CONSTANTS.VERIFIED_ADDRESS_LIST_KEY);
const fromBlockList = c.env.KV ? await c.env.KV.get<string[]>(CONSTANTS.EMAIL_KV_BLACK_LIST, 'json') : [];
return c.json({ return c.json({
blockList: blockList || [], blockList: blockList || [],
sendBlockList: sendBlockList || [], sendBlockList: sendBlockList || [],
verifiedAddressList: verifiedAddressList || [] verifiedAddressList: verifiedAddressList || [],
fromBlockList: fromBlockList || []
}) })
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@@ -259,7 +261,7 @@ api.get('/admin/account_settings', async (c) => {
api.post('/admin/account_settings', async (c) => { api.post('/admin/account_settings', async (c) => {
/** @type {{ blockList: Array<string>, sendBlockList: Array<string> }} */ /** @type {{ blockList: Array<string>, sendBlockList: Array<string> }} */
const { blockList, sendBlockList, verifiedAddressList } = await c.req.json(); const { blockList, sendBlockList, verifiedAddressList, fromBlockList } = await c.req.json();
if (!blockList || !sendBlockList || !verifiedAddressList) { if (!blockList || !sendBlockList || !verifiedAddressList) {
return c.text("Invalid blockList or sendBlockList", 400) return c.text("Invalid blockList or sendBlockList", 400)
} }
@@ -278,6 +280,12 @@ api.post('/admin/account_settings', async (c) => {
c, CONSTANTS.VERIFIED_ADDRESS_LIST_KEY, c, CONSTANTS.VERIFIED_ADDRESS_LIST_KEY,
JSON.stringify(verifiedAddressList) JSON.stringify(verifiedAddressList)
) )
if (fromBlockList?.length > 0 && !c.env.KV) {
return c.text("Please enable KV to use fromBlockList", 400)
}
if (fromBlockList) {
await c.env.KV.put(CONSTANTS.EMAIL_KV_BLACK_LIST, JSON.stringify(fromBlockList || []))
}
return c.json({ return c.json({
success: true success: true
}) })
+2 -1
View File
@@ -1,5 +1,5 @@
export const CONSTANTS = { export const CONSTANTS = {
VERSION: 'v0.7.0', VERSION: 'v0.7.1',
// DB settings // DB settings
ADDRESS_BLOCK_LIST_KEY: 'address_block_list', ADDRESS_BLOCK_LIST_KEY: 'address_block_list',
@@ -13,4 +13,5 @@ export const CONSTANTS = {
TG_KV_SETTINGS_KEY: "temp-mail-telegram-settings", TG_KV_SETTINGS_KEY: "temp-mail-telegram-settings",
WEBHOOK_KV_SETTINGS_KEY: "temp-mail-webhook-settings", WEBHOOK_KV_SETTINGS_KEY: "temp-mail-webhook-settings",
WEBHOOK_KV_USER_SETTINGS_KEY: "temp-mail-webhook-user-settings", WEBHOOK_KV_USER_SETTINGS_KEY: "temp-mail-webhook-user-settings",
EMAIL_KV_BLACK_LIST: "temp-mail-email-black-list",
} }
+16
View File
@@ -0,0 +1,16 @@
import { CONSTANTS } from "../constants";
import { Bindings } from "../types";
export const isBlocked = async (from: string, env: Bindings): Promise<boolean> => {
if (env.BLACK_LIST && env.BLACK_LIST.split(",").some(word => from.includes(word))) {
return true;
}
if (!env.KV) {
return false;
}
const blockList = await env.KV.get<string[]>(CONSTANTS.EMAIL_KV_BLACK_LIST, 'json') || [];
if (blockList.some(word => from.includes(word))) {
return true;
}
return false;
}
+3 -2
View File
@@ -5,11 +5,12 @@ import { sendMailToTelegram } from "../telegram_api";
import { Bindings, HonoCustomType } from "../types"; import { Bindings, HonoCustomType } from "../types";
import { auto_reply } from "./auto_reply"; import { auto_reply } from "./auto_reply";
import { trigerWebhook } from "../mails_api/webhook_settings"; import { trigerWebhook } from "../mails_api/webhook_settings";
import { isBlocked } from "./black_list";
async function email(message: ForwardableEmailMessage, env: Bindings, ctx: ExecutionContext) { async function email(message: ForwardableEmailMessage, env: Bindings, ctx: ExecutionContext) {
if (env.BLACK_LIST && env.BLACK_LIST.split(",").some(word => message.from.includes(word))) { if (await isBlocked(message.from, env)) {
message.setReject("Missing from address"); message.setReject("Reject from address");
console.log(`Reject message from ${message.from} to ${message.to}`); console.log(`Reject message from ${message.from} to ${message.to}`);
return; return;
} }