* feat: return address_id in /admin/new_address response
- Add address_id field to newAddress function return type
- Update CHANGELOG.md and CHANGELOG_EN.md
Fixes#912
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: verify address_id in new_address response
* fix: add address_id validation and improve test coverage
- Add null check for address_id after DB query
- Change address_id to required field in return type
- Add dedicated test for /admin/new_address endpoint
- Update e2e helper return type to non-optional
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* 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>
refactor: modularize IMAP server with fixes and E2E tests
- Modularize IMAP server into imap_server, imap_mailbox, imap_message,
imap_http_client, parse_email, config, models
- Support dual login: JWT token and address+password via backend
- Add STARTTLS support with configurable TLS cert/key
- Fix FETCH/STORE returning UID instead of sequence number (RFC 3501)
- Implement IMessageFile.open() for correct BODY[] raw MIME delivery
- Add UIDNEXT to SELECT response via _cbSelectWork override
- Use per-restart UIDVALIDITY to force client resync
- Pass raw MIME to SimpleMessage for accurate RFC822.SIZE
- Fix SENT mailbox returning empty source
- Handle CREATE command gracefully for Thunderbird compatibility
- Add IMAP E2E tests: auth, LIST, SELECT, STATUS, FETCH, SEARCH,
STORE, UID FETCH, BODY[] integrity, size, seq numbers, SENT mailbox
- Add SMTP E2E tests using nodemailer: send plain/HTML, auth failure,
sendbox verification
- Add sendTestMail helper using admin/send_mail
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: add receive_mail E2E endpoint using real email() handler
Add /admin/test/receive_mail that constructs a mock ForwardableEmailMessage
and calls the real email() handler, so E2E tests exercise the full mail
processing pipeline. Extract both test endpoints into e2e_test_api.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: trigger CI
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* test: add E2E tests for auto-reply settings
Add auto-reply.spec.ts with two test cases:
- GET empty → POST save → GET verify saved fields
- POST with too-long subject returns 400
Enable ENABLE_AUTO_REPLY in E2E wrangler config.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add full fields and body assertion for too-long validation per review
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* 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>