feat: add email blacklist filtering

This commit is contained in:
eoao
2026-05-08 22:40:17 +08:00
parent 154f536c61
commit b60add170c
9 changed files with 166 additions and 8 deletions

View File

@@ -27,3 +27,8 @@ app.delete('/setting/deleteBackground', async (c) => {
return c.json(result.ok());
});
app.put('/setting/setBlacklist', async (c) => {
const setting = await settingService.setBlacklist(c, await c.req.json());
return c.json(result.ok(setting));
})

View File

@@ -24,7 +24,10 @@ export async function email(message, env, ctx) {
ruleEmail,
ruleType,
r2Domain,
noRecipient
noRecipient,
blackSubject,
blackContent,
blackFrom
} = await settingService.query({ env });
if (receive === settingConst.receive.CLOSE) {
@@ -32,7 +35,6 @@ export async function email(message, env, ctx) {
return;
}
const reader = message.raw.getReader();
let content = '';
@@ -44,6 +46,14 @@ export async function email(message, env, ctx) {
const email = await PostalMime.parse(content);
const blockFlag = checkBlock(blackSubject, blackContent, blackFrom, email);
if (blockFlag) {
message.setReject('Message rejected');
return;
}
const account = await accountService.selectByEmailIncludeDel({ env: env }, message.to);
if (!account && noRecipient === settingConst.noRecipient.CLOSE) {
@@ -169,3 +179,31 @@ export async function email(message, env, ctx) {
throw e
}
}
function checkBlock(blackSubjectStr, blackContentStr, blackFromStr, email) {
const blackFromList = blackFromStr ? blackFromStr.split(',') : []
const blackContentList = blackContentStr ? blackContentStr.split(',') : []
const blackSubjectList = blackSubjectStr ? blackSubjectStr.split(',') : []
for (const blackSubject of blackSubjectList) {
if (email.subject?.includes(blackSubject)) {
return true
}
}
for (const blackContent of blackContentList) {
if (email.html?.includes(blackContent) || email.text?.includes(blackContent)) {
return true
}
}
for (const blackFrom of blackFromList) {
if (email.from.address.includes(blackFrom)) {
return true
}
}
return false
}

View File

@@ -46,6 +46,9 @@ export const setting = sqliteTable('setting', {
tgMsgTo: text('tg_msg_to').default('show').notNull(),
tgMsgText: text('tg_msg_text').default('hide').notNull(),
minEmailPrefix: integer('min_email_prefix').default(0).notNull(),
emailPrefixFilter: text('email_prefix_filter').default('').notNull()
emailPrefixFilter: text('email_prefix_filter').default('').notNull(),
blackSubject: text('black_subject').default('').notNull(),
blackContent: text('black_content').default('').notNull(),
blackFrom: text('black_from').default('').notNull()
});
export default setting

View File

@@ -28,10 +28,23 @@ const dbInit = {
await this.v2_7DB(c);
await this.v2_8DB(c);
await this.v2_9DB(c);
await this.v3_0DB(c);
await settingService.refresh(c);
return c.text('success');
},
async v3_0DB(c) {
try {
await c.env.db.batch([
c.env.db.prepare(`ALTER TABLE setting ADD COLUMN black_subject TEXT NOT NULL DEFAULT '';`),
c.env.db.prepare(`ALTER TABLE setting ADD COLUMN black_content TEXT NOT NULL DEFAULT '';`),
c.env.db.prepare(`ALTER TABLE setting ADD COLUMN black_from TEXT NOT NULL DEFAULT '';`)
]);
} catch (e) {
console.warn(`跳过字段:${e.message}`);
}
},
async v2_9DB(c) {
try {
await c.env.db.prepare(`UPDATE setting SET auto_refresh = 5 WHERE auto_refresh = 1;`).run();

View File

@@ -184,6 +184,14 @@ const settingService = {
return background;
},
async setBlacklist(c, params) {
const { blackSubject, blackContent, blackFrom } = params
await orm(c).update(setting).set({ blackSubject, blackContent, blackFrom }).run();
await this.refresh(c);
return this.get(c);
},
async websiteConfig(c) {
const settingRow = await this.get(c, true);
@@ -220,7 +228,8 @@ const settingService = {
minEmailPrefix: settingRow.minEmailPrefix,
projectLink: settingRow.projectLink
};
}
},
};
export default settingService;