feat: add empty address cleanup feature (#765)

* feat: add empty address cleanup feature

Add functionality to clean up email addresses that have never received any emails and were created more than N days ago.

Changes:
- Add emptyAddress cleanup type to backend cleanup logic
- Add enableEmptyAddressAutoCleanup and cleanEmptyAddressDays to CleanupSettings model
- Add scheduled task support for auto-cleanup of empty addresses
- Add UI controls in Maintenance page for manual and auto cleanup
- Add i18n support (English and Chinese translations)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: update dependencies

Update package.json and lock files across frontend, worker, pages, and vitepress-docs

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* docs: update CHANGELOG for empty address cleanup feature

Add entry for new maintenance page feature to clean up email addresses with no emails older than N days

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Dream Hunter
2025-11-13 17:57:35 +08:00
committed by GitHub
parent 088bf3eefe
commit 113f9ad66b
12 changed files with 1237 additions and 1265 deletions

View File

@@ -273,6 +273,13 @@ export const cleanup = async (
DELETE FROM sendbox WHERE created_at < datetime('now', '-${cleanDays} day')`
).run();
break;
case "emptyAddress":
// Delete addresses that have no emails and were created more than N days ago
await batchDeleteAddressWithData(
c,
`name NOT IN (SELECT DISTINCT address FROM raw_mails WHERE address IS NOT NULL) AND created_at < datetime('now', '-${cleanDays} day')`
)
break;
default:
throw new Error("Invalid cleanType")
}

View File

@@ -48,6 +48,8 @@ export type CleanupSettings = {
cleanInactiveAddressDays: number;
enableUnboundAddressAutoCleanup: boolean | undefined;
cleanUnboundAddressDays: number;
enableEmptyAddressAutoCleanup: boolean | undefined;
cleanEmptyAddressDays: number;
}
export class GeoData {

View File

@@ -57,4 +57,11 @@ export async function scheduled(event: ScheduledEvent, env: Bindings, ctx: any)
autoCleanupSetting.cleanUnboundAddressDays
);
}
if (autoCleanupSetting.enableEmptyAddressAutoCleanup) {
await cleanup(
{ env: env, } as Context<HonoCustomType>,
"emptyAddress",
autoCleanupSetting.cleanEmptyAddressDays
);
}
}