* 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>
Security fix: XSS bypass via jsdom raw-text tag parsing,
prototype pollution with custom elements, and lenient config
parsing in _isValidAttribute.
Supersedes #872
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: sanitize mail content in reply/forward to prevent XSS
- Add DOMPurify to sanitize HTML email content (whitelist-based)
- Add escapeHtml for plain text content (escape &<>"')
- Guard mail.originalSource with fallback to empty string
- Add jsdom for vitest DOM environment (DOMPurify requires DOM)
- Add XSS regression tests (script tags, event handlers, HTML escape)
- Add contentType assertion for empty message fallback case
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add XSS sanitization E2E screenshots
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove temporary screenshots from tree
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: normalize escapeHtml input and add forward text escape test
- escapeHtml: convert input via String(str ?? '') to handle non-string values
- Add test for plain text forward with special chars (<, &, >)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: preserve HTML content when replying to HTML emails (#728)
Reply was using curMail.text (plain text) instead of curMail.message (HTML),
causing loss of original email formatting. Forward already used HTML correctly.
Now reply prefers HTML content with plain text fallback, matching forward behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add vitest unit tests for reply/forward mail logic
Extract buildReplyModel and buildForwardModel into testable utility
functions and add 13 unit tests covering HTML content preservation,
plain text fallback, sender parsing, and subject formatting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: remove unnecessary vitest exclude config
The e2e files have been deleted, so the test.exclude config in
vite.config.js is no longer needed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: revert unnecessary trailing comma in vite.config.js
Restore vite.config.js to match main exactly — no changes needed
for this PR.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add e2e screenshots for PR review
Screenshots from local Playwright test showing:
1. HTML email rendered correctly in inbox
2. Reply editor preserving HTML content in blockquote
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove temporary test screenshots
Screenshots have been posted as PR comment, no longer needed in tree.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: use html contentType for HTML email replies instead of rich
wangEditor (rich text editor) strips block-level HTML tags inside
blockquote, losing all formatting. Use contentType 'html' for HTML
email replies (matching forward behavior) so content is edited as
raw HTML in a textarea, preserving all formatting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: update e2e screenshots showing HTML formatting preserved
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove temporary screenshots from tree
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add SMTP send flow E2E screenshots with mailpit
Screenshots showing complete SMTP HTML email reply flow:
1. View rich HTML email (gradient headers, tables, badges)
2. Reply compose with HTML mode (textarea, not wangEditor)
3. Sent box showing preserved HTML formatting
4. Mailpit inbox receiving the SMTP email
5. Mailpit email detail with full HTML rendering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove temporary SMTP test screenshots from tree
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Change updateAddressUpdatedAt to non-blocking async execution
- GET /api/mails, /api/settings, /user_api/settings no longer wait for DB update
- Improves response time for GET requests
- Also updates dependencies
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat(oauth2): add email format transformation support
- Add enableEmailFormat, userEmailFormat, userEmailReplace fields
- Support regex pattern matching and replacement template ($1, $2, etc.)
- Add Linux Do OAuth2 template with email format pre-configured
- Add input length limit (256 chars) to prevent ReDoS attacks
- Update admin UI with conditional display and tooltips
- Update documentation (zh/en) with configuration examples
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* chore: update lock files and version
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: restore accessTokenFormat as optional field
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
fix: scheduled task cleanup error "e.get is not a function"
- Use optional chaining in i18n.getMessagesbyContext to safely access Context methods
- Update version to v1.2.1
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat: optimize email filtering with frontend-only search
- Remove backend keyword parameter from mail APIs (breaking change)
- Implement frontend filtering on current page (20-100 items)
- Add message_id database index for UPDATE performance
- Support desktop and mobile responsive layouts
- Update API documentation and CHANGELOG
BREAKING CHANGE: /admin/mails and /user_api/mails no longer accept keyword parameter
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix: restore Mail ID query input in Index.vue
- Keep showMailIdQuery UI input for querying specific mail by ID
- Triggered when URL contains mail_id parameter
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* feat: upgrade version to v1.2.0
- Update version number to 1.2.0 in all package.json files
- Add v1.2.0 placeholder in CHANGELOG.md with custom SQL cleanup feature
- Upgrade dependencies
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: update @unhead/vue import path for v2.x compatibility
Change import from '@unhead/vue' to '@unhead/vue/client' for createHead
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Add AI-powered email content extraction feature using Cloudflare Workers AI to automatically identify and extract important information from emails including verification codes, authentication links, service links, and subscription links.
Features:
- AI extraction with priority-based logic (auth_code > auth_link > service_link > subscription_link > other_link)
- Admin allowlist configuration with wildcard support (*@example.com)
- Frontend display in both email list (compact) and detail view (full mode)
- Bilingual documentation (Chinese/English)
- Database migration: add metadata field to raw_mails (v0.0.3 -> v0.0.4)
Technical highlights:
- Proper regex escaping for wildcard pattern matching
- Content truncation to avoid AI token limits
- Error handling that won't affect email receiving
- JSON schema validation for AI responses
- Type-safe TypeScript implementation
- Vue I18n support with special character escaping
References:
- Inspired by Alle Project: https://github.com/bestruirui/Alle
- Uses Cloudflare Workers AI JSON Mode
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
* 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>
- Update version number to 1.1.0 in all package.json files
- Add v1.1.0 placeholder in CHANGELOG.md
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
- feat: |Admin| 新增 IP 黑名单功能,用于限制访问频率较高的 API
- feat: |Admin| 新增 RATE_LIMIT_API_DAILY_REQUESTS 配置,用于限制每日 API 请求次数
- fix: |Admin| IP 黑名单检查增加错误处理,提高系统稳定性
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
- Add clear inbox/sent items APIs for users and admins
- Implement ENABLE_USER_DELETE_EMAIL permission checks
- Fix multilingual support for success messages
- Update Vue to 3.5.21 and Wrangler to 4.34.0
- Add UI components for clearing email data in account settings
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>