修复发送成功无法记录联系人
@@ -7,7 +7,7 @@
|
||||
<h1>Cloud Mail</h1>
|
||||
</div>
|
||||
<div align="center">
|
||||
<h4>A responsive email service built with Vue 3 that supports email sending and can be deployed on Cloudflare. 🎉</h4>
|
||||
<h4>Serverless responsive email service with sending capabilities, deployable on the Cloudflare platform 🎉</h4>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -15,14 +15,12 @@
|
||||
|
||||
- [Online Demo](https://skymail.ink)<br>
|
||||
- [Deployment Guide](https://doc.skymail.ink/en/)<br>
|
||||
- [Beginner’s Guide – UI Deployment](https://doc.skymail.ink/en/guide/via-ui.html)
|
||||
- [UI Deployment](https://doc.skymail.ink/en/guide/via-ui.html)
|
||||
|
||||
|
||||
|  |  |
|
||||
|--------------------------|---------------------|
|
||||
|--------------------------|--------------------------|
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|
||||
## Features
|
||||
|
||||
@@ -34,8 +32,6 @@
|
||||
|
||||
- **🛡️ Admin Features**: Admins can manage users and emails, with RBAC permission control to limit access to features and resources.
|
||||
|
||||
- **🔀 Multiple Accounts**: Users can add multiple email accounts.
|
||||
|
||||
- **📦 Attachment Support**: Send and receive attachments, stored and downloaded via R2 object storage.
|
||||
|
||||
- **🔔 Email Push**: Forward received emails to Telegram bots or other email providers.
|
||||
@@ -44,14 +40,8 @@
|
||||
|
||||
- **📈 Data Visualization**: Use Echarts to visualize system data, including user email growth.
|
||||
|
||||
- **⭐ Starred Emails**: Mark important emails for quick access.
|
||||
|
||||
- **🎨 Personalization**: Customize website title, login background, and transparency.
|
||||
|
||||
- **⚙️ Feature Settings**: Toggle on or off features like registration, email sending, and more, with the option to make the site private.
|
||||
|
||||
- **🤖 CAPTCHA**: Integrated with Turnstile CAPTCHA to prevent automated registration.
|
||||
|
||||
- **📜 More Features**: Under development...
|
||||
|
||||
## Tech Stack
|
||||
@@ -62,7 +52,7 @@
|
||||
|
||||
- **ORM**: [Drizzle](https://orm.drizzle.team/)
|
||||
|
||||
- **Platform**: [Cloudflare Workers](https://developers.cloudflare.com/workers/)
|
||||
- **Serverless Platform**: [Cloudflare Workers](https://developers.cloudflare.com/workers/)
|
||||
|
||||
- **Email Service**: [Resend](https://resend.com/)
|
||||
|
||||
@@ -75,17 +65,9 @@
|
||||
|
||||
## Support
|
||||
|
||||
|
||||
<a href="https://doc.skymail.ink/support.html">
|
||||
<img width="170px" src="./doc/images/support.png" alt="">
|
||||
</a><br><br>
|
||||
|
||||
|
||||
**Special Sponsors**
|
||||
|
||||
[DartNode](https://dartnode.com):Providing cloud computing service resource support.
|
||||
|
||||
[](https://dartnode.com "Powered by DartNode - Free VPS for Open Source")
|
||||
</a>
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<h1>Cloud Mail</h1>
|
||||
</div>
|
||||
<div align="center">
|
||||
<h4>使用Vue3开发的响应式邮箱服务,支持邮件发送,无需服务器可部署到Cloudflare平台 🎉</h4>
|
||||
<h4>Serverless 响应式邮箱服务,支持邮件发送,可部署到Cloudflare平台 🎉</h4>
|
||||
</div>
|
||||
<div align="center">
|
||||
<span>简体中文 | <a href="/README-en.md" style="margin-left: 5px">English </a></span>
|
||||
@@ -14,26 +14,24 @@
|
||||
|
||||
## 项目简介
|
||||
|
||||
只需要一个域名,就可以创建多个不同的邮箱,类似各大邮箱平台 QQ邮箱,谷歌邮箱等,本项目使用Cloudflare部署,Resend推送邮件,无需服务器费用,搭建自己的邮箱服务
|
||||
只需要一个域名,就可以创建多个不同的邮箱,类似各大邮箱平台,本项目可部署到 Cloudflare Workers ,降低服务器成本,搭建自己的邮箱服务
|
||||
|
||||
## 项目展示
|
||||
|
||||
- [在线演示](https://skymail.ink)<br>
|
||||
- [部署文档](https://doc.skymail.ink)<br>
|
||||
- [小白保姆教程-界面部署](https://doc.skymail.ink/guide/via-ui.html)
|
||||
- [界面部署](https://doc.skymail.ink/guide/via-ui.html)
|
||||
|
||||
|  |  |
|
||||
|--------------------------|---------------------|
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|-----------------------|-----------------------|
|
||||
|  |  |
|
||||
|
||||
|
||||
|
||||
|
||||
## 功能介绍
|
||||
|
||||
- **💰 低成本使用**:无需服务器,部署到 Cloudflare Workers 降低使用成本
|
||||
- **💰 低成本使用**: 部署到 Cloudflare Workers 降低服务器成本
|
||||
|
||||
- **💻 响应式设计**:响应式布局自动适配PC和大部分手机端浏览器
|
||||
|
||||
@@ -41,8 +39,6 @@
|
||||
|
||||
- **🛡️ 管理员功能**:可以对用户,邮件进行管理,RABC权限控制对功能及使用资源限制
|
||||
|
||||
- **🔀 多号模式**:开启后一个用户可以添加多个邮箱,默认一用户一邮箱,类似各大邮箱平台
|
||||
|
||||
- **📦 附件收发**:支持收发附件,使用R2对象存储保存和下载文件
|
||||
|
||||
- **🔔 邮件推送**:接收邮件后可以转发到TG机器人或其他服务商邮箱
|
||||
@@ -51,27 +47,21 @@
|
||||
|
||||
- **📈 数据可视化**:使用echarts对系统数据详情,用户邮件增长可视化显示
|
||||
|
||||
- **⭐ 星标邮件**:标记重要邮件,以便快速查阅
|
||||
|
||||
- **🎨 个性化设置**:可以自定义网站标题,登录背景,透明度
|
||||
|
||||
- **⚙️ 功能设置**:可以对注册,邮件发送,添加等功能关闭和开启,设为私人站点
|
||||
|
||||
- **🤖 人机验证**:集成Turnstile人机验证,防止人机批量注册
|
||||
|
||||
- **📜 更多功能**:正在开发中...
|
||||
|
||||
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **框架**:[Vue3](https://vuejs.org/) + [Element Plus](https://element-plus.org/)
|
||||
- **前端框架**:[Vue3](https://vuejs.org/) + [Element Plus](https://element-plus.org/)
|
||||
|
||||
- **Web框架**:[Hono](https://hono.dev/)
|
||||
|
||||
- **ORM:**[Drizzle](https://orm.drizzle.team/)
|
||||
|
||||
- **平台:** [Cloudflare workers](https://developers.cloudflare.com/workers/)
|
||||
- **Serverless 平台:** [Cloudflare workers](https://developers.cloudflare.com/workers/)
|
||||
|
||||
- **邮件推送:** [Resend](https://resend.com/)
|
||||
|
||||
@@ -84,17 +74,9 @@
|
||||
|
||||
## 赞助
|
||||
|
||||
|
||||
<a href="https://doc.skymail.ink/support.html" >
|
||||
<img width="170px" src="./doc/images/support.png" alt="">
|
||||
</a><br><br>
|
||||
|
||||
|
||||
**特别赞助商**
|
||||
|
||||
[DartNode](https://dartnode.com):提供云计算服务资源支持
|
||||
|
||||
[](https://dartnode.com "Powered by DartNode - Free VPS for Open Source")
|
||||
</a>
|
||||
|
||||
## 许可证
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 450 KiB |
|
Before Width: | Height: | Size: 461 KiB After Width: | Height: | Size: 525 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 252 KiB After Width: | Height: | Size: 238 KiB |
|
Before Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 313 KiB |
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 4.4 KiB |
@@ -167,12 +167,14 @@ const selectRecipientList = ref([])
|
||||
const contacts = computed(() => writerStore.sendRecipientRecord.map(item => ({email: item})))
|
||||
|
||||
function openContacts() {
|
||||
form.receiveEmail.forEach(item => {
|
||||
if (writerStore.sendRecipientRecord.includes(item)) {
|
||||
contactsTabRef.value.toggleRowSelection({email: item});
|
||||
}
|
||||
})
|
||||
showContacts.value = true
|
||||
nextTick(() => {
|
||||
form.receiveEmail.forEach(item => {
|
||||
if (writerStore.sendRecipientRecord.includes(item)) {
|
||||
contactsTabRef.value.toggleRowSelection({email: item});
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function deleteContact() {
|
||||
@@ -372,6 +374,8 @@ async function sendEmail() {
|
||||
|
||||
userStore.refreshUserInfo();
|
||||
|
||||
addRecipientRecord();
|
||||
|
||||
if (form.draftId) {
|
||||
form.subject = ''
|
||||
form.content = ''
|
||||
@@ -379,8 +383,8 @@ async function sendEmail() {
|
||||
draftStore.setDraft = {...toRaw(form)}
|
||||
}
|
||||
|
||||
resetForm()
|
||||
show.value = false
|
||||
resetForm();
|
||||
}).catch((e) => {
|
||||
ElNotification({
|
||||
title: t('sendFailMsg'),
|
||||
@@ -389,20 +393,22 @@ async function sendEmail() {
|
||||
position: 'bottom-right'
|
||||
})
|
||||
show.value = true
|
||||
addRecipientRecord();
|
||||
}).finally(() => {
|
||||
percentMessage.close()
|
||||
percent.value = 0
|
||||
sending = false
|
||||
|
||||
writerStore.sendRecipientRecord = writerStore.sendRecipientRecord.filter(
|
||||
email => !form.receiveEmail.includes(email)
|
||||
);
|
||||
|
||||
writerStore.sendRecipientRecord.unshift(...form.receiveEmail);
|
||||
writerStore.sendRecipientRecord = writerStore.sendRecipientRecord.slice(0, 500);
|
||||
})
|
||||
}
|
||||
|
||||
function addRecipientRecord() {
|
||||
writerStore.sendRecipientRecord = writerStore.sendRecipientRecord.filter(
|
||||
email => !form.receiveEmail.includes(email)
|
||||
);
|
||||
|
||||
writerStore.sendRecipientRecord.unshift(...form.receiveEmail);
|
||||
writerStore.sendRecipientRecord = writerStore.sendRecipientRecord.slice(0, 500);
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
form.receiveEmail = []
|
||||
|
||||
@@ -10,9 +10,9 @@ const r2Service = {
|
||||
}
|
||||
|
||||
const setting = await settingService.query(c);
|
||||
const { bucket, region, endpoint, s3AccessKey, s3SecretKey } = setting;
|
||||
const { bucket, endpoint, s3AccessKey, s3SecretKey } = setting;
|
||||
|
||||
return !!(bucket && region && endpoint && s3AccessKey && s3SecretKey);
|
||||
return !!(bucket && endpoint && s3AccessKey && s3SecretKey);
|
||||
},
|
||||
|
||||
async putObj(c, key, content, metadata) {
|
||||
|
||||