mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-06-05 23:51:39 +08:00
feat: add JUNK_MAIL_CHECK_LIST for check exits and passed item && add ParsedEmailContext to cache the parsed Email (#553)
* feat: Junk mail only check JUNK_MAIL_FORCE_PASS_LIST * feat: add `JUNK_MAIL_CHECK_LIST` for check exits and passed item && add `ParsedEmailContext` to cache the parsed Email
This commit is contained in:
@@ -1,19 +1,22 @@
|
||||
import { Bindings } from "../types";
|
||||
import { Bindings, ParsedEmailContext } from "../types";
|
||||
import { getBooleanValue, getStringArray } from "../utils";
|
||||
import { commonParseMail } from "../common";
|
||||
|
||||
export const check_if_junk_mail = async (
|
||||
env: Bindings, address: string,
|
||||
raw_mail: string, message_id: string | null
|
||||
parsedEmailContext: ParsedEmailContext,
|
||||
message_id: string | null
|
||||
): Promise<boolean> => {
|
||||
if (!getBooleanValue(env.ENABLE_CHECK_JUNK_MAIL)) {
|
||||
return false;
|
||||
}
|
||||
const parsedEmail = await commonParseMail(raw_mail);
|
||||
const parsedEmail = await commonParseMail(parsedEmailContext);
|
||||
if (!parsedEmail?.headers) return false;
|
||||
|
||||
const checkListWhenExist = getStringArray(env.JUNK_MAIL_CHECK_LIST);
|
||||
const forcePassList = getStringArray(env.JUNK_MAIL_FORCE_PASS_LIST);
|
||||
const passedList: string[] = [];
|
||||
const existList: string[] = [];
|
||||
|
||||
const headers = parsedEmail.headers;
|
||||
for (const header of headers) {
|
||||
@@ -22,28 +25,35 @@ export const check_if_junk_mail = async (
|
||||
|
||||
// check spf
|
||||
if (header["key"].toLowerCase() == "received-spf") {
|
||||
if (!header["value"].toLowerCase().includes("pass")) {
|
||||
return true;
|
||||
existList.push("spf");
|
||||
if (header["value"].toLowerCase().includes("pass")) {
|
||||
passedList.push("spf");
|
||||
}
|
||||
passedList.push("spf");
|
||||
}
|
||||
|
||||
// check dkim and dmarc
|
||||
if (header["key"].toLowerCase() == "authentication-results") {
|
||||
if (header["value"].toLowerCase().includes("dkim=")) {
|
||||
if (!header["value"].toLowerCase().includes("dkim=pass")) {
|
||||
return true;
|
||||
existList.push("dkim");
|
||||
if (header["value"].toLowerCase().includes("dkim=pass")) {
|
||||
passedList.push("dkim");
|
||||
}
|
||||
passedList.push("dkim");
|
||||
}
|
||||
if (header["value"].toLowerCase().includes("dmarc=")) {
|
||||
if (!header["value"].toLowerCase().includes("dmarc=pass")) {
|
||||
return true;
|
||||
existList.push("dmarc");
|
||||
if (header["value"].toLowerCase().includes("dmarc=pass")) {
|
||||
passedList.push("dmarc");
|
||||
}
|
||||
passedList.push("dmarc");
|
||||
}
|
||||
}
|
||||
}
|
||||
// check if all checkListWhenExist item passed when exist
|
||||
if (checkListWhenExist?.some(
|
||||
(checkName) => existList.includes(checkName.toLowerCase())
|
||||
&& !passedList.includes(checkName.toLowerCase())
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (forcePassList?.length == 0) return false;
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@ import { Context } from "hono";
|
||||
|
||||
import { getEnvStringList } from "../utils";
|
||||
import { sendMailToTelegram } from "../telegram_api";
|
||||
import { Bindings, HonoCustomType, RPCEmailMessage } from "../types";
|
||||
import { Bindings, HonoCustomType, RPCEmailMessage, ParsedEmailContext } from "../types";
|
||||
import { auto_reply } from "./auto_reply";
|
||||
import { isBlocked } from "./black_list";
|
||||
import { triggerWebhook, triggerAnotherWorker, commonParseMail} from "../common";
|
||||
import { triggerWebhook, triggerAnotherWorker, commonParseMail } from "../common";
|
||||
import { check_if_junk_mail } from "./check_junk";
|
||||
|
||||
|
||||
@@ -16,10 +16,13 @@ async function email(message: ForwardableEmailMessage, env: Bindings, ctx: Execu
|
||||
return;
|
||||
}
|
||||
const rawEmail = await new Response(message.raw).text();
|
||||
const parsedEmailContext: ParsedEmailContext = {
|
||||
rawEmail: rawEmail
|
||||
};
|
||||
|
||||
// check if junk mail
|
||||
try {
|
||||
const is_junk = await check_if_junk_mail(env, message.to, rawEmail, message.headers.get("Message-ID"));
|
||||
const is_junk = await check_if_junk_mail(env, message.to, parsedEmailContext, message.headers.get("Message-ID"));
|
||||
if (is_junk) {
|
||||
message.setReject("Junk mail");
|
||||
console.log(`Junk mail from ${message.from} to ${message.to}`);
|
||||
@@ -31,14 +34,19 @@ async function email(message: ForwardableEmailMessage, env: Bindings, ctx: Execu
|
||||
|
||||
const message_id = message.headers.get("Message-ID");
|
||||
// save email
|
||||
const { success } = await env.DB.prepare(
|
||||
`INSERT INTO raw_mails (source, address, raw, message_id) VALUES (?, ?, ?, ?)`
|
||||
).bind(
|
||||
message.from, message.to, rawEmail, message_id
|
||||
).run();
|
||||
if (!success) {
|
||||
message.setReject(`Failed save message to ${message.to}`);
|
||||
console.log(`Failed save message from ${message.from} to ${message.to}`);
|
||||
try {
|
||||
const { success } = await env.DB.prepare(
|
||||
`INSERT INTO raw_mails (source, address, raw, message_id) VALUES (?, ?, ?, ?)`
|
||||
).bind(
|
||||
message.from, message.to, rawEmail, message_id
|
||||
).run();
|
||||
if (!success) {
|
||||
message.setReject(`Failed save message to ${message.to}`);
|
||||
console.log(`Failed save message from ${message.from} to ${message.to}`);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log("save email error", error);
|
||||
}
|
||||
|
||||
// forward email
|
||||
@@ -55,17 +63,16 @@ async function email(message: ForwardableEmailMessage, env: Bindings, ctx: Execu
|
||||
try {
|
||||
await sendMailToTelegram(
|
||||
{ env: env } as Context<HonoCustomType>,
|
||||
message.to, rawEmail, message_id);
|
||||
message.to, parsedEmailContext, message_id);
|
||||
} catch (error) {
|
||||
console.log("send mail to telegram error", error);
|
||||
}
|
||||
|
||||
// send webhook
|
||||
let parsedText;
|
||||
try {
|
||||
parsedText = await triggerWebhook(
|
||||
await triggerWebhook(
|
||||
{ env: env } as Context<HonoCustomType>,
|
||||
message.to, rawEmail, message_id
|
||||
message.to, parsedEmailContext, message_id
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("send webhook error", error);
|
||||
@@ -74,12 +81,10 @@ async function email(message: ForwardableEmailMessage, env: Bindings, ctx: Execu
|
||||
// trigger another worker
|
||||
try {
|
||||
const headersMap = new Map<string, string>();
|
||||
if(message.headers) {
|
||||
message.headers.forEach((value, key) => {headersMap.set(key, value);});
|
||||
}
|
||||
if (!parsedText){
|
||||
parsedText = (await commonParseMail(rawEmail))?.text ?? ""
|
||||
if (message.headers) {
|
||||
message.headers.forEach((value, key) => { headersMap.set(key, value); });
|
||||
}
|
||||
const parsedText = (await commonParseMail(parsedEmailContext))?.text ?? ""
|
||||
const rpcEmail: RPCEmailMessage = {
|
||||
from: message.from,
|
||||
to: message.to,
|
||||
|
||||
Reference in New Issue
Block a user