添加说明和MIT
This commit is contained in:
20
LICENSE
Normal file
20
LICENSE
Normal file
@@ -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.
|
||||||
151
README.md
151
README.md
@@ -1 +1,150 @@
|
|||||||
1312
|
<p align="center">
|
||||||
|
<img src="demo/logo.png" width="10%" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<h1>Cloud Mail</h1>
|
||||||
|
</div>
|
||||||
|
<div align="center">
|
||||||
|
<h4>一个使用Vue3开发的响应式简约邮箱服务, 可以部署到Cloudflare云平台实现免费白嫖🎉</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 在线演示
|
||||||
|
|
||||||
|
👉 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) 许可证
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
demo/demo1.png
Normal file
BIN
demo/demo1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
BIN
demo/demo2.png
Normal file
BIN
demo/demo2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
BIN
demo/demo3.png
Normal file
BIN
demo/demo3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 195 KiB |
BIN
demo/demo4.png
Normal file
BIN
demo/demo4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
demo/logo.png
Normal file
BIN
demo/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
@@ -43,6 +43,10 @@ export async function email(message, env, ctx) {
|
|||||||
|
|
||||||
const emailRow = await emailService.receive({ env }, params);
|
const emailRow = await emailService.receive({ env }, params);
|
||||||
|
|
||||||
|
if (!env.r2) {
|
||||||
|
console.warn('r2对象存储未配置, 附件取消保存');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (email.attachments.length > 0) {
|
if (email.attachments.length > 0) {
|
||||||
|
|
||||||
@@ -58,11 +62,6 @@ export async function email(message, env, ctx) {
|
|||||||
|
|
||||||
await attService.addAtt({ env }, attachments);
|
await attService.addAtt({ env }, attachments);
|
||||||
|
|
||||||
if (!env.r2) {
|
|
||||||
console.log('r2对象存储未配置, 附件取消保存');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let attachment of attachments) {
|
for (let attachment of attachments) {
|
||||||
await r2Service.putObj({ env }, attachment.key, attachment.content, {
|
await r2Service.putObj({ env }, attachment.key, attachment.content, {
|
||||||
contentType: attachment.mimeType,
|
contentType: attachment.mimeType,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default {
|
|||||||
return app.fetch(req, env, ctx);
|
return app.fetch(req, env, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return env.ASSETS.fetch(req);
|
return env.assets.fetch(req);
|
||||||
},
|
},
|
||||||
email: email
|
email: email
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,20 +11,20 @@ ip = "0.0.0.0"
|
|||||||
[[d1_databases]]
|
[[d1_databases]]
|
||||||
binding = "db"
|
binding = "db"
|
||||||
database_name = "email"
|
database_name = "email"
|
||||||
database_id = "xxxxx"
|
database_id = ""
|
||||||
|
|
||||||
[[kv_namespaces]]
|
[[kv_namespaces]]
|
||||||
binding = "kv"
|
binding = "kv"
|
||||||
id = "xxxxx"
|
id = ""
|
||||||
|
|
||||||
[[r2_buckets]]
|
[[r2_buckets]]
|
||||||
binding = "r2"
|
binding = "r2"
|
||||||
bucket_name = "email"
|
bucket_name = "email"
|
||||||
|
|
||||||
[vars]
|
[vars]
|
||||||
domain = ["xxxxx", "xxxxx"]
|
domain = ["", ""]
|
||||||
admin = "xxxxx"
|
admin = ""
|
||||||
r2_domain = "xxxxx"
|
r2_domain = ""
|
||||||
jwt_secret = "xxxxx"
|
jwt_secret = ""
|
||||||
site_key = "xxxxx"
|
site_key = ""
|
||||||
secret_key = "xxxxx"
|
secret_key = ""
|
||||||
|
|||||||
@@ -9,25 +9,25 @@ head_sampling_rate = 1
|
|||||||
[[d1_databases]]
|
[[d1_databases]]
|
||||||
binding = "db"
|
binding = "db"
|
||||||
database_name = "email-test"
|
database_name = "email-test"
|
||||||
database_id = "xxxxx"
|
database_id = ""
|
||||||
|
|
||||||
[[kv_namespaces]]
|
[[kv_namespaces]]
|
||||||
binding = "kv"
|
binding = "kv"
|
||||||
id = "xxxxx"
|
id = ""
|
||||||
|
|
||||||
[[r2_buckets]]
|
[[r2_buckets]]
|
||||||
binding = "r2"
|
binding = "r2"
|
||||||
bucket_name = "email-test"
|
bucket_name = "email-test"
|
||||||
|
|
||||||
[assets]
|
[assets]
|
||||||
|
binding = "assets"
|
||||||
directory = "./dist"
|
directory = "./dist"
|
||||||
binding = "ASSETS"
|
|
||||||
|
|
||||||
[vars]
|
[vars]
|
||||||
domain = ["xxxxx", "xxxxx"]
|
domain = ["", ""]
|
||||||
admin = "xxxxx"
|
admin = ""
|
||||||
r2_domain = "xxxxx"
|
r2_domain = ""
|
||||||
jwt_secret = "xxxxx"
|
jwt_secret = ""
|
||||||
site_key = "xxxxx"
|
site_key = ""
|
||||||
secret_key = "xxxxx"
|
secret_key = ""
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,27 @@ compatibility_date = "2025-04-09"
|
|||||||
[observability]
|
[observability]
|
||||||
enabled = true
|
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]
|
[assets]
|
||||||
directory = "./dist"
|
binding = "assets" #静态资源存放位置默认不可修改
|
||||||
binding = "ASSETS"
|
directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist
|
||||||
|
|
||||||
[vars]
|
[vars]
|
||||||
domain = ["xxxxx", "xxxxx"]
|
domain = [] #邮件域名可可配置多个 示例: ["example1.com","example2.com"]
|
||||||
admin = "xxxxx@xxxxx"
|
admin = "" #管理员的邮箱 示例: admin@example.com
|
||||||
r2_domain = "xxxxx"
|
r2_domain = "" #r2对象存储桶的访问域名
|
||||||
jwt_secret = "xxxxx"
|
jwt_secret = "" #jwt令牌的密钥,随便填一串字符串
|
||||||
site_key = "xxxxx"
|
site_key = "" #Turnstile人机验证的站点密钥
|
||||||
secret_key = "xxxxx"
|
secret_key = "" #Turnstile人机验证的后端密钥
|
||||||
|
|||||||
Reference in New Issue
Block a user