Cloudsteading
Application view supplied in the upstream repository README

Cloud Mail

Receive domain email and browse messages in a self-hosted Cloudflare web inbox.

Cloud Mail is a self-hosted Fastmail/Gmail alternative built on Cloudflare (D1, Email Workers, KV, R2, Workers). Free tier eligible within limits. Inspect the source and license in the linked repository.

Source & license

Upstream license: MIT

License TL;DR

You can use it, change it, self-host it and sell it. Keep the original copyright and license notice with copies of the code. You don’t have to publish your changes. The authors don’t promise it will work.

Explain MIT in plain English →

Summary of the main license. Separate packages and assets can have different terms.

Inspect repository ↗Read this project’s actual license ↗

Repository owner

@maillab

See the upstream repository for the original creator and contributors.

Maintain this project? Maintainer verification →

Cloudflare hosting

Free tier eligible within limits

The documented Cloud Mail deployment can use Cloudflare Free allowances for a small workload under the request, CPU and service-specific quotas below. This is conditional eligibility, not a measured zero-cost deployment; optional features, domains and external providers can add costs.

Hosting requirements
  • Workers Free allows 100,000 requests per day shared across the account and 10 ms CPU per invocation; measure CPU-heavy authentication, parsing and rendering before assuming it fits.
  • Keep aggregate D1 use below 5 million rows read/day, 100,000 rows written/day and 5 GB total storage; a request can touch many rows.
  • Keep KV below 100,000 reads/day, 1,000 writes, deletes and list operations/day each, and 1 GB; cache refreshes and backups consume writes.
  • Use R2 Standard storage, at most 10 GB-month, 1 million Class A operations and 10 million Class B operations/month; provision an eligible billing-enabled R2 account.
  • Only ordinary Free-eligible Workers AI models are covered, within 10,000 neurons/day; optional external providers and paid-only models are excluded.
  • Inbound Email Routing can use Workers Free, but processing consumes Workers quotas and requires a domain; arbitrary-recipient outbound email requires Workers Paid.
  • Use a small personal or team workload; domain registration and optional third-party providers are separate costs. Provision your own IDs, secrets and migrations.
Check current pricing ↗
Sources checked 01/10/2026

Repository snapshot: ec7a2bb. Hosting eligibility reflects the deployment documentation and listed assumptions.

  • gmail ↗

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

  • fastmail ↗

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

  • workers ↗

    name = "cloud-mail" main = "src/index.js" compatibility_date = "2025-06-04" keep_vars = true [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对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;re

  • d1 ↗

    e = "2025-06-04" keep_vars = true [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对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analy

  • kv ↗

    名默认不可修改 #database_name = "" #d1数据库名字 #database_id = "" #d1数据库id #[[kv_namespaces]] #binding = "kv" #kv绑定名默认不可修改 #id = "" #kv数据库id #[[r2_buckets]] #binding = "r2" #r2对象存储绑定名默认不可修改 #bucket_name = "" #r2对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analysis_cache = false #是否开启分析数据缓存 #orm_log = false #是否sql日志 #domain = [] #邮件域名可可配置多个 示例: ["example1.com","ex

  • r2 ↗

    namespaces]] #binding = "kv" #kv绑定名默认不可修改 #id = "" #kv数据库id #[[r2_buckets]] #binding = "r2" #r2对象存储绑定名默认不可修改 #bucket_name = "" #r2对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analysis_cache = false #是否开启分析数据缓存 #orm_log = false #是否sql日志 #domain = [] #邮件域名可可配置多个 示例: ["example1.com","example2.com"] #admin = "" #管理员的邮箱 示例: admin@example.com #jwt_secret =

  • workers-ai ↗

    = "" #r2对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analysis_cache = false #是否开启分析数据缓存 #orm_log = false #是否sql日志 #domain = [] #邮件域名可可配置多个 示例: ["example1.com","example2.com"] #admin = "" #管理员的邮箱 示例: admin@example.com #jwt_secret = "" #jwt令牌的密钥,随便填一串字符串 [build] command = "pnpm --prefix ../mail-vue install && pnpm --prefix ../mail-vue run build"

  • email-workers ↗

    ing = "r2" #r2对象存储绑定名默认不可修改 #bucket_name = "" #r2对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analysis_cache = false #是否开启分析数据缓存 #orm_log = false #是否sql日志 #domain = [] #邮件域名可可配置多个 示例: ["example1.com","example2.com"] #admin = "" #管理员的邮箱 示例: admin@example.com #jwt_secret = "" #jwt令牌的密钥,随便填一串字符串 [build] command = "pnpm --prefix ../mail-vue install && pnpm --

  • free-tier-eligible ↗

    name = "cloud-mail" main = "src/index.js" compatibility_date = "2025-06-04" keep_vars = true [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对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;re

  • free-tier-eligible ↗

    e = "2025-06-04" keep_vars = true [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对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analy

  • free-tier-eligible ↗

    名默认不可修改 #database_name = "" #d1数据库名字 #database_id = "" #d1数据库id #[[kv_namespaces]] #binding = "kv" #kv绑定名默认不可修改 #id = "" #kv数据库id #[[r2_buckets]] #binding = "r2" #r2对象存储绑定名默认不可修改 #bucket_name = "" #r2对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analysis_cache = false #是否开启分析数据缓存 #orm_log = false #是否sql日志 #domain = [] #邮件域名可可配置多个 示例: ["example1.com","ex

  • free-tier-eligible ↗

    up>1, 2, 3, 4</sup> | Duration | CPU time | | --- | --- | --- | --- | | **Free** | 100,000 per day | No charge for duration | 10 milliseconds of CPU time per invocation | | **Standard** | 10 million included per month <br> +$0.30 per additional million | No charge or limit for duration | 30 million CPU milliseconds included per month<br> +$0.02 per additional million CPU milliseconds<br><br> Max of [5 minutes of CPU time](https://developers.cloudflare.com/workers/platform/limits/#account-plan-limits) per invocation (default: 30 seconds)<br> Max of 15 minutes of CPU time per [Cron Trigger](https://developers.cloudflare.com/workers/configuration/cron-triggers/) or [Queue Consumer](https://developers.cloudflare.co

  • free-tier-eligible ↗

    oudflare.com/workers/platform/pricing/#workers) | | --- | --- | --- | | Rows read | 5 million / day | First 25 billion / month included + $0.001 / million rows | | Rows written | 100,000 / day | First 50 million / month included + $1.00 / million rows | | Storage (per GB stored) | 5 GB (total) | First 5 GB included + $0.75 / GB-mo | Track your D1 usage To accurately track your usage, use the [meta object](https://developers.cloudflare.com/d1/worker-api/return-object/), [GraphQL Analytics API](https://developers.cloudflare.com/d1/observability/metrics-analytics/#query-via-the-graphql-api), or the [Cloudflare dashboard ↗︎](https://dash.cloudflare.com/?to=/:account/workers/d1/). Select your D1 database, then vie

  • free-tier-eligible ↗

    cing/). | | Free plan<sup>1</sup> | Paid plan | | --- | --- | --- | | Keys read | 100,000 / day | 10 million/month, + $0.50/million | | Keys written | 1,000 / day | 1 million/month, + $5.00/million | | Keys deleted | 1,000 / day | 1 million/month, + $5.00/million | | List requests | 1,000 / day | 1 million/month, + $5.00/million | | Stored data | 1 GB | 1 GB, + $0.50/ GB-month | <sup>1</sup> The Workers Free plan includes limited Workers KV usage. All limits reset daily at 00:00 UTC. If you exceed any one of these limits, further operations of that type will fail with an error. Note Workers KV pricing for read, write and delete operations is on a per-key basis. Bulk read operations are billed by the amount

  • free-tier-eligible ↗

    infrequent access storage) for 1.1 GB, you will be billed for 2 GB. ### Free tier You can use the following amount of storage and operations each month for free. | | Free | | --- | --- | | Storage | 10 GB-month / month | | Class A Operations | 1 million requests / month | | Class B Operations | 10 million requests / month | | Egress (data transfer to Internet) | Free <sup>[1](#user-content-fn-1)</sup> | Caution The free tier only applies to Standard storage, and does not apply to Infrequent Access storage. ### Storage usage Storage is billed using gigabyte-month (GB-month) as the billing metric. A GB-month is calculated by averaging the *peak* storage per day over a billing period (30 days). For examp

  • free-tier-eligible ↗

    000 Neurons**. Our free allocation allows anyone to use a total of **10,000 Neurons per day at no charge**. To use more than 10,000 Neurons per day, you need to sign up for the [Workers Paid plan](https://developers.cloudflare.com/workers/platform/pricing/#workers). On Workers Paid, you will be charged at $0.011 / 1,000 Neurons for any usage above the free allocation of 10,000 Neurons per day. You can monitor your Neuron usage in the [Cloudflare Workers AI dashboard ↗︎](https://dash.cloudflare.com/?to=/:account/ai/workers-ai). All limits reset daily at 00:00 UTC. If you exceed any one of the above limits, further operations will fail with an error. | | Free <br> allocation | Pricing | | --- | --- | --- | |

  • free-tier-eligible ↗

    g is based on your Cloudflare plan and email usage. ## Plan pricing Email Routing is available on both the Workers Free and Workers Paid plans. Sending to arbitrary recipients requires the Workers Paid plan. Sending to [verified destination addresses](https://developers.cloudflare.com/email-service/configuration/email-routing-addresses/#destination-addresses) in your account is free on all plans, including when only Email Routing is configured. | | Workers Free | Workers Paid | | --- | --- | --- | | **Outbound emails (Email Sending)** | Not available | 3,000 included per month, then $0.35 per 1,000 emails | | **Inbound emails (Email Routing)** | Unlimited | Unlimited | The 3,000 included emails apply per a

  • MIT ↗

    The MIT License (MIT) Copyright (c) 2025 aslost 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 NON

  • architecture ↗

    name = "cloud-mail" main = "src/index.js" compatibility_date = "2025-06-04" keep_vars = true [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对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;re

  • architecture ↗

    e = "2025-06-04" keep_vars = true [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对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analy

  • architecture ↗

    名默认不可修改 #database_name = "" #d1数据库名字 #database_id = "" #d1数据库id #[[kv_namespaces]] #binding = "kv" #kv绑定名默认不可修改 #id = "" #kv数据库id #[[r2_buckets]] #binding = "r2" #r2对象存储绑定名默认不可修改 #bucket_name = "" #r2对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analysis_cache = false #是否开启分析数据缓存 #orm_log = false #是否sql日志 #domain = [] #邮件域名可可配置多个 示例: ["example1.com","ex

  • architecture ↗

    namespaces]] #binding = "kv" #kv绑定名默认不可修改 #id = "" #kv数据库id #[[r2_buckets]] #binding = "r2" #r2对象存储绑定名默认不可修改 #bucket_name = "" #r2对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analysis_cache = false #是否开启分析数据缓存 #orm_log = false #是否sql日志 #domain = [] #邮件域名可可配置多个 示例: ["example1.com","example2.com"] #admin = "" #管理员的邮箱 示例: admin@example.com #jwt_secret =

  • architecture ↗

    = "" #r2对象存储桶的名字 #[[send_email]] #name = "email" #CF发件, 配置后优先使用 [ai] binding = "ai" [assets] binding = "assets" #静态资源绑定名默认不可修改 directory = "./dist" #前端vue项目打包的静态资源存放位置,默认dist not_found_handling = "single-page-application" run_worker_first = true [triggers] crons = ["0 * * * *"] #每小时执行;resetDaySendCount 仅在 UTC 0 点生效 [vars] #ai_model = "" #ai模型,不填默认使用@cf/meta/llama-3.1-8b-instruct-fast #analysis_cache = false #是否开启分析数据缓存 #orm_log = false #是否sql日志 #domain = [] #邮件域名可可配置多个 示例: ["example1.com","example2.com"] #admin = "" #管理员的邮箱 示例: admin@example.com #jwt_secret = "" #jwt令牌的密钥,随便填一串字符串 [build] command = "pnpm --prefix ../mail-vue install && pnpm --prefix ../mail-vue run build"

Upstream screenshot · maillab/cloud-mail repository contributors ↗. Depicts the upstream project. We have not deployed and tested a fresh installation here.

What it can replace

Compare the workflow you need. These mappings describe overlap; full feature parity requires a separate comparison.

Gmail logoGmail ↗

Receiving owned-domain email and browsing an inbox with attachments; outbound sending is a separately configured provider and IMAP/SMTP or full managed-mail parity is excluded.

See supporting source ↗
Fastmail logoFastmail ↗

Receiving owned-domain email and browsing an inbox with attachments; outbound sending is a separately configured provider and IMAP/SMTP or full managed-mail parity is excluded.

See supporting source ↗
external SaaS target
varies
→ D1 + Email Workers + KV
external SaaS target
varies
→ D1 + Email Workers + KV

How it works

The shape of Cloud Mail on Cloudflare, and how it stacks up against the rented tools it replaces.

Architecture

Diagram based on the linked repository documentation. See the sources and hosting assumptions above.

View upstream source ↗
Public interface
Public interface1
Cloud Mail
Browser, API or documented client interface
↓
App
cloud-mail
entry
Cloudflare Workers · configuration-derived
Configured cron: 0 * * * *
↓

Configuration and workflow sources

Reviewed commit ec7a2bb17c95. Files were read as data; upstream applications and CI jobs were not executed.

Partial source coverage: 106 files outside collection bounds; 0 collection or parsing issues. Dynamic imports and generated entrypoints may need manual review.

Deployment configuration · 4 files
mail-worker/wrangler.toml ↗

Cloudflare Workers · compatibility 2025-06-04

cloud-mail · default

Entrypoint: src/index.js

Build: pnpm --prefix ../mail-vue install && pnpm --prefix ../mail-vue run build

Static assets: ./dist · single-page-application · Worker first: true

Cron triggers (UTC): 0 * * * *

  • ai → Workers AI
  • assets → Static assets
mail-worker/wrangler-action.toml ↗

Cloudflare Workers · compatibility 2025-06-04

${NAME} · default

Entrypoint: src/index.js

Build: pnpm --prefix ../mail-vue install && pnpm --prefix ../mail-vue run build

Static assets: ./dist · single-page-application · Worker first: true

Cron triggers (UTC): 0 * * * *

Configured route patterns: ${CUSTOM_DOMAIN}

  • db → D1
  • kv → KV
  • r2 → R2
  • ai → Workers AI
  • assets → Static assets
mail-worker/wrangler-dev.toml ↗

Cloudflare Workers · compatibility 2025-06-04

cloud-mail-dev · default

Entrypoint: src/index.js

Static assets: ./dist · single-page-application · Worker first: true

  • db → D1
  • kv → KV
  • assets → Static assets
mail-worker/wrangler-test.toml ↗

Cloudflare Workers · compatibility 2025-06-04

test-mail · default

Entrypoint: src/index.js

Build: pnpm --prefix ../mail-vue install && pnpm --prefix ../mail-vue run build

Static assets: ./dist · single-page-application · Worker first: true

Cron triggers (UTC): 0 * * * *

  • db → D1
  • kv → KV
  • ai → Workers AI
  • assets → Static assets

Named environments are separate deployments. Bindings are shown only where declared. Configured routes are URL patterns, not verified application endpoints.

Runtime source · handlers, binding usage and workflow steps

Observed TypeScript/JavaScript declarations from Worker entrypoints and resolved relative imports. Calls and workflow steps may run conditionally; their listed order is not a proven end-to-end request flow. Router declarations may be mounted under a prefix or may not be registered. This shows code wiring, not a successful deployment or runtime test. Dynamic wiring, aliases and generated code may not resolve.

mail-worker/src/index.js ↗
  • L10 · fetch handler exported · references assets · calls url.pathname.startsWith, url.pathname.replace, url.toString, app.fetch, some, kvObjService.toObjResp, url.pathname.substring, env.assets.fetch
  • L26 · email handler exported
  • L27 · scheduled handler exported · calls analysisService.refreshEchartsCache, verifyRecordService.clearRecord, userService.resetDaySendCount, emailService.completeReceiveAll, emailService.autoClean, oauthService.clearNoBindOathUser

Environment references: env.assets

mail-worker/src/email/email.js ↗
  • L16 · email calls (conditional paths may differ): settingService.query, message.setReject, message.raw.getReader, reader.read, decode, PostalMime.parse, checkBlock, accountService.selectByEmailIncludeDel, emailUtils.getBaseEmail, userService.selectByIdIncludeDel, roleService.selectByUserId, roleService.hasAvailDomainPerm, roleService.isBanEmail, emailUtils.getName, email.to.find, aiService.extractCode, JSON.stringify, fileUtils.getBuffHash, fileUtils.getExtFileName, attachments.push
  • L205 · checkBlock calls (conditional paths may differ): blackFromStr.split, blackContentStr.split, blackSubjectStr.split, emailUtils.getDomain

Environment references: env.admin

mail-worker/src/service/user-service.js ↗

    Environment references: c.env.admin · c.env.kv · c.env.domain

    mail-worker/src/service/email-service.js ↗

      Environment references: c.env.admin · c.env.email · c.env.kv · c.env.db

      mail-worker/src/service/kv-obj-service.js ↗

        Environment references: c.env.kv

        mail-worker/src/service/analysis-service.js ↗

          Environment references: c.env.kv · c.env.analysis_cache

          mail-worker/src/security/security.js ↗
          • L168 · permKeyToPaths calls (conditional paths may differ): Array.isArray, paths.push

          Environment references: c.env.kv · c.env.admin

          Build and deployment pipeline · 1 GitHub Actions workflows

          Repository CI declarations, separate from runtime request processing. Job dependencies and conditions are shown as written; long commands are shortened with an ellipsis; a workflow file does not prove a recent successful run.

          🚀 Deploy cloud-mail to Cloudflare Workers · .github/workflows/deploy-cloudflare.yml ↗

          Triggers: push, workflow_dispatch

          🏗️ Build and Deploy · no job dependencies declared

          1. 🚚 检出代码仓库 / Checkout repositoryactions/checkout@v4
          2. ⚙ 设置 pnpm / Set up pnpmpnpm/action-setup@v4.1.0
          3. ⚙ 设置 Node.js / Set up Node.jsactions/setup-node@v4
          4. 📦 安装依赖 / Install dependenciespnpm install --frozen-lockfile
          5. 📡 禁用 Wrangler 遥测 / Disable wrangler telemetrypnpm wrangler telemetry disable
          6. 🛠️ 设置环境 / Set up environmentecho "🔐 Starting environment setup..." if [ -z "$JWT_SECRET" ] || grep -q '[?%#/\\]' <<< "$JWT_SECRET"; then echo "❌ JWT_SECRET variable is empty or contains invalid characters (?, %, #, /, \\)." exit 1 fi if ! jq -e 'type == "array"' <<< "$DOMAIN" ; then echo "❌ DOMAIN variable must be a JSON array (e.g., [\"example.com\"])." exit 1 fi if [ -z "$ADMIN" ]; then echo "❌ ADMIN variable cannot be empty." exit 1 fi if [ -z "$CLOUDFLARE_ACCOUNT_ID" ]; then echo "❌ CLOUDFLARE_ACCOUNT_ID variable can…
          7. ⚡ 设置KV数据库 / Set up KV databaseCONFIG_FILE="wrangler-action.toml" if [ -n "$KV_NAMESPACE_ID" ]; then sed -i "s|\${KV_NAMESPACE_ID}|${KV_NAMESPACE_ID}|g" "$CONFIG_FILE" echo "✅ Using the database from environment variables." exit 0 fi echo "🔍 Checking if the database exists..." set +e KV_LIST=$(pnpm wrangler kv namespace list 2>&1) STATUS=$? set -e if [ $STATUS -ne 0 ]; then echo "$KV_LIST" exit 1 fi if echo "$KV_LIST" | jq -e ".[] | select(.title == \"$NAME\")" >/dev/null; then echo "✅ Database $NAME already exists." KV_ID=…
          8. 🐬 设置D1数据库 / Set up D1 databaseCONFIG_FILE="wrangler-action.toml" if [ -n "$D1_DATABASE_ID" ]; then sed -i "s|\${D1_DATABASE_ID}|${D1_DATABASE_ID}|g" "$CONFIG_FILE" echo "✅ Using the database from environment variables." exit 0 fi echo "🔍 Checking if the database exists..." set +e DB_LIST=$(pnpm wrangler d1 list --json 2>&1) STATUS=$? set -e if [ $STATUS -ne 0 ]; then echo "$DB_LIST" exit 1 fi if echo "$DB_LIST" | jq -e ".[] | select(.name == \"$NAME\")" >/dev/null; then echo "✅ Database $NAME already exists." D1_ID=$(echo …
          9. 🚀 开始部署 / Start deploymentecho "🚀 Starting deployment..." pnpm wrangler deploy -c wrangler-action.toml 2>&1 \ | tee deploy.log \ | grep -v "https://.*\.workers\.dev" \ | sed -E 's/env\.domain .*/env.domain (***)/' \ || true DEPLOY_EXIT_CODE=${PIPESTATUS[0]} if [ $DEPLOY_EXIT_CODE -ne 0 ]; then exit 1 fi WORKER_URL=$(grep -o "https://.*\.workers\.dev" deploy.log || echo "") if [ -n "$WORKER_URL" ]; then echo "::add-mask::$WORKER_URL" fi echo "worker_url=$WORKER_URL" >> $GITHUB_OUTPUT echo "✅ Setup completed."
          10. ♻️ 初始化数据库 / Initialize databaseecho "🛠️ Starting database initialization..." sleep 15 WORKER_URL="${CUSTOM_DOMAIN:+https://$CUSTOM_DOMAIN}" WORKER_URL="${WORKER_URL:-${{ steps.deploy.outputs.worker_url }}}" if [ -z "$WORKER_URL" ]; then echo "❌ Preview URL not available. Please set CUSTOM_DOMAIN." exit 1 fi HTTP_CODE=$(curl -sL -w "%{http_code}" -o response.txt "$WORKER_URL/api/init/${JWT_SECRET}") RESPONSE_BODY=$(cat response.txt) if [ "$RESPONSE_BODY" = "success" ]; then echo "✅ Setup completed." else echo "❌ Failed. HTTP…
          11. 🗑️ 删除运行记录 / Delete workflow runsGitRML/delete-workflow-runs@main
          mail-vue/package.json ↗
          • build: vite build --mode release
          mail-worker/package.json ↗
          • deploy: wrangler deploy

          Full upstream document by @maillab · README.md · snapshot ec7a2bb

          Cloud Mail

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

          简体中文 | English

          releases issues stargazers forks

          trendshift

          项目简介

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

          项目展示

          功能介绍

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

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

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

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

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

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

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

          • 🔢 验证码识别:使用Workers AI,自动识别邮件验证码

          • 📈 数据可视化:使用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				# 项目配置
          

          赞助

          许可证

          本项目采用 MIT 许可证

          交流

          Telegram

          Frequently asked about Cloud Mail

          What is Cloud Mail?+

          Cloud Mail is a self-hosted Fastmail/Gmail alternative built on the Cloudflare developer platform. Receive domain email and browse messages in a self-hosted Cloudflare web inbox.

          What does Cloud Mail replace?+

          Cloud Mail is listed as an alternative to Fastmail, Gmail. Compare the features and tradeoffs before migrating.

          What Cloudflare primitives does Cloud Mail use?+

          Cloud Mail is built on D1, Email Workers, KV, R2, Workers, Workers AI.

          How much does Cloud Mail cost to run?+

          The documented Cloud Mail deployment can use Cloudflare Free allowances for a small workload under the request, CPU and service-specific quotas below. This is conditional eligibility, not a measured zero-cost deployment; optional features, domains and external providers can add costs. Workers Free allows 100,000 requests per day shared across the account and 10 ms CPU per invocation; measure CPU-heavy authentication, parsing and rendering before assuming it fits. Keep aggregate D1 use below 5 million rows read/day, 100,000 rows written/day and 5 GB total storage; a request can touch many rows. Keep KV below 100,000 reads/day, 1,000 writes, deletes and list operations/day each, and 1 GB; cache refreshes and backups consume writes. Use R2 Standard storage, at most 10 GB-month, 1 million Class A operations and 10 million Class B operations/month; provision an eligible billing-enabled R2 account. Only ordinary Free-eligible Workers AI models are covered, within 10,000 neurons/day; optional external providers and paid-only models are excluded. Inbound Email Routing can use Workers Free, but processing consumes Workers quotas and requires a domain; arbitrary-recipient outbound email requires Workers Paid. Use a small personal or team workload; domain registration and optional third-party providers are separate costs. Provision your own IDs, secrets and migrations. Check current Cloudflare pricing before deploying.

          Is Cloud Mail open source?+

          The upstream repository declares the MIT license. Read its terms at https://raw.githubusercontent.com/maillab/cloud-mail/ec7a2bb17c950576c38d7308128cac7696fea169/LICENSE. Source code and contributor credit are available at https://github.com/maillab/cloud-mail.

          Discussion · 0

          sign in to comment →
          No comments yet — be the first.