Commit Graph

596 Commits

Author SHA1 Message Date
Dream Hunter
d1fb1f773b Fix send mail form validation (#989)
* fix: harden send mail form validation

* fix: tighten send mail content checks

* fix: refine send mail empty-content checks

* fix: reset send mail preview state
2026-04-18 15:29:48 +08:00
Dream Hunter
5c40eeec80 docs: add SEND_MAIL_DOMAINS docs (#988) 2026-04-18 12:28:15 +08:00
Dream Hunter
000cd0ddfa fix: limit SEND_MAIL domain checks to binding paths (#987)
* fix: scope SEND_MAIL domain gating to binding

* test: cover SEND_MAIL domain gating in e2e
2026-04-17 18:08:19 +08:00
Dream Hunter
e772db8c3e feat: add SEND_MAIL delivery and quota controls (#986)
* feat: add SEND_MAIL delivery and quota controls

* test: cover -1 unlimited runtime for send mail quota

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

* fix: split send limit validation and save

* refactor: move send limit counters to settings

* fix: polish send mail limit review follow-ups

* docs: note SEND_MAIL breaking change

* test: align send mail limit e2e with new messages

* fix: address review follow-ups

* fix: harden admin send mail handlers

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-17 11:37:14 +08:00
Dream Hunter
a5aa475380 chore: upgrade dependencies and bump version to v1.7.0 (#982)
- Upgrade deps across frontend/worker/pages/vitepress-docs (wrangler 4.82.2, dompurify 3.4.0, resend 6.11.0, etc.)
- Bump version to v1.7.0 in all package.json and worker constants
- Add v1.7.0 CHANGELOG placeholder; move #978/#930 Bug Fixes from v1.6.0 to v1.7.0 (merged after v1.6.0 tag)
- Add upgrade-dependencies skill; translate version-upgrade skill to English

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 20:13:40 +08:00
jiaxin
3221f5ae30 fix: lowercase configured address prefixes (#980)
* fix: normalize address casing for password login

Store new mailbox addresses in lowercase and migrate historical address data so mixed-case password logins can read inbox, sendbox, and settings consistently.

* fix: only lowercase configured address prefixes

Limit the #930 change to prefix normalization and document that existing mixed-case data must be migrated manually by users.
2026-04-14 15:59:25 +08:00
jiaxin
15e339282d fix: respect user mail deletion toggle in user center (#979)
* fix: respect user mail deletion toggle in user center

Hide user mailbox delete actions and block /user_api/mails deletion when ENABLE_USER_DELETE_EMAIL is disabled. Add an e2e regression test and changelog entries for issue #978.

* test: hash user password in mail deletion e2e

Use the same SHA-256 pre-hashed password format as the frontend for the user register/login flow in the mail deletion regression test.
2026-04-14 15:25:39 +08:00
dreamhunter2333
e15b1b83d0 ci: upgrade to upload-artifact@v7 and download-artifact@v8 for Node.js 24 v1.6.0 2026-04-12 21:26:22 +08:00
dreamhunter2333
c297a49b2a ci: upgrade upload/download-artifact to v4 for Node.js 24 compatibility 2026-04-12 21:24:14 +08:00
dreamhunter2333
de3f9e92ed fix: add checkout step to release job in tag_build workflow 2026-04-12 21:22:05 +08:00
Dream Hunter
832e996dd8 docs: add missing PR #968 to CHANGELOG (#976) 2026-04-12 21:14:09 +08:00
Dream Hunter
e81c9d0d9c docs: add SPA settings screenshot (#975) 2026-04-12 21:03:05 +08:00
Dream Hunter
163df5c908 chore: update dependencies (#974)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 21:11:25 +08:00
Dream Hunter
c3058817ff feat(admin): add IP whitelist (strict allowlist mode) (#920) (#971)
* feat(admin): add IP whitelist (strict allowlist mode) (#920)

- Add enableWhitelist/whitelist fields to IpBlacklistSettings
- Implement three-layer access control: whitelist → blacklist → daily limit
- Whitelist uses exact match for IPv4/IPv6, regex for patterns
- Whitelisted IPs skip blacklist checks (trusted)
- Fail-closed when cf-connecting-ip missing under whitelist mode
- Frontend: independent whitelist toggle + empty list protection
- Backend: backward compatible (old frontends get defaults)
- E2E tests: config validation + runtime behavior
- Docs: CHANGELOG zh/en updated

Closes #920

* fix(admin): address PR review feedback on IP whitelist

- Add IPv4-mapped IPv6 (::ffff:x.x.x.x) exact match in isWhitelisted
- Include error.message in whitelist regex parse failure log
- Include actual/max size in whitelist size limit error message

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

* fix(admin): validate whitelist regex on save and preserve existing whitelist on partial update

- Reject invalid regex patterns in whitelist at save time to prevent runtime lockout
- Preserve existing enableWhitelist/whitelist from DB when older clients omit these fields

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

* fix(admin): revert P2 - keep simple ?? defaults for backward compat

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

* fix(admin): validate whitelist elements are strings before trimming

Prevents 500 error when whitelist contains non-string elements (e.g. numbers, null)

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

* docs(admin): add IP blacklist/whitelist documentation (zh + en)

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

* fix(admin): fix fingerprint blacklist bypass when cf-connecting-ip absent, improve e2e tests

- Split checkBlacklist into checkFingerprintBlacklist (IP-independent) and checkIpAsnBlacklist
- Fingerprint check now runs before the !reqIp early-return to prevent bypass
- Add afterEach reset to config test group, extract RESET_SETTINGS constant
- Strengthen whitelist-blocks test to deterministic 403 assertion
- Add e2e tests: invalid regex rejection, non-string element rejection, fingerprint-blocks-without-IP

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

* fix(admin): suppress no-useless-escape lint warning in whitelist regex check

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 21:06:13 +08:00
dependabot[bot]
16c4e43871 chore(deps): bump nodemailer and imapflow in /e2e (#963)
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) and [imapflow](https://github.com/postalsys/imapflow). These dependencies needed to be updated together.

Updates `nodemailer` from 8.0.4 to 8.0.5
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v8.0.4...v8.0.5)

Updates `imapflow` from 1.2.18 to 1.3.1
- [Release notes](https://github.com/postalsys/imapflow/releases)
- [Changelog](https://github.com/postalsys/imapflow/blob/master/CHANGELOG.md)
- [Commits](https://github.com/postalsys/imapflow/compare/v1.2.18...v1.3.1)

---
updated-dependencies:
- dependency-name: nodemailer
  dependency-version: 8.0.5
  dependency-type: direct:production
- dependency-name: imapflow
  dependency-version: 1.3.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-11 20:16:58 +08:00
dreamhunter2333
68cbfb9c32 Revert "feat(admin): add IP whitelist (strict allowlist mode) (#920)"
This reverts commit e18285d3ef.
2026-04-11 20:11:52 +08:00
dreamhunter2333
e18285d3ef feat(admin): add IP whitelist (strict allowlist mode) (#920)
- Add enableWhitelist/whitelist fields to IpBlacklistSettings
- Implement three-layer access control: whitelist → blacklist → daily limit
- Whitelist uses exact match for IPv4/IPv6, regex for patterns
- Whitelisted IPs skip blacklist checks (trusted)
- Fail-closed when cf-connecting-ip missing under whitelist mode
- Frontend: independent whitelist toggle + empty list protection
- Backend: backward compatible (old frontends get defaults)
- E2E tests: config validation + runtime behavior
- Docs: CHANGELOG zh/en updated

Closes #920
2026-04-11 18:49:09 +08:00
Dream Hunter
1584851a36 docs: note that subdomains need Email Routing enabled separately (#970)
Subdomains do not inherit Email Routing from the apex domain;
each subdomain must enable Email Routing and configure its own
DNS records and Catch-all rule.

Refs #969

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 16:32:20 +08:00
YewFence
1cafbbf220 feat(address): 支持最大地址数量设置为 0 表示无限制 (#968)
* feat(address): 支持最大地址数量设置为 0 表示无限制

- 移除角色配置中 =0 时回退到全局设置的逻辑
- 添加负数校验防止无效输入
- 更新前端文案说明 0 表示无限制

* fix(admin): 修复 maxAddressCount 验证逻辑,禁止负数和非对象输入

在 saveRoleAddressConfig 接口增加 configs 参数类型校验,
确保其为有效对象而非数组或 null。同时在 UserSettings 模型中
验证 maxAddressCount 必须大于等于 0,防止无效数据进入系统。

* style: 修正错误的缩进
2026-04-09 17:04:58 +08:00
Dream Hunter
873a10ddb1 docs: simplify D1 naming guidance (#961) 2026-04-08 01:26:28 +08:00
Dream Hunter
9689a1cbca docs: clarify Pages backend URL config (#960)
* docs: clarify pages backend url setup

* docs: refine pages and d1 examples

* docs: harden pages zip generator
2026-04-07 23:59:31 +08:00
Dream Hunter
ef475bab21 chore: upgrade frontend and worker dependencies (#959)
chore: upgrade project dependencies
2026-04-07 19:37:34 +08:00
Dream Hunter
e6ef110ec9 fix: avoid D1 LIKE pattern length limit on admin search (#956) (#957)
D1 caps LIKE/GLOB pattern length at 50 bytes. /admin/address and
/admin/users wrapped the query as `%${query}%` and fed it to LIKE,
so searching by a full email address crashed with "LIKE or GLOB
pattern too complex". Fall back to instr() above the 50-byte
threshold.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 19:23:26 +08:00
Dream Hunter
42281cdc49 ci: upgrade GitHub Actions to support Node.js 24 (#951)
* ci: upgrade GitHub Actions to support Node.js 24

- pnpm/action-setup: v4 → v5
- actions/upload-artifact: v4 → v6
- actions/download-artifact: v4 → v6
- sync.yaml: replace inactive aormsby/Fork-Sync-With-Upstream-action with gh repo sync

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

* ci: replace softprops/action-gh-release with gh release CLI

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

* fix(ci): use gh release upload instead of create for existing releases

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 21:44:07 +08:00
Dream Hunter
5248c03b6c docs: restructure sidebar, expand FAQ, enhance send mail docs (#949)
* docs: restructure sidebar, expand FAQ, enhance send mail docs

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

* docs: remove specific example domain reference in FAQ per review

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 11:47:25 +08:00
Dream Hunter
b86d1faac4 docs: update missing documentation from closed issues (#948)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 11:11:44 +08:00
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
Dream Hunter
f08d062b32 docs: clarify ENABLE_MAIL_GZIP guidance (#938) v1.5.0 2026-04-04 19:12:07 +08:00
Dream Hunter
8885948291 docs: add ENABLE_MAIL_GZIP to wrangler.toml.template (#937)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 18:51:58 +08:00
Dream Hunter
7c6d0d7c8a feat(mail): support gzip compressed email storage via ENABLE_MAIL_GZIP (#933)
* feat(mail): support gzip compressed email storage in D1 raw_blob column

Add ENABLE_MAIL_GZIP env var to optionally gzip-compress incoming emails
into a new raw_blob BLOB column, saving D1 storage space. Reading is
backward-compatible: prioritizes raw_blob (decompress) with fallback to
plaintext raw field. Includes DB migration v0.0.7, docs, and changelogs.

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

* fix: gzip fallback on missing column + decouple resolve from handleListQuery

- email/index.ts: gzip INSERT failure now falls back to plaintext INSERT
  instead of silently losing the email (P1: data loss prevention)
- common.ts: add handleMailListQuery for raw_mails-specific list queries
  with resolveRawEmailList, keeping handleListQuery generic
- Replace handleListQuery → handleMailListQuery in mails_api, admin_mail_api,
  user_mail_api (only raw_mails callers)
- Add e2e test infrastructure: worker-gzip service, wrangler.toml.e2e.gzip,
  api-gzip playwright project, mail-gzip.spec.ts with 4 test cases

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

* fix: address CodeRabbit review feedback for gzip feature

- Use destructuring in resolveRawEmailRow to truly remove raw_blob key
- Narrow fallback scope: only fallback to plaintext on compression failure
  or missing raw_blob column, re-throw other DB errors
- Clean unused imports in e2e gzip test

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

* fix: add try-catch in resolveRawEmail to prevent single corrupt blob from failing entire list

A corrupted raw_blob would cause decompressBlob to throw, which with
Promise.all in resolveRawEmailList would reject the entire batch query.
Now catches decompression errors and falls back to row.raw field.

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

* fix(mail): align sendAdminInternalMail with gzip storage path

sendAdminInternalMail now respects ENABLE_MAIL_GZIP: compresses to
raw_blob when enabled, with fallback to plaintext on failure.
Added e2e test verifying admin internal mail is readable under gzip.

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

* fix(e2e): match admin internal mail by body content instead of encoded subject

mimetext base64-encodes the Subject header, so the raw MIME string
does not contain the literal subject text. Match on body content
(balance: 99) which is plaintext.

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

* fix(e2e): add WORKER_GZIP_URL guard and length assertions in gzip tests

Address CodeRabbit feedback:
- Skip gzip tests when WORKER_GZIP_URL is not set to prevent false positives
- Assert results array length before accessing [0] for clearer error messages

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

* fix(mail): narrow gzip fallback scope and fix webhook query compatibility

- sendAdminInternalMail: separate compress vs DB error handling, only
  fallback to plaintext on compression failure or missing raw_blob
  column, rethrow other DB errors (aligns with email/index.ts)
- Webhook test endpoints: use SELECT * instead of explicit raw_blob
  column reference, so pre-migration databases don't 500
- Docs/changelog: clarify that db_migration must run before enabling
  ENABLE_MAIL_GZIP

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

* fix(telegram): use generic Record type for raw_mails query result

Align with other query sites — avoid hardcoding raw_blob in the
TypeScript type annotation so the query works with or without the
column after migration.

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

* refactor(models): add RawMailRow type and unify raw_mails query typing

Add RawMailRow type to models with raw_blob as optional field, replacing
ad-hoc Record<string, unknown> and inline type annotations across
webhook test endpoints, telegram API, and gzip utilities.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 18:46:39 +08:00
Dream Hunter
53c35062c8 docs: add delete-address api docs (#936) 2026-04-04 18:33:56 +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
dependabot[bot]
be1bf71a47 chore(deps): bump nodemailer and imapflow in /e2e (#916)
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) and [imapflow](https://github.com/postalsys/imapflow). These dependencies needed to be updated together.

Updates `nodemailer` from 8.0.1 to 8.0.4
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v8.0.1...v8.0.4)

Updates `imapflow` from 1.2.12 to 1.2.18
- [Release notes](https://github.com/postalsys/imapflow/releases)
- [Changelog](https://github.com/postalsys/imapflow/blob/master/CHANGELOG.md)
- [Commits](https://github.com/postalsys/imapflow/compare/v1.2.12...v1.2.18)

---
updated-dependencies:
- dependency-name: nodemailer
  dependency-version: 8.0.4
  dependency-type: direct:production
- dependency-name: imapflow
  dependency-version: 1.2.18
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-30 14:55:53 +08:00
BobDLA
424991a165 fix: surface backend deploy errors in GitHub Actions (#917) 2026-03-29 01:48:17 +08:00
Dream Hunter
c97a9a278b docs: clarify Address JWT vs User JWT and reorganize API menu (#914)
- Add warning notes in new-address-api and mail-api docs
- Explain the difference between Address JWT and User JWT
- Create dedicated 'API Endpoints' section in sidebar
- Update both zh and en documentation

Refs #910
2026-03-26 02:10:04 +08:00
Dream Hunter
a45d01f9fd feat: return address_id in /admin/new_address response (#913)
* 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>
2026-03-26 00:18:15 +08:00
Dream Hunter
03965f3612 fix(imap): fix mojibake in nested emails, empty headers, and date handling (#909)
* fix(imap): fix mojibake in nested emails, empty headers, and date handling

- Add line-by-line mojibake fix fallback for complex emails with mixed content
- Apply empty header cleanup globally to fix nested message/rfc822 parts
- Add locale-independent date formatting (format_imap_date, format_rfc2822_date)
- Fill missing Date header from created_at field
- Fix getSubPart for non-multipart messages
- Accept CREATE requests from clients (e.g. Gmail creating Drafts)
- Strip whitespace from IMAP password
- Use MIMEText instead of MIMEMultipart for sent mail generation
- Keep body in original CTE encoding for correct BODYSTRUCTURE
- Update CHANGELOG (zh/en)

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

* docs: consolidate IMAP changelog entries into single line

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 20:52:18 +08:00
greenhandzdl
64d11799b3 fix:Prevent shell from parsing configuration file errors (#908)
* fix:unsuccessful run

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-22 16:47:13 +08:00
dependabot[bot]
10f1f1f32b chore(deps): bump pyopenssl from 25.3.0 to 26.0.0 in /smtp_proxy_server (#902)
Bumps [pyopenssl](https://github.com/pyca/pyopenssl) from 25.3.0 to 26.0.0.
- [Changelog](https://github.com/pyca/pyopenssl/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/pyopenssl/compare/25.3.0...26.0.0)

---
updated-dependencies:
- dependency-name: pyopenssl
  dependency-version: 26.0.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-19 20:32:10 +08:00
Dream Hunter
e77ab12140 docs: clarify mail API raw payload semantics (#906)
docs: clarify mail API returns raw RFC822 content
2026-03-19 20:31:22 +08:00
Dream Hunter
79b9835fa2 docs: add changelog for OAuth2 sessionStorage fallback (#900) (#901)
* docs: add changelog for OAuth2 sessionStorage fallback (#900)

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

* docs: mention Android via browser in changelog

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 00:07:58 +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
eeea512ab1 fix: use native fetch for Telegram attachment upload (#898)
* fix: use native fetch for Telegram attachment upload

telegraf's sendMediaGroup uses Node.js streams (multipart-stream) for
file uploads, which is incompatible with CF Workers runtime, causing
"SyntaxError: Unexpected end of JSON input".

Replace with native fetch + FormData + attach:// protocol which works
correctly in CF Workers.

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

* fix: wrap sendTelegramAttachments in top-level try-catch

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 03:15:04 +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
e7df77cac0 fix: update address timestamp on send mail and refactor TG attachment guard (#896)
fix: update address timestamp on send mail, refactor TG attachment guard

- Call updateAddressUpdatedAt after successful send mail to keep
  address activity timestamp up to date
- Refactor Telegram attachment push: replace early return with if block
  to prevent skipping future logic after attachment section

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 02:39:18 +08:00
Dream Hunter
9ee21da8a9 feat: support attachment push for Telegram and Webhook (#895)
* feat: support attachment push for Telegram and Webhook (#894)

- Parse email attachments via postal-mime in commonParseMail
- Send attachments via Telegram Bot API sendDocument after text message
- Include base64-encoded attachments in webhook payload
- Add e2e tests for webhook attachment push
- Add i18n messages for attachment-related notifications

Closes #894

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

* refactor: remove user-facing error message for failed attachment send

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

* refactor: remove unused i18n attachment messages

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

* refactor: use sendMediaGroup for batch attachment sending

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

* refactor: remove redundant commonParseMail call, use cached result

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

* refactor: remove webhook attachment support, raw already contains attachments

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

* fix: use sendDocument for single attachment, sendMediaGroup for 2+

Telegram sendMediaGroup requires 2-10 items minimum. Use sendDocument
for single attachment case. Update CHANGELOG with 50MB limit info.

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

* fix: batch sendMediaGroup in groups of 9, add attachments to wasm parser

Telegram sendMediaGroup supports 2-10 items. Batch large attachment
lists into groups of 9. Also add attachments field to commented-out
wasm parser for future compatibility.

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

* feat: add caption to attachment messages, update wasm patch

Add email sender and subject as caption on Telegram attachment messages.
Caption is shown on the first attachment only for sendMediaGroup.
Update wasm parser patch to include attachments field mapping, and fix
wasm comment to use correct field names (content_type, content as
Uint8Array directly).

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

* refactor: unify attachment sending with sendMediaGroup for all cases

sendMediaGroup works with 1+ files (tested). Remove sendDocument
special case and always use sendMediaGroup with batching.

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

* chore: reduce sendMediaGroup batch size to 6

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

* chore: change WASM parse email comment from TODO to NOTE

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

* chore: regenerate wasm parser patch with attachments support

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

* feat: add ENABLE_TG_PUSH_ATTACHMENT env var to control attachment push

Add environment variable to enable/disable Telegram attachment push
(default disabled). Update type definitions, wrangler template,
worker-vars docs (zh/en), telegram feature docs (zh/en), and
changelogs.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 02:10:48 +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