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 + +| ![](demo/demo1.png) | ![](demo/demo2.png) | +|---------------------|---------------------| +| ![](demo/demo3.png) | ![](demo/demo4.png) | + + + + + +## 功能介绍 + +- **💰免费白嫖**:无需服务器,部署到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人机验证的后端密钥