目标
- 创建属于自己的cloudflare邮箱系统
- 打开SMTP服务用于自己的系统
创建D1数据库
cloudflare→worker和pages→D1 SQL 数据库→创建
自己输入名称,地区选不选吧,理论上速度都差不多
CREATE TABLE IF NOT EXISTS raw_mails (
id INTEGER PRIMARY KEY,
message_id TEXT,
source TEXT,
address TEXT,
raw TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_raw_mails_address ON raw_mails(address);
CREATE TABLE IF NOT EXISTS address (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_address_name ON address(name);
CREATE TABLE IF NOT EXISTS auto_reply_mails (
id INTEGER PRIMARY KEY,
source_prefix TEXT,
name TEXT,
address TEXT UNIQUE,
subject TEXT,
message TEXT,
enabled INTEGER DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_auto_reply_mails_address ON auto_reply_mails(address);
CREATE TABLE IF NOT EXISTS address_sender (
id INTEGER PRIMARY KEY,
address TEXT UNIQUE,
balance INTEGER DEFAULT 0,
enabled INTEGER DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_address_sender_address ON address_sender(address);
CREATE TABLE IF NOT EXISTS sendbox (
id INTEGER PRIMARY KEY,
address TEXT,
raw TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_sendbox_address ON sendbox(address);
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
user_email TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
user_info TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_users_user_email ON users(user_email);
CREATE TABLE IF NOT EXISTS users_address (
id INTEGER PRIMARY KEY,
user_id INTEGER,
address_id INTEGER UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_users_address_user_id ON users_address(user_id);
CREATE INDEX IF NOT EXISTS idx_users_address_address_id ON users_address(address_id);
CREATE TABLE IF NOT EXISTS user_roles (
id INTEGER PRIMARY KEY,
user_id INTEGER UNIQUE NOT NULL,
role_text TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_user_roles_user_id ON user_roles(user_id);
CREATE TABLE IF NOT EXISTS user_passkeys (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
passkey_name TEXT NOT NULL,
passkey_id TEXT NOT NULL,
passkey TEXT NOT NULL,
counter INTEGER DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_user_passkeys_user_id ON user_passkeys(user_id);
CREATE UNIQUE INDEX IF NOT EXISTS idx_user_passkeys_user_id_passkey_id ON user_passkeys(user_id, passkey_id);
workers后端
Workers 和 Pages→创建→创建worker→跳过编辑代码
去worker设置的 可观察性→运行时→兼容性标志添加
nodejs_compat
然后再下载这个js然后上传上去
再去设置里
如果你想用自己的域名就在‘域和路由’里添加一个域名(注意,这个域名是用于api的域名,不是用于登录web邮箱的域名)
然后在’变量和机密’中添加变量
配置项 | 值 |
---|---|
TITLE# 自定义网站标题 | “Custom Title” |
PREFIX# 要处理的邮箱名称前缀,不需要后缀可配置为空字符串 | “tmp” |
MIN_ADDRESS_LEN # (min, max) adderss的长度,如果不设置,默认为(1, 30) | 1 |
MAX_ADDRESS_LEN | 30 |
ADDRESS_CHECK_REGEX | “^(?!.admin).” |
ADDRESS_REGEX | “[^a-z0-9]” |
PASSWORDS# 如果你想要你的网站私有,添加密码 | [“123”, “456”] |
ADMIN_PASSWORDS# admin 控制台密码, 不配置则不允许访问控制台 | [“123”, “456”] |
DISABLE_ADMIN_PASSWORD_CHECK# admin 联系方式,不配置则不显示,可配置任意字符串 | false |
ADMIN_CONTACT | "[email protected]" |
DEFAULT_DOMAINS# 默认用户可用的域名(未登录或未分配角色的用户) | [“xxx.xxx1” , “xxx.xxx2”] |
DOMAINS# 你的域名, 支持多个域名 | [“xxx.xxx1” , “xxx.xxx2”] |
DOMAIN_LABELS# 对于中文域名,可以使用 DOMAIN_LABELS 显示域名的中文展示名称 | [“中文.xxx”, “xxx.xxx2”] |
USER_DEFAULT_ROLE# 新用户默认角色, 仅在启用邮件验证时有效 | “vip” |
ADMIN_USER_ROLE# admin 角色配置, 如果用户角色等于 ADMIN_USER_ROLE 则可以访问 admin 控制台 | “admin” |
USER_ROLES | { domains = [“xxx.xxx1” , “xxx.xxx2”], role = “vip”, prefix = “vip” } |
{ domains = [“xxx.xxx1” , “xxx.xxx2”], role = “admin”, prefix = “” } | |
JWT_SECRET# 用于生成 jwt 的密钥, jwt 用于给用户登录以及鉴权 | “xxx” |
BLACK_LIST# 黑名单,用于过滤发件人,逗号分隔 | “” |
ENABLE_USER_CREATE_EMAIL# 是否允许用户创建邮件, 不配置则不允许 | true |
ENABLE_USER_DELETE_EMAIL# 允许用户删除邮件, 不配置则不允许 | true |
ENABLE_AUTO_REPLY# 允许自动回复邮件 | false |
COPYRIGHT# 前端界面页脚文本 | “Dream Hunter” |
DISABLE_SHOW_GITHUB# 是否显示 GitHub 链接 | true |
DEFAULT_SEND_BALANCE# 默认发送邮件余额,如果不设置,将为 0 | 1 |
NO_LIMIT_SEND_ROLE# 可以无限发送邮件的角色 | “vip” |
CF_TURNSTILE_SITE_KEY# Turnstile 人机验证配置 | “” |
CF_TURNSTILE_SECRET_KEY# Turnstile 人机验证配置 | “” |
TG_MAX_ADDRESS# telegram bot 最多绑定邮箱数量 | 5 |
FORWARD_ADDRESS_LIST# 全局转发地址列表,如果不配置则不启用,启用后所有邮件都会转发到列表中的地址 | [“[email protected]”] |
这里说一下我的配置
ADMIN_PASSWORDS | [“你的管理员密码”] |
---|---|
PASSWORDS | [“网页登录密码,如果不需要私人网页那不用填这个”] |
TITLE | “网站标题” |
DOMAINS | [“你的域名”] |
ENABLE_USER_CREATE_EMAIL | true #允许发送邮件,不配置意味着不允许 |
ENABLE_USER_DELETE_EMAIL | true #允许删除,不配置同理 |
JWT_SECRET | “xxx” 不知道有什么用但是应该有用 |
PREFIX | " " #要处理的邮箱名称前缀,不需要前缀可配置为空字符串 |
然后配置D1数据库
往下滑到 绑定→D1数据库
名称为 DB 值为你之前创建的数据库
然后访问网址,如果显示OK就执行下一步,如果不OK就看看是哪里出了问题
如果你要启用注册用户功能,并需要发送邮件验证,则需要创建 KV 缓存, 不需要可跳过此步骤
点击 Workers和Pages→KV→创建命名空间,名称随意
然后在刚才绑定数据库那里再绑定个KV空间就行
worker kv的变量名称要设置为大写的 KV ,否则无法识别(
配置邮件转发
- 配置对应域名的 电子邮件 DNS 记录, 如果是多个域名,需要配置多个域名的 电子邮件 DNS 记录
- 在将电子邮件地址绑定到您的 Worker 之前,您需要启用电子邮件路由并拥有至少一个经过验证的电子邮件地址。
- 配置每个域名的 Cloudflare Email Routing catch-all 发送到 worker
Pages前端
Wokers和Pages→创建→Pages→上传资产
- 在这个页面里的‘输入地址’输入api网址,就是刚才workers里的https://xxx.aaa.dev或者你自己的域名,然后点击生成后下载压缩包后上传到这个pages
- 手动下载这个压缩包,修改压缩包里面的 index-xxx.js 文件 ,xx 是随机的字符串
搜索 https://temp-email-api.xxx.xxx ,替换成你worker 的域名,然后压缩成新的zip文件,然后上传
在自定义域里可以用自己的域名
配置发送邮件
- 使用 Cloudflare Workers 给已认证的邮箱发送邮件
admin 后台 账号配置 已验证地址列表(可通过 cf 内部 api 发送邮件) - 使用 resend 发送邮件
注册 https://resend.com/domains 根据提示添加 DNS 记录,API KEYS 页面创建 api key
在 cloudflare worker 页面的变量中添加 RESEND_TOKEN
如果你有多个域名,对应不同的 api key,可以在变量中添加多个 secret, 名称为 RESEND_TOKEN_ + <. 换成 _ 的 大写域名>,例如你的域名为1.aaa.bbb和2.ccc.ddd
RESEND_TOKEN_1_aaa_bbb key1
RESEND_TOKEN_2_ccc_ddd key2
SMTP
如果你用了resend服务,直接用resend的就好
如果用cf的话建议看官方文档https://temp-mail-docs.awsl.uk/zh/guide/feature/config-smtp-proxy.html
不是因为我看不懂
绝对不是(
而且cf的smtp服务好像只能给同一个cf邮局内的邮件发送,所以还是用resend吧(