diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..615caf2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2025 LaziestRen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
index c0340d2..c5a3289 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,150 @@
-1312
\ No newline at end of file
+
+
+
+
+
+
Cloud Mail
+
+
+
一个使用Vue3开发的响应式简约邮箱服务, 可以部署到Cloudflare云平台实现免费白嫖🎉
+
+
+
+
+
+
+
+## 在线演示
+
+👉 https://skymail.ink
+
+|  |  |
+|---------------------|---------------------|
+|  |  |
+
+
+
+
+
+## 功能介绍
+
+- **💰免费白嫖**:无需服务器,部署到Cloudflare Workers 免费使用,不要钱
+
+- **💻响应式设计**:响应式布局自动适配PC和大部分手机端浏览器
+
+- **🔀多号模式**:开启后一个用户可以添加多个邮箱,默认一用户一邮箱,类似各大邮箱平台
+
+- **📦附件接收**:支持接收附件,使用R2对象存储保存和下载文件
+
+- **⭐星标邮件**:标记重要邮件,以便快速查阅
+
+- **🎨个性化标题**:可以自定义网站标题
+
+- **⏱️轮询刷新**:轮询请求服务器自动获取最新邮件,可自定义间隔
+
+- **⚙️功能开关**:可以对注册,添加等功能关闭和开启,设为私人站点
+
+- **🤖人机验证**:集成Turnstile人机验证,防止伪人批量注册
+
+- **📜更多功能**:正在开发中...
+
+
+
+## 技术栈
+
+- **框架**:[Vue3](https://vuejs.org/) + [Element Plus](https://element-plus.org/)
+
+- **缓存**:[Cloudflare KV](https://developers.cloudflare.com/kv/)
+
+- **数据库**:[Cloudflare D1](https://developers.cloudflare.com/d1/)
+
+- **文件存储**:[Cloudflare R2](https://developers.cloudflare.com/r2/)
+
+- **ORM:**[Drizzle ORM](https://orm.drizzle.team/)
+
+
+
+
+
+## 项目配置
+
+```toml
+[[d1_databases]]
+binding = "db" #d1数据库绑定名默认不可修改
+database_name = "" #d1数据库名字
+database_id = "" #d1数据库id
+
+[[kv_namespaces]]
+binding = "kv" #kv绑定名默认不可修改
+id = "" #kv数据库id
+
+[[r2_buckets]]
+binding = "r2" #r2对象存储绑定名默认不可修改
+bucket_name = "" #r2对象存储桶的名字
+
+
+[assets]
+binding = "assets" #静态资源存放位置默认不可修改
+directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist
+
+[vars]
+domain = [] #邮件域名可可配置多个 示例: ["example1.com","example2.com"]
+admin = "" #管理员的邮箱 示例: admin@example.com
+r2_domain = "" #r2对象存储桶的访问域名
+jwt_secret = "" #jwt令牌的密钥,随便填一串字符串
+site_key = "" #Turnstile人机验证的站点密钥
+secret_key = "" #Turnstile人机验证的后端密钥
+
+```
+
+
+
+## 目录结构
+
+```
+cloud-mail
+├── mail-worker #worker后端项目
+│ ├── src
+│ │ ├── api #后端接口层
+│ │ ├── const #常量
+│ │ ├── email #邮件接收
+│ │ ├── entity #数据库实体层
+│ │ ├── error #自定义异常
+│ │ ├── hono #web框架配置 拦截器等
+│ │ ├── init #项目启动时初始配置
+│ │ ├── model #响应体数据封装
+│ │ ├── security #身份认证层
+│ │ ├── service #服务层
+│ │ ├── utils #工具类
+│ │ └── index.js #入口文件
+│ ├── pageckge.json #项目依赖
+│ └── wrangler.toml #项目配置
+└── mail-vue #vue前端项目
+ ├── src
+ │ ├── assets #静态资源字体等
+ │ ├── axios #axios配置
+ │ ├── components #自定义组件
+ │ ├── day #dayjs配置
+ │ ├── layout #主体布局组件
+ │ ├── request #api接口
+ │ ├── router #路由配置
+ │ ├── store #全局状态管理
+ │ ├── utils #工具类
+ │ ├── views #页面组件
+ │ ├── app.vue #根组件
+ │ ├── main.js #入口js
+ │ └── style.css #全局css
+ ├── package.json #项目依赖
+ └── env.dev #项目配置
+```
+
+
+
+## 许可证
+
+本项目采用 [MIT](LICENSE) 许可证
+
+
+
+
+
diff --git a/demo/demo1.png b/demo/demo1.png
new file mode 100644
index 0000000..e9172b7
Binary files /dev/null and b/demo/demo1.png differ
diff --git a/demo/demo2.png b/demo/demo2.png
new file mode 100644
index 0000000..89a0bd5
Binary files /dev/null and b/demo/demo2.png differ
diff --git a/demo/demo3.png b/demo/demo3.png
new file mode 100644
index 0000000..d79f46d
Binary files /dev/null and b/demo/demo3.png differ
diff --git a/demo/demo4.png b/demo/demo4.png
new file mode 100644
index 0000000..2c4e4c9
Binary files /dev/null and b/demo/demo4.png differ
diff --git a/demo/logo.png b/demo/logo.png
new file mode 100644
index 0000000..0a6f4f2
Binary files /dev/null and b/demo/logo.png differ
diff --git a/mail-worker/src/email/email.js b/mail-worker/src/email/email.js
index 03479b3..59685a9 100644
--- a/mail-worker/src/email/email.js
+++ b/mail-worker/src/email/email.js
@@ -43,6 +43,10 @@ export async function email(message, env, ctx) {
const emailRow = await emailService.receive({ env }, params);
+ if (!env.r2) {
+ console.warn('r2对象存储未配置, 附件取消保存');
+ return;
+ }
if (email.attachments.length > 0) {
@@ -58,11 +62,6 @@ export async function email(message, env, ctx) {
await attService.addAtt({ env }, attachments);
- if (!env.r2) {
- console.log('r2对象存储未配置, 附件取消保存');
- return;
- }
-
for (let attachment of attachments) {
await r2Service.putObj({ env }, attachment.key, attachment.content, {
contentType: attachment.mimeType,
diff --git a/mail-worker/src/index.js b/mail-worker/src/index.js
index f96956a..56afc53 100644
--- a/mail-worker/src/index.js
+++ b/mail-worker/src/index.js
@@ -11,7 +11,7 @@ export default {
return app.fetch(req, env, ctx);
}
- return env.ASSETS.fetch(req);
+ return env.assets.fetch(req);
},
email: email
};
diff --git a/mail-worker/wrangler-dev.toml b/mail-worker/wrangler-dev.toml
index 3ac4967..1c516db 100644
--- a/mail-worker/wrangler-dev.toml
+++ b/mail-worker/wrangler-dev.toml
@@ -11,20 +11,20 @@ ip = "0.0.0.0"
[[d1_databases]]
binding = "db"
database_name = "email"
-database_id = "xxxxx"
+database_id = ""
[[kv_namespaces]]
binding = "kv"
-id = "xxxxx"
+id = ""
[[r2_buckets]]
binding = "r2"
bucket_name = "email"
[vars]
-domain = ["xxxxx", "xxxxx"]
-admin = "xxxxx"
-r2_domain = "xxxxx"
-jwt_secret = "xxxxx"
-site_key = "xxxxx"
-secret_key = "xxxxx"
+domain = ["", ""]
+admin = ""
+r2_domain = ""
+jwt_secret = ""
+site_key = ""
+secret_key = ""
diff --git a/mail-worker/wrangler-test.toml b/mail-worker/wrangler-test.toml
index 294395f..8afe0fa 100644
--- a/mail-worker/wrangler-test.toml
+++ b/mail-worker/wrangler-test.toml
@@ -9,25 +9,25 @@ head_sampling_rate = 1
[[d1_databases]]
binding = "db"
database_name = "email-test"
-database_id = "xxxxx"
+database_id = ""
[[kv_namespaces]]
binding = "kv"
-id = "xxxxx"
+id = ""
[[r2_buckets]]
binding = "r2"
bucket_name = "email-test"
[assets]
+binding = "assets"
directory = "./dist"
-binding = "ASSETS"
[vars]
-domain = ["xxxxx", "xxxxx"]
-admin = "xxxxx"
-r2_domain = "xxxxx"
-jwt_secret = "xxxxx"
-site_key = "xxxxx"
-secret_key = "xxxxx"
+domain = ["", ""]
+admin = ""
+r2_domain = ""
+jwt_secret = ""
+site_key = ""
+secret_key = ""
diff --git a/mail-worker/wrangler.toml b/mail-worker/wrangler.toml
index 8de7a88..be22acd 100644
--- a/mail-worker/wrangler.toml
+++ b/mail-worker/wrangler.toml
@@ -5,14 +5,27 @@ compatibility_date = "2025-04-09"
[observability]
enabled = true
+[[d1_databases]]
+binding = "db" #d1数据库绑定名默认不可修改
+database_name = "" #d1数据库名字
+database_id = "" #d1数据库id
+
+[[kv_namespaces]]
+binding = "kv" #kv绑定名默认不可修改
+id = "" #kv数据库id
+
+[[r2_buckets]]
+binding = "r2" #r2对象存储绑定名默认不可修改
+bucket_name = "" #r2对象存储桶的名字
+
[assets]
-directory = "./dist"
-binding = "ASSETS"
+binding = "assets" #静态资源存放位置默认不可修改
+directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist
[vars]
-domain = ["xxxxx", "xxxxx"]
-admin = "xxxxx@xxxxx"
-r2_domain = "xxxxx"
-jwt_secret = "xxxxx"
-site_key = "xxxxx"
-secret_key = "xxxxx"
+domain = [] #邮件域名可可配置多个 示例: ["example1.com","example2.com"]
+admin = "" #管理员的邮箱 示例: admin@example.com
+r2_domain = "" #r2对象存储桶的访问域名
+jwt_secret = "" #jwt令牌的密钥,随便填一串字符串
+site_key = "" #Turnstile人机验证的站点密钥
+secret_key = "" #Turnstile人机验证的后端密钥