Sanitize HTML announcements in both the About page and startup notification through a shared DOMPurify helper. Add regression tests and bilingual changelog entries.
Co-authored-by: tuanaiseo <tuanaiseo@gmail.com>
Fix IMAP flag persistence so read/unread state survives reconnects, and align SEARCH/FETCH behavior with persisted flags.
Co-authored-by: bounce12340 <bounce12340@users.noreply.github.com>
Cover the junk-mail policy behavior fixed in #1085:
- none/neutral results for SPF/DKIM/DMARC are treated as the method
being absent and do not trigger JUNK_MAIL_CHECK_LIST rejection
- explicit fail results are still rejected
- JUNK_MAIL_FORCE_PASS_LIST only accepts an explicit pass
Run with: node --test-isolation=none --test worker/src/email/junk_mail_policy.test.mjs
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(mailbox): add list view mode
- Add a toggleable list view for the mailbox, with a settings option and back button.
- deselect mail on second click in list view
- set current mail on row click in multi-action mode
* feat(mailbox): add configurable body preview line clamp
Allow users to set the number of preview lines (0–5) for mail body in the list view via a slider in Appearance settings. Includes i18n support for the new option and its "Off" state.
* chore: clarify some i18n message in settings
include the following changes:
- The original "Mailbox Split Size" to "Left list width in two-column mailbox view"
- The description of new feature "Full-width mailbox list view"
sync all languages with the updated message
* docs: update changelog with recent UI improvements
- Added mailbox full-width list view and body preview lines settings
- Extended left panel width ratio range to 0
- Included English changelog translations
* docs: fix CHANGELOG improvements types
* fix: enable mail list preview line clamp settings on mobile
* fix: validate AI extracted link domains
* fix: validate extracted links against full email content
* refactor: simplify AI link domain guard
* refactor: keep AI domain fix prompt-only
docs: add Resend DNS-only proxy warning to send-mail config
Resend domain verification CNAME records must use DNS-only (gray
cloud) on Cloudflare. Proxied (orange cloud) records prevent
verification, and a single failed attempt can take hours before
retry. This is a recurring issue (#515) that the Resend setup
docs did not warn about.
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
* fix: add page header padding for mobile layout
* fix: limit page header padding to mobile layout
* docs: update changelog for mobile header fix
---------
Co-authored-by: dreamhunter2333 <dreamhunter2333@gmail.com>
feat: add regex fallback for verification code extraction without Workers AI
When AI email extraction is enabled but no Workers AI binding is available,
fall back to a built-in, zero-dependency regex extractor so self-hosted
deployments without Workers AI still surface verification codes in Telegram
notifications and webhooks.
- Add worker/src/email/extract_code.ts: rule-based multilingual
(English / Chinese / Japanese / Korean) verification-code extractor with
year and YYYYMMDD date rejection to avoid false positives.
- ai_extract.ts: share the allowlist check and content parsing across both
paths, extract a saveExtractMetadata helper, and use the regex fallback
when env.AI is absent.
- Reuse the existing aiExtractResult pipeline (auth_code type), so Telegram
and webhook output need no changes.
- Update bilingual CHANGELOG and AI-extract feature docs.
Random subdomain mailbox creation only generates addresses; mail delivery
depends on DNS / Cloudflare Email Routing covering *.<base-domain>.
Cloudflare Email Routing does not inherit apex configuration onto
subdomains, so a wildcard `*` MX record on the base domain is required
for random subdomains to actually receive mail.
- Add `[!IMPORTANT]` block in subdomain.md (zh/en) explaining the two
deliverable paths: DNS-only wildcard MX (recommended for random
subdomains) vs Cloudflare dashboard "Add subdomain"
- Link to Cloudflare Email Routing — Subdomains official docs from
worker-vars.md and subdomain.md
- Instruct copying apex MX records to host `*` preserving each record's
priority/target, instead of hardcoding specific MX targets
- Shorten frontend `randomSubdomainTip` for CreateAccount and Login
views (6 locales: zh/en/de/es/ja/pt-BR), drop Markdown backticks
(Vue text interpolation renders them literally), and point users to
the docs instead of embedding DNS instructions
- Trim overlap between existing `[!NOTE]` and new `[!IMPORTANT]` in
subdomain.md
- Update CHANGELOG.md / CHANGELOG_EN.md under v1.9.0(main)
Closes#1035Closes#1026
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix: update AI extract default model
* fix: update e2e worker node version
* fix: use node lts for e2e worker
* fix: align AI model and CI node version
* ci: allow docs deploy without GitHub release
* fix: use workflow run branch for docs tag fallback
---------
Co-authored-by: dreamhunter2333 <dreamhunter2333@gmail.com>
- bump project version metadata to v1.9.0
- refresh npm dependencies and lockfiles across frontend, worker, pages, and docs
- link .agents/skills to .claude/skills
In quick-start / worker-vars / email-routing (zh + en), explicitly
call out that a Cloudflare-hosted domain with Email Routing + Catch-all
must be set up before deploying, and that subdomains do not inherit
the parent domain's Email Routing. Closes#1004.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stale localStorage credentials (`jwt` / `auth` / `adminAuth` / `userJwt` /
`access_token`) can be the empty string, the literal string `"undefined"`,
or carry a stray newline / control character left over from an older
build. axios + undici reject these eagerly with `Invalid character in
header content ["Authorization"]`, so every API call crashes client-side
before reaching the worker.
This adds two tiny helpers in `frontend/src/utils/headers.js`:
- `safeHeaderValue(v)` returns the trimmed value when it is a non-empty
string with no control chars (per RFC 7230) and no `"undefined"` /
`"null"` sentinel; otherwise `undefined`.
- `safeBearerHeader(jwt)` wraps a safe JWT with `Bearer `, otherwise
`undefined`.
`apiFetch` builds the headers object incrementally and only sets each
auth header when its value is safe. Missing/unsafe credentials now drop
out cleanly and the worker returns a normal 401, which the existing
`response.status === 401` flow already handles by surfacing the auth
prompt — the same UX users see on a fresh session.
Tests: `frontend/src/utils/__tests__/headers.test.js` adds 9 vitest
cases covering safe input, sentinel strings, control chars (\\n / \\r /
\\t / NUL / 0x1F / DEL), trimming, and `Bearer` construction. Build
(`pnpm build`) and tests (`pnpm test`) both pass.
Co-authored-by: voidborne-d <voidborne.d@agentmail.to>
Co-authored-by: Dream Hunter <dreamhunter2333@gmail.com>
* feat(i18n): enhance locale handling and routing
- Implemented dynamic locale aliases in router configuration.
- Added support for preferred locale storage in global state.
- Improved locale resolution logic in router beforeEach guard.
- Created utility functions for locale management and path manipulation.
- Added tests for locale matching and message extraction.
- Updated Header component to allow language selection.
- Refactored getRouterPathWithLang to utilize new locale utilities.
- Updated Vite configuration to support aliasing for vue-i18n.
- Bumped version numbers across various packages to 1.9.0.
* feat(i18n): update version to 1.8.0 and enhance locale handling
- Updated version numbers across all package.json files to 1.8.0.
- Enhanced locale handling in App.vue by centralizing locale configurations.
- Improved Turnstile component to support dynamic language rendering.
- Refactored i18n utilities to include initial locale setup and empty locale messages.
- Updated i18n.ts to utilize the new locale management structure.
- Added naive-locale.ts for better integration with Naive UI's locale handling.
- Adjusted Header.vue to streamline language selection and locale changes.
- Fixed translations in multiple locale files for consistency and accuracy.
* fix(i18n): address review feedback
* feat(i18n): update default locale to English and enhance language handling in components
* fix(i18n): switch locale selector to dropdown
* docs: add topbar language and github order design spec
* fix(i18n): 修复 Header 语言切换器相关问题,恢复为独立控件并调整样式
* Refactor locale handling in router and add locale-guard utility functions
- Improved locale resolution logic in router by introducing utility functions for better readability and maintainability.
- Added `locale-guard.js` to encapsulate locale-related functions such as getting route locale, resolving locale for navigation, and applying locale navigation state.
- Updated JWT synchronization logic to streamline the handling of JWT from query parameters.
- Modified i18n messages test to check for coverage of registered locale message keys instead of extracting English source messages.
* 删除顶部栏语言和GitHub顺序设计文档
* fix: 修复前端设置初始化时未返回 domains 数组导致的 undefined 错误
* refactor(i18n): consolidate locale infrastructure
* fix(i18n): stabilize locale route switching
* fix(i18n): persist default locale selection
* fix(i18n): 修复前端设置初始化时未返回 domains 数组导致的 undefined 错误,统一按空数组兜底处理
feat(i18n): 添加 locale 别名处理,支持默认语言的重定向
test(i18n): 增加对默认语言别名重定向的测试用例
* refactor: replace useAppI18n with useScopedI18n in multiple components for improved localization management
* fix(tests): 移除不必要的 URL 断言以简化 Passkey 测试
* fix(i18n): 更新语言切换逻辑,确保使用当前语言设置进行路由导航
* fix(i18n): 强制路由切换以确保语言切换后正确导航
* refactor(i18n): 优化消息注册和路由本地化逻辑,移除冗余代码
* refactor(i18n): 拆分 API 文件以优化路由管理,更新语言处理逻辑
* fix: align i18n release notes and frontend test script
* feat: add cf-temp-mail-usage skill and parsed mail API for AI agents
- feat: new /api/parsed_mails and /api/parsed_mail/:id endpoints returning
server-parsed subject/text/html/attachments metadata (reuses commonParseMail)
- feat: add .claude/skills/cf-temp-mail-usage read-only skill so AI agents
(OpenClaw / Codex / Cursor) can consume a mailbox with a user-supplied JWT,
bypassing the Turnstile challenge required for mailbox creation
- refactor: split mails_api/index.ts and admin_api/index.ts into thin route
shells; move business logic into dedicated *_api.ts files
- docs: update README / README_EN / CHANGELOG with agent-email feature and
npx degit install instructions for the skill
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat: rename skill to cf-temp-mail-agent-mail, add agent-email docs, fix sender trim
- Rename skill from cf-temp-mail-usage to cf-temp-mail-agent-mail
- Rewrite SKILL.md: parsed API primary, local fallback, prerequisites, multi-agent install
- Add vitepress docs (zh + en) for AI Agent mailbox usage
- Fix leading space in parsed_mail_api sender field via .trim()
- Update README install section with 3 install methods
- Update changelogs (zh + en)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* docs: simplify README agent skill section to one-liner with links
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat: add send mail API to skill, credential persistence, remove poll example
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
- Upgrade version to 1.8.0 in all package.json files
- Add cf-temp-mail-release-notify skill with MarkdownV2 Telegram posting
- Optimize docs_deploy.yml to auto-trigger on Tag Build CI completion
- Add v1.8.0 placeholder in CHANGELOG.md and CHANGELOG_EN.md
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>