mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-05-12 02:20:12 +08:00
fix: auto-reply not triggering when source_prefix is empty (#880)
* fix: auto-reply not triggering when source_prefix is empty (#459) - Empty source_prefix now matches all senders (was short-circuiting as falsy) - Support regex matching with /pattern/ syntax in source_prefix - Backward compatible: plain strings still use startsWith - Use E2E_TEST_MODE switch to skip cloudflare:email import in tests - Track reply() calls in E2E mock for testability Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: update auto-reply UI labels for regex support Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update changelogs for auto-reply fix and regex feature Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: upgrade version to v1.5.0 - Update version number to 1.5.0 in all package.json files and constants.ts - Split CHANGELOG: v1.4.0 entries finalized, new v1.5.0(main) section with auto-reply changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add error logging for invalid regex in auto-reply source_prefix Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: address CodeRabbit review suggestions - Use const object instead of let for mock state tracking - Add log when auto-reply subject/message falls back to defaults Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add source_prefix regex syntax to auto-reply docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cloudflare_temp_email",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -44,20 +44,19 @@ const receiveMail = async (c: Context<HonoCustomType>) => {
|
||||
if (!headers.has('Message-ID')) headers.set('Message-ID', `<e2e-${Date.now()}@test>`);
|
||||
|
||||
const rawBytes = new TextEncoder().encode(raw);
|
||||
let rejected: string | undefined;
|
||||
const state = { rejected: undefined as string | undefined, replyCalled: false };
|
||||
const mockMessage: ForwardableEmailMessage = {
|
||||
from, to, headers,
|
||||
rawSize: rawBytes.byteLength,
|
||||
raw: new ReadableStream({ start(ctrl) { ctrl.enqueue(rawBytes); ctrl.close(); } }),
|
||||
setReject(reason: string) { rejected = reason; },
|
||||
setReject(reason: string) { state.rejected = reason; },
|
||||
forward: async () => ({ messageId: '' }),
|
||||
reply: async () => ({ messageId: '' }),
|
||||
reply: async () => { state.replyCalled = true; return { messageId: '' }; },
|
||||
};
|
||||
|
||||
const { email: emailHandler } = await import('../email');
|
||||
await emailHandler(mockMessage, c.env, { waitUntil: () => {}, passThroughOnException: () => {} });
|
||||
|
||||
return c.json({ success: !rejected, ...(rejected ? { rejected } : {}) });
|
||||
return c.json({ success: !state.rejected, replyCalled: state.replyCalled, ...(state.rejected ? { rejected: state.rejected } : {}) });
|
||||
};
|
||||
|
||||
export default { seedMail, receiveMail };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export const CONSTANTS = {
|
||||
VERSION: 'v' + '1.4.0',
|
||||
VERSION: 'v' + '1.5.0',
|
||||
|
||||
// DB Version
|
||||
DB_VERSION_KEY: 'db_version',
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
import { createMimeMessage } from "mimetext";
|
||||
import { getBooleanValue } from "../utils";
|
||||
|
||||
/**
|
||||
* Check if the sender matches the source_prefix filter.
|
||||
* - empty/undefined: match all senders
|
||||
* - starts and ends with `/`: treat as regex (e.g. `/.*@example\.com$/`)
|
||||
* - otherwise: legacy startsWith match
|
||||
*/
|
||||
function matchSender(from: string, sourcePrefix: string | undefined): boolean {
|
||||
if (!sourcePrefix) return true;
|
||||
if (sourcePrefix.startsWith("/") && sourcePrefix.endsWith("/") && sourcePrefix.length > 2) {
|
||||
try {
|
||||
const regex = new RegExp(sourcePrefix.slice(1, -1));
|
||||
return regex.test(from);
|
||||
} catch (error) {
|
||||
console.error("Invalid regex in source_prefix:", sourcePrefix, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return from.startsWith(sourcePrefix);
|
||||
}
|
||||
|
||||
export const auto_reply = async (message: ForwardableEmailMessage, env: Bindings): Promise<void> => {
|
||||
const message_id = message.headers.get("Message-ID");
|
||||
// auto reply email
|
||||
@@ -9,7 +29,10 @@ export const auto_reply = async (message: ForwardableEmailMessage, env: Bindings
|
||||
const results = await env.DB.prepare(
|
||||
`SELECT * FROM auto_reply_mails where address = ? and enabled = 1`
|
||||
).bind(message.to).first<Record<string, string>>();
|
||||
if (results && results.source_prefix && message.from.startsWith(results.source_prefix)) {
|
||||
if (results && matchSender(message.from, results.source_prefix)) {
|
||||
if (!results.subject || !results.message) {
|
||||
console.log("auto-reply using defaults:", !results.subject ? "subject" : "", !results.message ? "message" : "");
|
||||
}
|
||||
const msg = createMimeMessage();
|
||||
msg.setHeader("In-Reply-To", message_id);
|
||||
msg.setSender({
|
||||
@@ -22,14 +45,18 @@ export const auto_reply = async (message: ForwardableEmailMessage, env: Bindings
|
||||
contentType: 'text/plain',
|
||||
data: results.message || "This is an auto-reply message, please reconact later."
|
||||
});
|
||||
const { EmailMessage } = await import('cloudflare:email');
|
||||
const replyMessage = new EmailMessage(
|
||||
message.to,
|
||||
message.from,
|
||||
msg.asRaw()
|
||||
);
|
||||
// @ts-ignore
|
||||
await message.reply(replyMessage);
|
||||
if (getBooleanValue(env.E2E_TEST_MODE)) {
|
||||
await message.reply(msg.asRaw());
|
||||
} else {
|
||||
const { EmailMessage } = await import('cloudflare:email');
|
||||
const replyMessage = new EmailMessage(
|
||||
message.to,
|
||||
message.from,
|
||||
msg.asRaw()
|
||||
);
|
||||
// @ts-ignore
|
||||
await message.reply(replyMessage);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("reply email error", error);
|
||||
|
||||
Reference in New Issue
Block a user