Commit Graph

309 Commits

Author SHA1 Message Date
Dream Hunter
a0db913952 fix: remove vite-plugin-top-level-await, incompatible with new esbuild (#940) 2026-04-04 20:08:25 +08:00
Dream Hunter
4746983780 feat: upgrade version to v1.6.0 (#939)
* feat: upgrade version to v1.6.0

- Update version number to 1.6.0 in all package.json files
- Add v1.6.0 placeholder in CHANGELOG.md and CHANGELOG_EN.md

* docs: update release skill to use bilingual format (zh + en collapsed)

* chore: upgrade dependencies

* fix: correct CHANGELOG placeholder position and update version-upgrade skill

* docs: update version-upgrade skill with correct CHANGELOG placeholder position
2026-04-04 19:58:47 +08:00
majorcheng
1a7cfb8c95 feat: 支持创建邮箱 API 的子域名后缀匹配开关 (#929)
* feat: 支持创建邮箱 API 的子域名后缀匹配开关

* fix: 修复 review 提到的开关三态与域名校验问题

* fix: 补充域名归一化与子域名匹配回归测试

* fix: 修复后台开关跟随 env 回退与 account_settings 半成功保存

* fix: 收口账号设置刷新提示与子域名状态重复读取

* fix: 拦截超长域名并透传账号设置刷新失败
2026-04-04 00:11:23 +08:00
Dream Hunter
d2c940aa2c feat(admin): add column sorting and reset pagination on search (#927)
* feat(admin): add column sorting and reset pagination on search (#918)

- Add server-side column sorting for admin address list (ID, name, created_at, updated_at, mail_count, send_count)
- Reset pagination to page 1 when searching or changing sort order
- Add optional orderBy parameter to handleListQuery with whitelist validation

Closes #918

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

* docs: add JSDoc warning for orderBy parameter in handleListQuery

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

* fix: address code review findings

- Fix count not resetting to 0 when search returns empty results
- Add source_meta column sorting support
- Use Object.hasOwn to prevent prototype pollution in sort column lookup

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 01:46:12 +08:00
tsymr
db93828a81 feat(subdomain): add random second-level mailbox support (#924)
Summary: add random second-level subdomain mailbox creation for web, admin, and
  Telegram.

Scope: worker config, UI toggle, and README/VitePress documentation.

Co-authored-by: wufei <fwu@creams.io>
2026-04-02 23:13:10 +08:00
Dream Hunter
6c58cd3c2e fix: add localStorage fallback for OAuth2 session state on mobile browsers (#900)
* fix: add localStorage fallback for OAuth2 session state on mobile browsers

Some mobile browsers (Safari ITP, WebViews) lose sessionStorage during
cross-origin OAuth2 redirects. Add localStorage fallback via computed
wrapper that dual-writes on set and reads sessionStorage-first on get.
Also cleanup state in finally block to ensure one-time consumption.

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

* fix: i18n for 'code not found' in OAuth2 callback

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 00:04:00 +08:00
Dream Hunter
e35c246757 fix: mail-parser-wasm missing message/rfc822 attachments (#897)
* fix: mail-parser-wasm treat message/rfc822 attachments as regular attachments

Previously, message/rfc822 attachments (e.g. .eml files) were
recursively parsed for sub-attachments instead of being returned
directly, causing them to be silently dropped. Now all attachments
are returned regardless of type.

Bump version to 0.2.2. Add .gitignore for worker build artifacts.

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

* chore: add missing entries to worker .gitignore

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

* chore: bump mail-parser-wasm to 0.2.2 in frontend

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 02:52:13 +08:00
Dream Hunter
5bb053fb7b chore: upgrade deps and GitHub Actions for Node.js 24 (#889)
chore: upgrade dependencies and GitHub Actions for Node.js 24 compatibility

Upgrade GitHub Actions to fix Node.js 20 deprecation warnings:
- actions/checkout v4 → v6
- actions/setup-node v4 → v6
- pnpm/action-setup v3 → v4
- docker/login-action v3 → v4
- docker/setup-qemu-action v3 → v4
- docker/setup-buildx-action v3 → v4
- docker/build-push-action v5 → v7
- node-version 20 → 22, pnpm 8 → 10

Upgrade project dependencies:
- frontend: vue 3.5.30, naive-ui 2.44.1, dompurify 3.3.3, @unhead/vue 2.1.12
- worker: hono 4.12.7, @cloudflare/workers-types, typescript-eslint 8.57.0
- all: wrangler 4.72.0

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 01:27:03 +08:00
Dream Hunter
7d880ef340 fix: user email regex setting visibility (#888)
fix: keep email regex option visible in user settings
2026-03-12 01:15:22 +08:00
Dream Hunter
e6cc8e2ffd feat: add Turnstile CAPTCHA for login forms (#767) (#885)
* feat: add Turnstile CAPTCHA for login forms (#767)

Add optional Turnstile verification for admin login, user login, and
address password login via ENABLE_LOGIN_TURNSTILE_CHECK env var.
Does not affect existing Turnstile on address creation / registration.

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

* docs: add ENABLE_LOGIN_TURNSTILE_CHECK to wrangler.toml.template

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

* fix: ensure openSettings loaded before admin login modal

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

* feat: add Turnstile to site access password and fix settings field name

- Add Turnstile to site access password modal in Header.vue
- Add /open_api/site_login endpoint for password + Turnstile verification
- Fix settings field name from enableTurnstileLogin to enableLoginTurnstileCheck

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

* refactor: move login endpoints to open_api/auth.ts

Move /open_api/site_login and /open_api/admin_login from commom_api.ts
to a dedicated open_api/auth.ts file for better code organization.

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

* fix: change Turnstile check failure status from 500 to 400

Turnstile validation failure is a client error, not a server error.
Change all Turnstile check error responses from 500 to 400.

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

* fix: use unique IDs for multiple Turnstile instances

When multiple modals with Turnstile appear simultaneously (e.g., site
access + admin login), the hardcoded id="cf-turnstile" causes conflicts.
Generate a unique container ID per Turnstile instance to fix this.

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

* fix: review fixes - cfToken separation, register Turnstile, error codes

- Separate cfToken refs in Login.vue to avoid token sharing between
  login and new address creation Turnstile instances
- Add Turnstile check to user registration endpoint (not just verify_code)
- Show Turnstile on register tab regardless of enableMailVerify
- Pass cf_token in register request body
- Fix site_login error message to use CustomAuthPasswordMsg
- Fix verifyCode Turnstile error status from 500 to 400
- Restore empty line in commom_api.ts

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

* fix: separate register Turnstile logic for with/without mail verify

- With mail verify: verify_code already checks Turnstile, register
  skips Turnstile (token is one-time use)
- Without mail verify: register checks Turnstile directly
- Separate loginCfToken for login tab to avoid token sharing with
  register tab Turnstile

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

* fix: add enableLoginTurnstileCheck to store defaults, simplify changelog

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

* fix: add /open_api/credential_login for credential login verification

Add credential_login endpoint that verifies both Turnstile token and
JWT credential server-side, replacing the generic verify_turnstile
endpoint. Credential login now validates the JWT before accepting it.

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

* fix: improve login endpoints - hash passwords, expose Turnstile refresh, fix status codes

- site_login/admin_login: always called, verify hashed password + optional Turnstile
- credential_login: always called, verify JWT + optional Turnstile
- Frontend sends hashed passwords instead of plaintext
- Turnstile component exposes refresh method via defineExpose
- Fix Turnstile error status 500→400 in mails_api and telegram_api

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

* refactor: rename to ENABLE_GLOBAL_TURNSTILE_CHECK and add isGlobalTurnstileEnabled helper

- Rename ENABLE_LOGIN_TURNSTILE_CHECK -> ENABLE_GLOBAL_TURNSTILE_CHECK
- Add isGlobalTurnstileEnabled() in utils.ts: checks env var + Turnstile keys all present
- Backend settings returns enableGlobalTurnstileCheck computed from the helper
- All backend endpoints use isGlobalTurnstileEnabled(c) instead of raw env check
- Update all frontend refs, docs, changelog, and wrangler template

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

* refactor: use utils.isGlobalTurnstileEnabled instead of named import

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

* test: add E2E tests for turnstile login endpoints

- Test all 3 new /open_api/* endpoints when ENABLE_GLOBAL_TURNSTILE_CHECK is disabled
- Verify settings returns enableGlobalTurnstileCheck: false
- Test admin_login with correct/wrong/empty hashed password
- Test site_login returns 401 when no PASSWORDS configured
- Test credential_login with valid JWT, invalid JWT, empty credential
- Test address_login with empty cf_token works when turnstile disabled
- Add ADMIN_PASSWORDS to E2E wrangler config for admin_login tests

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

* test: rename test file to login-endpoints.spec.ts

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

* fix: validate JWT payload has address field in credential_login

Prevents user tokens or challenge tokens from being accepted as
address credentials since they share the same JWT_SECRET.

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

* fix: refresh Turnstile token on login failure to allow retry

After a failed login attempt, the consumed Turnstile token is now
refreshed so users can retry without manually refreshing.
Also adds ref to signup Turnstile in UserLogin.vue to refresh after
verification code is sent (single-use token consumed).

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

* fix: separate Turnstile tokens for signup and reset password flows

Split shared cfToken into signupCfToken and resetCfToken to prevent
single-use Turnstile token conflicts between signup tab and reset
password modal. Each flow now has its own token ref and refreshes
the correct Turnstile widget after use.

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

* fix: update comments from "login turnstile" to "global turnstile"

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:47:26 +08:00
Dream Hunter
94c606959f docs: add webhook preset templates and Telegram push docs (#884)
docs: add webhook preset templates and Telegram per-user push docs (#769)

Add Telegram Bot, WeChat Work, Discord webhook preset templates to
frontend and documentation. Add per-user mail push and global push
documentation for Telegram Bot.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 21:45:05 +08:00
Dream Hunter
c5893a2944 chore: upgrade dependencies (#881)
* chore: upgrade dependencies

- dompurify 3.3.1 → 3.3.2
- naive-ui 2.43.2 → 2.44.0
- vue-i18n 11.2.8 → 11.3.0
- @cloudflare/workers-types 4.20260305.1 → 4.20260307.1
- @types/node 25.3.3 → 25.3.5
- wrangler 4.70.0 → 4.71.0 (all subprojects)

* feat: upgrade @simplewebauthn packages from v10 to v13

Breaking changes addressed:
- [v11] startRegistration/startAuthentication now take object param
- [v11] registrationInfo.credential replaces flat destructuring
- [v11] authenticator param renamed to credential in verifyAuthenticationResponse
- [v13] @simplewebauthn/types removed, types imported from @simplewebauthn/server

Packages:
- @simplewebauthn/server: 10.0.1 → 13.2.3
- @simplewebauthn/browser: 10.0.0 → 13.2.2
- @simplewebauthn/types: removed (deprecated)

* test: add passkey API E2E tests

- User registration and login flow
- register_request/authenticate_request return valid WebAuthn options
- authenticate_response with invalid credential returns 404
- register_response with invalid credential returns error
- Passkey list empty for new user
- Rename/delete operations with validation

* fix: use UI login instead of localStorage injection in browser passkey test

The localStorage approach doesn't work with VueUse's useStorage because
it doesn't detect external changes during page navigation.

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

* fix: hash password before registration to match frontend login behavior

The frontend hashes passwords with SHA-256 before sending to the API.
Registration via API must use the same hashed password so that UI login
matches the stored value.

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

* fix: allow crypto.subtle in Docker browser tests

The frontend uses crypto.subtle for password hashing, which requires
a secure context (HTTPS or localhost). In Docker, the frontend runs
at http://frontend:5173 which is not a secure context. Add Chromium
flag to treat this origin as secure.

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

* fix: serve frontend over HTTPS in Docker for WebAuthn secure context

WebAuthn (navigator.credentials) and crypto.subtle both require a
secure context (HTTPS or localhost). The Docker frontend was serving
over HTTP, making passkey operations impossible.

Changes:
- Generate self-signed cert in Dockerfile.frontend
- Configure Vite to serve over HTTPS
- Update FRONTEND_URL to https://
- Add ignoreHTTPSErrors to Playwright browser config
- Use localStorage injection for passkey test login

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

* fix: add Vite proxy to avoid mixed-content blocking in HTTPS Docker frontend

HTTPS pages cannot make HTTP API requests (mixed content). Add a Vite
proxy for all API paths so the browser makes same-origin HTTPS requests,
which Vite proxies to the HTTP worker server-to-server.

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

* fix: store userJwt without JSON.stringify in localStorage

VueUse's useStorage with a string default uses raw string serialization
(no JSON wrapping). Using JSON.stringify added double quotes around the
JWT token, causing 401 Unauthorized from the worker.

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

* refactor: clean up passkey API test per review feedback

Remove unused variables and rename test to match actual behavior.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 02:18:17 +08:00
Dream Hunter
5f3762ef58 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>
2026-03-08 19:08:06 +08:00
Bowl42
fca9bade48 feat: add webhook preset templates for Message Pusher, Bark, and ntfy (#877) 2026-03-06 19:53:08 +08:00
Bowl42
635e0f4456 chore(deps): bump dompurify from 3.3.1 to 3.3.2 in /frontend (#874)
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>
2026-03-06 12:46:57 +08:00
Dream Hunter
2f8183e024 fix: correct API path typo requset → request (#869)
* fix: correct API path typo `requset_send_mail_access` → `request_send_mail_access`

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

* fix: correct typo in send-access E2E test (requset → request)

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 22:33:06 +08:00
Dream Hunter
3df55dce91 chore: upgrade dependencies across all subprojects (#861) 2026-03-05 20:27:59 +08:00
Bowl42
0c337a1942 fix: sanitize mail content in reply/forward to prevent XSS (#857)
* 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>
2026-03-04 23:30:43 +08:00
Bowl42
372f7b4149 fix: preserve HTML content when replying to HTML emails (#856)
* 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>
2026-03-04 22:51:27 +08:00
Bowl42
abad88b986 fix: improve email content readability in dark mode (#855) 2026-03-04 20:52:19 +08:00
Dream Hunter
f55e8c9818 feat: add configurable Status menu button (#851) 2026-03-03 12:58:49 +08:00
Dream Hunter
bafd003cbd chore: upgrade dependencies (#842)
chore: upgrade dependencies across frontend, worker, pages and docs

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 14:05:12 +08:00
Dream Hunter
723e1fe75d feat: add ip.im link for source IP in admin account list (#841) 2026-02-25 13:59:53 +08:00
Dream Hunter
566c6536d1 docs: fix user API auth and add admin delete API docs (#836) 2026-02-16 15:49:26 +08:00
Dream Hunter
bde08b9d55 feat: add email regex validation for user registration (#835) 2026-02-16 12:40:20 +08:00
Dream Hunter
56351ed963 style: improve empty state display for inbox and sent box (#831)
- Add different messages based on mail count (empty vs select)
- Add semantic icons (InboxRound for inbox, SendRound for sent)
- Unify list container height to min-height: 60vh; max-height: 100vh
- Update CHANGELOG for v1.4.0

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 23:47:49 +08:00
Dream Hunter
9583f0e1c5 feat: upgrade version to v1.4.0 (#830) 2026-02-02 22:15:58 +08:00
Dream Hunter
0f418d7e94 feat: hide send mail UI when not configured (#827)
- Add isSendMailEnabled and isAnySendMailEnabled functions in common.ts
- Return enableSendMail field in /open_api/settings
- Hide sendmail tab, sendbox tab, and reply button when send mail is not configured
- Check RESEND_TOKEN, SMTP_CONFIG, and SEND_MAIL binding per domain

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 23:37:51 +08:00
Dream Hunter
e4b6c82e92 perf: use waitUntil for async address activity updates (#826)
- 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>
2026-02-01 21:20:39 +08:00
Dream Hunter
d367bc92b2 feat(oauth2): add SVG icon support for OAuth2 providers (#825)
- Add optional `icon` field to UserOauth2Settings type
- Include preset SVG icons for GitHub, Linux Do, and Authentik templates
- Render icons on OAuth2 login buttons
- Add icon configuration UI with preview in admin panel

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 21:00:15 +08:00
Dream Hunter
decede7ed3 feat(oauth2): add email format transformation support (#818)
* 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>
2026-01-23 21:30:44 +08:00
Dream Hunter
e4c96c9868 style: use softer blue for AI extraction info in dark mode (#817)
- Use Gmail's #A8C7FA color for AI extraction alert and tag in dark mode
- Update CHANGELOG.md and CHANGELOG_EN.md for v1.2.1

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 20:20:06 +08:00
Dream Hunter
2318e0f7e2 fix: scheduled task cleanup error - upgrade to v1.2.1 (#816)
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>
2026-01-19 20:05:06 +08:00
Dream Hunter
8964d4461d feat: add admin account page with logout and responsive address bar (#803)
- Add admin account tab to display current login method
- Support logout for admin password login only
- Show login method (password/user admin/disabled check)
- Improve address bar responsive layout with auto-wrap
- Update changelog for new features

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

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 19:16:39 +08:00
Dream Hunter
a771446b9b Unify address selection UI (#801)
* feat: unify address selection UI

* docs: update changelog for address UI

* feat: restore user mailbox tab
2026-01-01 21:14:07 +08:00
Dream Hunter
50ab6756bd fix: remove invalid escape sequences in i18n placeholders (#800)
- Remove backslashes from source_patterns_placeholder in both en and zh
- Fix vue-i18n SyntaxError: 10 (invalid escape sequence)
- Change placeholder from 'e.g. @gmail\\.com$' to 'e.g. gmail.com'

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

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-31 02:13:32 +08:00
Dream Hunter
aee1f1942b fix: ensure emailForwardingList is always initialized (#799)
- Fix emailRuleSettings initialization to ensure emailForwardingList is always an array
- Prevent SyntaxError when adding new forwarding rules with incomplete backend data
- Use optional chaining to safely access emailRuleSettings fields

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

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-31 02:04:42 +08:00
Dream Hunter
5e227d2b2d feat: add source address regex forwarding (#796)
feat: add source address regex forwarding for email rules

- Add sourcePatterns field to filter forwarding by sender address regex
- Support 'any' and 'all' match modes for multiple patterns
- Add ReDoS protection with 200 character limit
- Frontend validation for regex patterns
- Fully backward compatible with existing configurations

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-29 17:15:24 +08:00
Dream Hunter
3b3968f3b4 feat: add address source tracking (source_meta field) (#794)
- Add source_meta field to address table for tracking creation source
- Web: records client IP address (with fallback to 'web:unknown')
- Telegram: records 'tg:{userId}'
- Admin: records 'admin'
- Add database migration with field existence check
- Add frontend display in admin Account page
- Backward compatible: fallback if field doesn't exist

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-28 13:44:52 +08:00
Dream Hunter
24366e2bff feat: improve mailbox UI spacing and email display (#788) 2025-12-15 13:35:03 +08:00
Dream Hunter
e5f62d4713 feat: optimize email filtering with frontend-only search (#787)
* 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>
2025-12-15 02:55:50 +08:00
Dream Hunter
1836f931ee fix: move useScript to top level for @unhead/vue v2 compatibility (#785)
Move useScript call outside onMounted to avoid context loss in async callbacks

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-12 16:24:31 +08:00
Dream Hunter
0f2836eebb feat: upgrade version to v1.2.0 (#784)
* 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>
2025-12-12 00:10:20 +08:00
Dream Hunter
b933aef7d9 fix: escape @ symbol in vue-i18n to fix SyntaxError (#783)
fix: escape @ symbol in vue-i18n translation strings

The @ symbol is interpreted as linked message syntax in vue-i18n,
causing SyntaxError when parsing. Use {'@'} to escape it.

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

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 23:56:00 +08:00
Dream Hunter
fa72d7187f feat: v1.1.0 release with AI email extraction and security enhancements (#782)
fix: initialize customSqlCleanupList to empty array if undefined

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

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 23:45:23 +08:00
Dream Hunter
d15a4904a5 feat: add custom SQL cleanup for scheduled maintenance (#781)
- Add CustomSqlCleanup type to models
- Add validateCustomSql and executeCustomSqlCleanup functions
- Add SQL validation: DELETE only, single statement, max 1000 chars
- Integrate custom SQL cleanup with scheduled job
- Add frontend UI with tabs for basic/custom SQL cleanup
- Support i18n for English and Chinese

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-11 23:33:33 +08:00
Dream Hunter
abe812666f fix: display auth_code result directly without result_text (#777)
- Ensure verification codes always show the raw result value
- Links continue to prefer result_text as display label
- Fixes display logic in both compact and full modes
2025-12-06 16:37:01 +08:00
Dream Hunter
dbb55d948f feat: add AI email extraction with Cloudflare Workers AI
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>
2025-12-06 16:28:19 +08:00
Dream Hunter
793901d349 fix: 修复自定义认证密码功能异常 (#771)
fix: 修复自定义认证密码功能异常的问题

- 修复前端属性名错误 (openSettings.auth -> openSettings.needAuth)
- 修复 /open_api/settings 接口被自定义认证拦截的问题

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

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-23 23:31:23 +08:00
Dream Hunter
113f9ad66b 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>
2025-11-13 17:57:35 +08:00