656 Commits

Author SHA1 Message Date
Dream Hunter
d04c1a865d feat: upgrade version to v1.11.0 (#1100)
- Update version number to 1.11.0 in all package.json files
- Add v1.11.0 placeholder in CHANGELOG.md
- Move (main) marker from v1.10.0 to v1.11.0
2026-07-31 20:52:09 +08:00
Dream Hunter
116ddc7324 feat: add admin mail detail API (#1099)
* feat: add admin mail detail API

* docs: clarify admin mail detail response
v1.10.0
2026-07-31 15:36:00 +08:00
Dream Hunter
2dcbad40ad chore: upgrade e2e dependencies (#1098) 2026-07-31 12:43:29 +08:00
Dream Hunter
95badf5aed chore: upgrade dependencies (#1097) 2026-07-31 11:36:37 +08:00
Dream Hunter
b3666c0900 fix: harden remote content policy edge cases (#1095)
* fix: harden remote content filtering edge cases

* fix: preserve safe escaped CSS

* test: cover unsafe navigation protocols
2026-07-29 15:36:11 +08:00
Josh Tsai
e499211197 feat: add setting to disable auto-loading external images in emails (#1092)
* feat: add setting to disable auto-loading external images in emails

Adds a privacy setting (default off) that blocks remote images in email
content until the user explicitly loads them per message. Blocked images
are replaced with a placeholder; a banner allows one-click loading.

Closes #1073

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

* fix(frontend): block remote content with DOMPurify and an allowlist policy

Address review on the blocking logic. The first pass matched quoted
`<img src="http...">` with a regex, which left unquoted src, srcset,
`<source>`, CSS background-image, SVG `<image href>` and entity-encoded
schemes fetching as usual, and replaced only `src` on an element that also
carried `srcset` -- so the browser still had a remote candidate to prefer
while the UI claimed the image was blocked.

Two changes rather than a wider regex:

Sanitising is delegated to DOMPurify, which is already a dependency. The
hard part here is not enumerating attributes but surviving the parser: a
hand-written pass over a DOMParser tree still missed that `<noscript>` is
parsed as markup where scripting is off and as raw text where it is on, so a
`</noscript>` smuggled into an attribute value reopens the document at
render time and revives an `<img>` the cleaner never saw. Elements that
fetch by themselves or change how relative URLs resolve -- base, meta,
script, link, iframe, object, embed, noscript -- are dropped in this mode.
`<style>` is kept so layout survives, with its url(), image-set() and
@import references filtered.

URL classification is an allowlist. Asking "does this look remote?" means
enumerating every disguise -- backslash authorities, tab/newline/control
characters the URL parser strips, CSS escapes, schemes with no slashes --
and losing to the first one not thought of. Asking "can I prove this is
local?" fails closed instead: cid:, data:image/, blob: and relative paths
are kept, everything else is blocked. Relative paths are only safe because
`<base>` is removed, which is what stopped it re-pointing them at a tracker.

The blocked URL is discarded rather than parked in a data-* attribute, so
"the cleaned body contains no remote URL at all" is directly assertable;
restoring images re-renders from the untouched source.

Also: blob: is added to the allowed schemes -- DOMPurify's default list
omits it, and email-parser rewrites cid: attachments into blob: URLs, so
without it every inline image would be stripped along with the trackers.

The policy lives in its own module with its own tests (30 attack vectors,
7 preservation cases); email-parser.js goes back to MIME parsing only. The
per-mail override no longer initialises from the global setting, and the
banner reports the blocked count as the PR description promised.

Refs #1073

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 14:28:15 +08:00
Dream Hunter
342fe22e4f chore: upgrade dependencies (#1093)
Refresh dependencies and lockfiles across frontend, Worker, Pages, and VitePress documentation packages. Update Wrangler to 4.114.0 and align Cloudflare Workers types with its peer requirements.

Validated with frontend tests/build, Worker build/lint, docs build, and repository E2E.
2026-07-28 18:05:53 +08:00
tuanaiseo
8c883b269f fix(frontend): sanitize announcement HTML (#1039)
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>
2026-07-28 17:49:32 +08:00
Josh Tsai
4c1e593d07 fix(imap-proxy): persist IMAP flags and mark mail as read (#1090)
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>
2026-07-27 20:15:25 +08:00
Josh Tsai
7eaa3b3b8e test: |Worker| add junk_mail_policy regression tests for issue #1084 (#1089)
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>
2026-07-25 20:21:46 +08:00
tura-ai-agent
0581632b59 docs: add Japanese README (#1088)
Add a complete Japanese README and link it from the Chinese and English READMEs.
2026-07-23 15:09:49 +08:00
wlnxing
4ce22ef249 fix: 按规范处理 SPF、DKIM 和 DMARC 认证结果 (#1085)
fix: align SPF, DKIM, and DMARC junk mail checks with RFC standards
2026-07-19 16:13:47 +08:00
Maxim Lapan
99b332345b fix: clean up related mails before deleting address in admin API (#1081)
* fix: clean up related mails before deleting address in admin API

* fix: run admin address deletion in a single D1 batch
2026-07-11 14:06:14 +08:00
Dream Hunter
565bb839db fix: hide mobile preview line setting (#1080) 2026-07-08 14:41:49 +08:00
YewFence
dbd1f8706d feat: 增加全宽列表视图功能 (#1079)
* 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
2026-07-08 14:21:10 +08:00
Dream Hunter
3f1d800e90 fix: validate AI extracted link domains (#1075)
* 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
2026-07-04 16:56:12 +08:00
Dream Hunter
70b30c2494 chore: upgrade Twisted to stable 26.4.0 (#1071)
chore: upgrade twisted to stable 26.4.0
2026-06-25 00:23:17 +08:00
Dream Hunter
1a1dd720c8 chore: upgrade smtp proxy and e2e dependencies (#1069) 2026-06-24 23:59:16 +08:00
Dream Hunter
2d501d82cf chore: upgrade dependencies (#1068) 2026-06-24 23:39:10 +08:00
Chánh Niệm
7c57592742 docs: add Resend DNS-only proxy warning to prevent #515-style verification failures (#1062)
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>
2026-06-19 15:49:03 +08:00
凉心
41105ed803 fix: add page header padding for mobile layout (#1056)
* 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>
2026-06-13 11:39:51 +08:00
Dream Hunter
c924b71a5c fix: compact HTML before AI email extraction (#1057)
fix: compact html before ai extraction
2026-06-12 00:41:19 +08:00
Dream Hunter
4f0b44de2e chore: upgrade Vitest to v4 (#1052)
chore: upgrade vitest to v4
2026-06-03 23:29:56 +08:00
Dream Hunter
f6fcbe793c feat: upgrade version to v1.10.0 (#1051)
- Update version number to 1.10.0 in all package.json files

- Add v1.10.0 placeholder in CHANGELOG.md
2026-06-03 22:14:44 +08:00
Dream Hunter
05a8ebb590 chore: upgrade dependencies (#1050) v1.9.0 2026-06-02 20:39:36 +08:00
Gene Dai
b7718100c5 feat: regex fallback for verification code extraction without Workers AI (#1048)
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.
2026-06-02 15:35:43 +08:00
Dream Hunter
bf786947e3 feat: add AI extract webhook placeholders 2026-05-29 02:27:46 +08:00
Dream Hunter
cfb31807f1 fix: keep Telegram AI extract result on metadata errors (#1045) 2026-05-29 01:48:02 +08:00
Wolf-L
308fbe2f9a feat: show AI extraction results in Telegram
Show AI extraction results in Telegram notifications and /mails views.
2026-05-29 01:13:31 +08:00
Dream Hunter
44b29aa646 feat: hide GitHub links for normal users
Add DISABLE_SHOW_GITHUB_FOR_USER to hide the Header GitHub/version entry from normal users while keeping it visible to admin users. Refs #1041
2026-05-21 23:38:49 +08:00
tuanaiseo
2221342560 fix: sanitize footer copyright html
Sanitize footer copyright HTML before rendering it with v-html.
2026-05-17 15:56:06 +08:00
Hging
add0124cfd fix: normalize domain casing
Fix domain casing normalization for configured domains and inbound recipient domains.
2026-05-16 18:35:39 +08:00
Dream Hunter
8324b133fb docs: clarify wildcard MX requirement for random subdomain (#1036)
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 #1035
Closes #1026

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-14 15:09:32 +08:00
Dream Hunter
74c8e8f7e4 fix: prevent iOS input focus zoom (#1033)
fix: prevent ios input focus zoom
2026-05-10 02:05:31 +08:00
Dream Hunter
2df4de22d9 chore: update SimpleWebAuthn dependencies (#1032)
chore: update simplewebauthn dependencies
2026-05-10 01:54:51 +08:00
Dream Hunter
437db7c050 fix: update AI extract default model
* 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
2026-05-10 01:18:23 +08:00
Dream Hunter
dd294037ab chore: upgrade project dependencies 2026-05-10 00:55:16 +08:00
Charlson
a9e2c89246 ci: allow docs deploy without GitHub release
* ci: allow docs deploy without GitHub release

* fix: use workflow run branch for docs tag fallback

---------

Co-authored-by: dreamhunter2333 <dreamhunter2333@gmail.com>
2026-05-10 00:50:08 +08:00
tar-xz
72bbfe8fd6 docs: fix GitHub Actions title typo
Fix a typo in the Chinese GitHub Actions deployment prerequisite title.
2026-05-01 00:20:17 +08:00
Dream Hunter
796a5e4ac5 feat: improve address credential connections 2026-04-30 15:33:06 +08:00
Dream Hunter
347be5c762 chore: prepare v1.9.0
- 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
2026-04-30 02:03:51 +08:00
Dream Hunter
0b17953097 fix: improve mobile header menu (#1016) v1.8.0 2026-04-29 16:25:15 +08:00
Dream Hunter
ec3e9f0b1f docs: update README feature overview
docs: update readme feature overview
2026-04-29 02:13:17 +08:00
Dream Hunter
fb6e77fded chore: update PR Agent model (#1014)
chore: update pr agent model
2026-04-29 02:07:47 +08:00
Dream Hunter
c703082391 docs: clarify GitHub OAuth email setup
docs: clarify github oauth email setup
2026-04-29 02:04:11 +08:00
Dream Hunter
4e01b4e26f docs: clarify mailbox rebinding and page function actions (#1012)
docs: clarify mailbox rebinding and page functions actions
2026-04-29 01:53:35 +08:00
Dream Hunter
7d68cbdffa docs: improve deployment troubleshooting (#1011)
* docs: improve deployment troubleshooting docs

* docs: fix GitHub casing in FAQ

* docs: clarify subdomain address creation
2026-04-29 01:36:59 +08:00
Lur1n7
6d43c107d8 docs: 添加 CloudMail 移动端管理客户端 (#1007) 2026-04-26 19:47:24 +08:00
Dream Hunter
46fbb4c099 docs: clarify Email Routing setup order (#1006)
docs: clarify email routing setup order
2026-04-25 21:35:14 +08:00
cloverstd
c9698d03f1 docs: highlight that a domain is a prerequisite for deployment (#1005)
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>
2026-04-25 18:57:32 +08:00