Skip to content
 
 

Latest commit

 

History

173 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cloud Mail

基于 Cloudflare 的简约响应式邮箱服务,支持邮件发送、附件收发 🎉

简体中文 | English

releases issues stargazers forks

trendshift

项目简介

只需要一个域名,就可以创建多个不同的邮箱,类似各大邮箱平台,本项目支持署到 Cloudflare Workers ,降低服务器成本,搭建自己的邮箱服务

项目展示

功能介绍

  • 💰 低成本使用: 可部署到 Cloudflare Workers 降低服务器成本

  • 💻 响应式设计:响应式布局自动适配PC和大部分手机端浏览器

  • 📧 邮件发送:集成Resend发送邮件,支持群发,内嵌图片和附件发送,发送状态查看

  • 🛡️ 管理员功能:可以对用户,邮件进行管理,RABC权限控制对功能及使用资源限制

  • 📦 附件收发:支持收发附件,使用R2对象存储保存和下载文件

  • 🔔 邮件推送:接收邮件后可以转发到TG机器人或其他服务商邮箱

  • 📡 开放API:支持使用API批量生成用户,多条件查询邮件

  • 📈 数据可视化:使用ECharts对系统数据详情,用户邮件增长可视化显示

  • 🎨 个性化设置:可以自定义网站标题,登录背景,透明度

  • 🤖 人机验证:集成Turnstile人机验证,防止人机批量注册

  • 📜 更多功能:正在开发中...

技术栈

目录结构

cloud-mail
├── mail-worker				    # worker后端项目
│   ├── src                  
│   │   ├── api	 			    # api接口层			
│   │   ├── const  			    # 项目常量
│   │   ├── dao                 # 数据访问层
│   │   ├── email			    # 邮件处理接收
│   │   ├── entity			    # 数据库实体
│   │   ├── error			    # 自定义异常
│   │   ├── hono			    # web框架配置、拦截器、全局异常等
│   │   ├── i18n			    # 语言国际化
│   │   ├── init			    # 数据库缓存初始化
│   │   ├── model			    # 响应体数据封装
│   │   ├── security			# 身份权限认证
│   │   ├── service			    # 业务服务层
│   │   ├── template			# 消息模板
│   │   ├── utils			    # 工具类
│   │   └── index.js			# 入口文件
│   ├── pageckge.json			# 项目依赖
│   └── wrangler.toml			# 项目配置
│
├── mail-vue				    # vue前端项目
│   ├── src
│   │   ├── axios 			    # axios配置
│   │   ├── components			# 自定义组件
│   │   ├── echarts			    # echarts组件导入
│   │   ├── i18n			    # 语言国际化
│   │   ├── init			    # 入站初始化
│   │   ├── layout			    # 主体布局组件
│   │   ├── perm			    # 权限认证
│   │   ├── request			    # api接口
│   │   ├── router			    # 路由配置
│   │   ├── store			    # 全局状态管理
│   │   ├── utils			    # 工具类
│   │   ├── views			    # 页面组件
│   │   ├── app.vue			    # 入口组件
│   │   ├── main.js			    # 入口js
│   │   └── style.css			# 全局css
│   ├── package.json			# 项目依赖
└── └── env.release				# 项目配置

生产部署后必须执行数据库升级

部署或更新 mail-worker 后,必须让生产 D1 执行一次项目内置升级流程。否则会出现“Worker 代码已经使用新表/新字段,但 D1 仍是旧结构”的问题。

本项目的升级入口是:

GET /api/init/:secret

其中 :secret 是 Worker 环境变量里的 jwt_secret,不要写进 Git、README、日志或公开聊天。

为什么必须执行

mail-worker/src/init/init.js 中的 dbInit.init() 会按顺序执行:

intDB
v1_1DB
v1_2DB
...
v2_9DB
v3SmtpDB
v3SmtpLifecycleDB
settingService.refresh

这些步骤会补齐 CloudMail 基础表、SMTP 凭据表、SMTP submission 表、Resend webhook inbox、失败通知 outbox,以及老表上的新增字段。

例如 SMTP lifecycle 升级会给老 email 表增加:

smtp_submission_id

并创建相关索引。如果生产 D1 没有这个字段,而新版 Worker 已经部署,就可能出现:

/api/email/send 返回 500
但 Resend 实际已经发送成功

原因是发信流程中 Resend 会先发送,之后 Worker 写入 D1 email 表时发现缺列并报错。

什么时候执行

每次生产部署后都执行一次:

https://<你的 CloudMail 域名>/api/init/<jwt_secret>

返回:

success

才算升级完成。

GitHub Actions 部署时也应保留部署后的初始化步骤:

curl -sL "https://<你的 CloudMail 域名>/api/init/${JWT_SECRET}"

幂等性

该升级流程可以重复执行:

  • CREATE TABLE IF NOT EXISTS 会跳过已存在的表;
  • CREATE INDEX IF NOT EXISTS 会跳过已存在的索引;
  • 新增列通过 addColumns() 包装,遇到 duplicate column 会忽略,其他错误才会中断。

因此,正常更新后重复调用一次 init 是推荐操作。

升级后验证

可以只读检查 D1 schema,确认关键列存在:

wrangler d1 execute <数据库名> --remote --command \
  "SELECT COUNT(*) AS has_column FROM pragma_table_info('email') WHERE name = 'smtp_submission_id';"

预期:

has_column = 1

还应确认 SMTP 相关表存在,例如:

smtp_credential
smtp_submission
smtp_recipient
smtp_notification
smtp_quota_reservation
smtp_provider_attempt
resend_webhook_inbox
smtp_provider_failure_outbox

故障特征

如果忘记执行升级,常见表现包括:

D1_ERROR: table email has no column named smtp_submission_id
/api/email/send 返回 500,但 Resend 已发送成功
SMTP submission 入库失败
Resend webhook 或失败通知无法关联邮件记录

遇到这种情况,不要重复点击发送,先执行数据库升级并验证 schema。


许可证

本项目采用 MIT 许可证

交流

Telegram

About

A Cloudflare-based email service | 基于 Cloudflare 的邮箱服务 | Cloudflare Email 邮箱 Mail

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages