mirror of
https://github.com/dreamhunter2333/cloudflare_temp_email.git
synced 2026-05-06 20:32:55 +08:00
Compare commits
2 Commits
03965f3612
...
c97a9a278b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c97a9a278b | ||
|
|
a45d01f9fd |
@@ -10,6 +10,7 @@
|
||||
|
||||
### Features
|
||||
|
||||
- feat: |Admin API| `/admin/new_address` 接口返回值新增 `address_id` 字段,避免创建后需再次查询地址 ID(#912)
|
||||
- feat: |自动回复| 发件人过滤支持正则表达式匹配,使用 `/pattern/` 语法(如 `/@example\.com$/`),同时保持前缀匹配的向后兼容
|
||||
- feat: |Turnstile| 新增全局登录表单 Turnstile 人机验证,通过 `ENABLE_GLOBAL_TURNSTILE_CHECK` 环境变量控制(#767)
|
||||
- feat: |Telegram| Telegram 推送支持发送邮件附件(单文件限制 50MB),多附件通过 `sendMediaGroup` 批量发送,通过 `ENABLE_TG_PUSH_ATTACHMENT` 环境变量开启(#894)
|
||||
@@ -26,6 +27,7 @@
|
||||
|
||||
### Docs
|
||||
|
||||
- docs: |API| 新增地址 JWT 与用户 JWT 的区分说明,避免混淆两种认证方式;调整文档菜单结构,将 API 接口文档归类到独立分组(#910)
|
||||
- docs: |Telegram| 新增每用户邮件推送和全局推送功能说明文档(#769)
|
||||
- docs: |Webhook| 新增 Telegram Bot、企业微信、Discord 等常用推送平台的 Webhook 模板示例
|
||||
- feat: |Webhook| 前端预设模板新增 Telegram Bot、企业微信、Discord 三个模板
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
### Features
|
||||
|
||||
- feat: |Admin API| `/admin/new_address` endpoint now returns `address_id` field, avoiding additional query after address creation (#912)
|
||||
- feat: |Auto Reply| Add regex matching support for sender filter using `/pattern/` syntax (e.g. `/@example\.com$/`), backward compatible with prefix matching
|
||||
- feat: |Turnstile| Add global Turnstile CAPTCHA for all login forms via `ENABLE_GLOBAL_TURNSTILE_CHECK` env var (#767)
|
||||
- feat: |Telegram| Support sending email attachments in Telegram push (50MB per file limit), multiple attachments sent via `sendMediaGroup`, controlled by `ENABLE_TG_PUSH_ATTACHMENT` env var (#894)
|
||||
@@ -26,6 +27,7 @@
|
||||
|
||||
### Docs
|
||||
|
||||
- docs: |API| Add clarification between Address JWT and User JWT to avoid confusion; reorganize documentation menu structure with dedicated API Endpoints section (#910)
|
||||
- docs: |Telegram| Add per-user mail push and global push documentation (#769)
|
||||
- docs: |Webhook| Add webhook template examples for Telegram Bot, WeChat Work, Discord and other common push platforms
|
||||
- feat: |Webhook| Add Telegram Bot, WeChat Work, Discord preset templates to frontend webhook settings
|
||||
|
||||
@@ -16,7 +16,7 @@ export async function createTestAddress(
|
||||
ctx: APIRequestContext,
|
||||
name: string,
|
||||
domain: string = TEST_DOMAIN
|
||||
): Promise<{ jwt: string; address: string }> {
|
||||
): Promise<{ jwt: string; address: string; address_id: number }> {
|
||||
const uniqueName = `${name}${Date.now()}`;
|
||||
const res = await ctx.post(`${WORKER_URL}/api/new_address`, {
|
||||
data: { name: uniqueName, domain },
|
||||
@@ -25,7 +25,7 @@ export async function createTestAddress(
|
||||
throw new Error(`Failed to create address: ${res.status()} ${await res.text()}`);
|
||||
}
|
||||
const body = await res.json();
|
||||
return { jwt: body.jwt, address: body.address };
|
||||
return { jwt: body.jwt, address: body.address, address_id: body.address_id };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,9 +4,10 @@ import { WORKER_URL, TEST_DOMAIN, createTestAddress, deleteAddress, requestSendA
|
||||
test.describe('Address Lifecycle', () => {
|
||||
test('create address, request send access, fetch settings, then delete', async ({ request }) => {
|
||||
// Create address
|
||||
const { jwt, address } = await createTestAddress(request, 'lifecycle-test');
|
||||
const { jwt, address, address_id } = await createTestAddress(request, 'lifecycle-test');
|
||||
expect(address).toContain('@' + TEST_DOMAIN);
|
||||
expect(jwt).toBeTruthy();
|
||||
expect(address_id).toBeGreaterThan(0);
|
||||
|
||||
// Request send access (creates address_sender row with DEFAULT_SEND_BALANCE)
|
||||
await requestSendAccess(request, jwt);
|
||||
|
||||
19
e2e/tests/api/admin-new-address.spec.ts
Normal file
19
e2e/tests/api/admin-new-address.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { WORKER_URL, TEST_DOMAIN } from '../../fixtures/test-helpers';
|
||||
|
||||
test.describe('Admin New Address', () => {
|
||||
test('should return address_id in response', async ({ request }) => {
|
||||
const uniqueName = `admin-test${Date.now()}`;
|
||||
const res = await request.post(`${WORKER_URL}/admin/new_address`, {
|
||||
data: { name: uniqueName, domain: TEST_DOMAIN },
|
||||
});
|
||||
|
||||
expect(res.ok()).toBe(true);
|
||||
const body = await res.json();
|
||||
|
||||
expect(body.address).toContain('@' + TEST_DOMAIN);
|
||||
expect(body.jwt).toBeTruthy();
|
||||
expect(body.address_id).toBeGreaterThan(0);
|
||||
expect(typeof body.address_id).toBe('number');
|
||||
});
|
||||
});
|
||||
@@ -149,19 +149,25 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
|
||||
items: [
|
||||
{ text: 'AI Email Recognition', link: 'feature/ai-extract' },
|
||||
{ text: 'Configure SMTP IMAP Proxy', link: 'feature/config-smtp-proxy' },
|
||||
{ text: 'Send Email API', link: 'feature/send-mail-api' },
|
||||
{ text: 'View Email API', link: 'feature/mail-api' },
|
||||
{ text: 'Configure Subdomain Email', link: 'feature/subdomain' },
|
||||
{ text: 'Configure Telegram Bot', link: 'feature/telegram' },
|
||||
{ text: 'Configure S3 Attachments', link: 'feature/s3-attachment' },
|
||||
{ text: 'Configure WASM Email Parser', link: 'feature/mail_parser_wasm_worker' },
|
||||
{ text: 'Configure Webhook', link: 'feature/webhook' },
|
||||
{ text: 'New Address API', link: 'feature/new-address-api' },
|
||||
{ text: 'OAuth2 Third-party Login', link: 'feature/user-oauth2' },
|
||||
{ text: 'Enhance with Other Workers', link: 'feature/another-worker-enhanced' },
|
||||
{ text: 'Add Google Ads', link: 'feature/google-ads.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'API Endpoints',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: 'New Address API', link: 'feature/new-address-api' },
|
||||
{ text: 'View Email API', link: 'feature/mail-api' },
|
||||
{ text: 'Send Email API', link: 'feature/send-mail-api' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Feature Overview',
|
||||
collapsed: false,
|
||||
|
||||
@@ -149,19 +149,25 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
|
||||
items: [
|
||||
{ text: 'AI 邮件识别', link: 'feature/ai-extract' },
|
||||
{ text: '配置 SMTP IMAP 代理服务', link: 'feature/config-smtp-proxy' },
|
||||
{ text: '发送邮件 API', link: 'feature/send-mail-api' },
|
||||
{ text: '查看邮件 API', link: 'feature/mail-api' },
|
||||
{ text: '配置子域名邮箱', link: 'feature/subdomain' },
|
||||
{ text: '配置 Telegram Bot', link: 'feature/telegram' },
|
||||
{ text: '配置 S3 附件', link: 'feature/s3-attachment' },
|
||||
{ text: '配置 worker 使用 wasm 解析邮件', link: 'feature/mail_parser_wasm_worker' },
|
||||
{ text: '配置 webhook', link: 'feature/webhook' },
|
||||
{ text: '新建邮箱地址 API', link: 'feature/new-address-api' },
|
||||
{ text: 'Oauth2 第三方登录', link: 'feature/user-oauth2' },
|
||||
{ text: '配置其他worker增强', link: 'feature/another-worker-enhanced' },
|
||||
{ text: '给网页增加 Google Ads', link: 'feature/google-ads.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'API 接口',
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ text: '新建邮箱地址 API', link: 'feature/new-address-api' },
|
||||
{ text: '查看邮件 API', link: 'feature/mail-api' },
|
||||
{ text: '发送邮件 API', link: 'feature/send-mail-api' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '功能简介',
|
||||
collapsed: false,
|
||||
|
||||
@@ -131,6 +131,14 @@ print(response.json())
|
||||
|
||||
## User Mail API
|
||||
|
||||
::: warning Note: User JWT vs Address JWT
|
||||
This endpoint uses **User JWT** (obtained via `/user_api/login` or `/user_api/register`), with `x-user-token` header.
|
||||
|
||||
**Do not confuse with Address JWT**:
|
||||
- Address JWT uses `Authorization: Bearer <jwt>` to access `/api/*` endpoints
|
||||
- User JWT uses `x-user-token: <jwt>` to access `/user_api/*` endpoints
|
||||
:::
|
||||
|
||||
Supports `address` filter
|
||||
|
||||
```python
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# Create New Email Address API
|
||||
|
||||
::: warning Note: Address JWT vs User JWT
|
||||
This page describes **Address JWT**, which is different from **User JWT**:
|
||||
|
||||
- **Address JWT**: Returned when creating a mailbox via `/api/new_address` or `/admin/new_address`
|
||||
- Use `Authorization: Bearer <jwt>` header
|
||||
- Access `/api/*` endpoints (view mails, delete mails, etc.)
|
||||
|
||||
- **User JWT**: Obtained via `/user_api/login` or `/user_api/register`
|
||||
- Use `x-user-token: <jwt>` header
|
||||
- Access `/user_api/*` endpoints (user account management)
|
||||
|
||||
**Do not confuse these two JWT types!**
|
||||
:::
|
||||
|
||||
## Create Email Address via Admin API
|
||||
|
||||
This is a `python` example using the `requests` library to send emails.
|
||||
|
||||
@@ -131,6 +131,14 @@ print(response.json())
|
||||
|
||||
## user 邮件 API
|
||||
|
||||
::: warning 注意:用户 JWT vs 地址 JWT
|
||||
此接口使用**用户 JWT**(通过 `/user_api/login` 或 `/user_api/register` 获得),使用 `x-user-token` header。
|
||||
|
||||
**请勿与地址 JWT 混淆**:
|
||||
- 地址 JWT 使用 `Authorization: Bearer <jwt>` 访问 `/api/*` 接口
|
||||
- 用户 JWT 使用 `x-user-token: <jwt>` 访问 `/user_api/*` 接口
|
||||
:::
|
||||
|
||||
支持 `address` 过滤
|
||||
|
||||
```python
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# 新建邮箱地址 API
|
||||
|
||||
::: warning 注意:地址 JWT vs 用户 JWT
|
||||
本页面介绍的是**地址 JWT**,与**用户 JWT** 是两种不同的认证方式:
|
||||
|
||||
- **地址 JWT**:通过 `/api/new_address` 或 `/admin/new_address` 创建邮箱时返回
|
||||
- 使用 `Authorization: Bearer <jwt>` header
|
||||
- 用于访问 `/api/*` 接口(查看邮件、删除邮件等)
|
||||
|
||||
- **用户 JWT**:通过 `/user_api/login` 或 `/user_api/register` 获得
|
||||
- 使用 `x-user-token: <jwt>` header
|
||||
- 用于访问 `/user_api/*` 接口(用户账户管理)
|
||||
|
||||
**请勿混淆两种 JWT 的使用方式!**
|
||||
:::
|
||||
|
||||
## 通过 admin API 新建邮箱地址
|
||||
|
||||
这是一个 `python` 的例子,使用 `requests` 库发送邮件。
|
||||
|
||||
@@ -168,7 +168,7 @@ export const newAddress = async (
|
||||
enableCheckNameRegex?: boolean,
|
||||
sourceMeta?: string | undefined | null,
|
||||
}
|
||||
): Promise<{ address: string, jwt: string, password?: string | null }> => {
|
||||
): Promise<{ address: string, jwt: string, password?: string | null, address_id: number }> => {
|
||||
const msgs = i18n.getMessagesbyContext(c);
|
||||
// trim whitespace and remove special characters
|
||||
name = name.trim().replace(getNameRegex(c), '')
|
||||
@@ -247,6 +247,10 @@ export const newAddress = async (
|
||||
`SELECT id FROM address where name = ?`
|
||||
).bind(name).first<number>("id");
|
||||
|
||||
if (!address_id) {
|
||||
throw new Error(msgs.FailedCreateAddressMsg);
|
||||
}
|
||||
|
||||
// 如果启用地址密码功能,自动生成密码
|
||||
const generatedPassword = await generatePasswordForAddress(c, name);
|
||||
|
||||
@@ -259,6 +263,7 @@ export const newAddress = async (
|
||||
jwt: jwt,
|
||||
address: name,
|
||||
password: generatedPassword,
|
||||
address_id: address_id,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user