feat: 账号设置页面增加 邮件转发规则 和 禁止接收未知地址邮件 配置 (#710)

This commit is contained in:
Dream Hunter
2025-08-23 16:19:53 +08:00
committed by GitHub
parent 89d8944e60
commit 0565978930
6 changed files with 199 additions and 12 deletions

View File

@@ -14,6 +14,7 @@ import worker_config from './worker_config'
import admin_mail_api from './admin_mail_api'
import { sendMailbyAdmin } from './send_mail'
import db_api from './db_api'
import { EmailRuleSettings } from '../models'
export const api = new Hono<HonoCustomType>()
@@ -217,13 +218,15 @@ api.get('/admin/account_settings', async (c) => {
const sendBlockList = await getJsonSetting(c, CONSTANTS.SEND_BLOCK_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') : [];
const emailRuleSettings = await getJsonSetting<EmailRuleSettings>(c, CONSTANTS.EMAIL_RULE_SETTINGS_KEY);
const noLimitSendAddressList = await getJsonSetting(c, CONSTANTS.NO_LIMIT_SEND_ADDRESS_LIST_KEY);
return c.json({
blockList: blockList || [],
sendBlockList: sendBlockList || [],
verifiedAddressList: verifiedAddressList || [],
fromBlockList: fromBlockList || [],
noLimitSendAddressList: noLimitSendAddressList || []
noLimitSendAddressList: noLimitSendAddressList || [],
emailRuleSettings: emailRuleSettings || {}
})
} catch (error) {
console.error(error);
@@ -235,7 +238,7 @@ api.post('/admin/account_settings', async (c) => {
/** @type {{ blockList: Array<string>, sendBlockList: Array<string> }} */
const {
blockList, sendBlockList, noLimitSendAddressList,
verifiedAddressList, fromBlockList
verifiedAddressList, fromBlockList, emailRuleSettings
} = await c.req.json();
if (!blockList || !sendBlockList || !verifiedAddressList) {
return c.text("Invalid blockList or sendBlockList", 400)
@@ -265,6 +268,10 @@ api.post('/admin/account_settings', async (c) => {
c, CONSTANTS.NO_LIMIT_SEND_ADDRESS_LIST_KEY,
JSON.stringify(noLimitSendAddressList || [])
)
await saveSetting(
c, CONSTANTS.EMAIL_RULE_SETTINGS_KEY,
JSON.stringify(emailRuleSettings || {})
)
return c.json({
success: true
})

View File

@@ -13,6 +13,7 @@ export const CONSTANTS = {
OAUTH2_SETTINGS_KEY: 'oauth2_settings',
VERIFIED_ADDRESS_LIST_KEY: 'verified_address_list',
NO_LIMIT_SEND_ADDRESS_LIST_KEY: 'no_limit_send_address_list',
EMAIL_RULE_SETTINGS_KEY: 'email_rule_settings',
// KV
TG_KV_PREFIX: "temp-mail-telegram",

View File

@@ -1,12 +1,14 @@
import { Context } from "hono";
import { getEnvStringList, getJsonObjectValue } from "../utils";
import { getEnvStringList, getJsonObjectValue, getJsonSetting } from "../utils";
import { sendMailToTelegram } from "../telegram_api";
import { auto_reply } from "./auto_reply";
import { isBlocked } from "./black_list";
import { triggerWebhook, triggerAnotherWorker, commonParseMail } from "../common";
import { check_if_junk_mail } from "./check_junk";
import { remove_attachment_if_need } from "./check_attachment";
import { EmailRuleSettings } from "../models";
import { CONSTANTS } from "../constants";
async function email(message: ForwardableEmailMessage, env: Bindings, ctx: ExecutionContext) {
@@ -32,6 +34,25 @@ async function email(message: ForwardableEmailMessage, env: Bindings, ctx: Execu
console.error("check junk mail error", error);
}
// check if unknown address mail
try {
const emailRuleSettings = await getJsonSetting<EmailRuleSettings>(
{ env: env } as Context<HonoCustomType>, CONSTANTS.EMAIL_RULE_SETTINGS_KEY
);
if (emailRuleSettings?.blockReceiveUnknowAddressEmail) {
const db_address_id = await env.DB.prepare(
`SELECT id FROM address where name = ? `
).bind(message.to).first("id");
if (!db_address_id) {
message.setReject("Unknown address");
console.log(`Unknown address mail from ${message.from} to ${message.to}`);
return;
}
}
} catch (error) {
console.error("check unknown address mail error", error);
}
// remove attachment if configured or size > 2MB
try {
await remove_attachment_if_need(env, parsedEmailContext, message.from, message.to, message.rawSize);
@@ -70,11 +91,19 @@ async function email(message: ForwardableEmailMessage, env: Bindings, ctx: Execu
try {
// 遍历 FORWARD_ADDRESS_LIST
const subdomainForwardAddressList = getJsonObjectValue<SubdomainForwardAddressList[]>(env.SUBDOMAIN_FORWARD_ADDRESS_LIST) || [];
for (const subdomainForwardAddress of subdomainForwardAddressList) {
const emailRuleSettings = await getJsonSetting<EmailRuleSettings>(
{ env: env } as Context<HonoCustomType>, CONSTANTS.EMAIL_RULE_SETTINGS_KEY
);
// 合并两个配置, env 里的配置优先级更高
const allSubdomainForwardAddressList = [
...(subdomainForwardAddressList || []),
...(emailRuleSettings?.emailForwardingList || []),
];
for (const subdomainForwardAddress of allSubdomainForwardAddressList) {
// 检查邮件是否匹配 domains
if (subdomainForwardAddress.domains && subdomainForwardAddress.domains.length > 0) {
for (const domain of subdomainForwardAddress.domains) {
if (message.to.endsWith(domain)) {
if (message.to.endsWith(domain) && subdomainForwardAddress.forward) {
// 转发邮件
await message.forward(subdomainForwardAddress.forward);
// 支持多邮箱转发收件,不进行截止

View File

@@ -145,3 +145,8 @@ export type UserOauth2Settings = {
enableMailAllowList?: boolean | undefined;
mailAllowList?: string[] | undefined;
}
export type EmailRuleSettings = {
blockReceiveUnknowAddressEmail: boolean;
emailForwardingList: SubdomainForwardAddressList[]
}