白嫖CloudFlare建立自己的电子邮局

目标

  1. 创建属于自己的cloudflare邮箱系统
  2. 打开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→编辑代码
下载这个js然后上传上去
然后在设置里
如果你想用自己的域名就在‘域和路由’里添加一个域名(注意,这个域名是用于api的域名,不是用于登录web邮箱的域名
然后在’变量和机密’中添加变量

下面等号左边为value,等号右边为值,符号(比如引号和括号也要输入在cf框内),如果不需要就不用增加变量 ``` # TITLE = "Custom Title" # 自定义网站标题 PREFIX = "tmp" # 要处理的邮箱名称前缀,不需要后缀可配置为空字符串 # (min, max) adderss的长度,如果不设置,默认为(1, 30) # ANNOUNCEMENT = "Custom Announcement" # 自定义公告 # address name 的正则表达式, 只用于检查,符合条件将通过检查 # ADDRESS_CHECK_REGEX = "^(?!.*admin).*" # address name 替换非法符号的正则表达式, 不在其中的符号将被替换,如果不设置,默认为 [^a-z0-9], 需谨慎使用, 有些符号可能导致无法收件 # ADDRESS_REGEX = "[^a-z0-9]" # MIN_ADDRESS_LEN = 1 # MAX_ADDRESS_LEN = 30 # 如果你想要你的网站私有,取消下面的注释,并修改密码 # PASSWORDS = ["123", "456"] # admin 控制台密码, 不配置则不允许访问控制台 # ADMIN_PASSWORDS = ["123", "456"] # 警告: 管理员控制台没有密码或用户检查 # DISABLE_ADMIN_PASSWORD_CHECK = false # admin 联系方式,不配置则不显示,可配置任意字符串 # 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 角色配置, 如果用户角色等于 ADMIN_USER_ROLE 则可以访问 admin 控制台 # ADMIN_USER_ROLE = "admin" # the role which can access admin panel # 用户角色配置, 如果 domains 为空将使用 default_domains # 如果 prefix 为 null 将使用默认前缀, 如果 prefix 为空字符串将不使用前缀 # USER_ROLES = [ # { domains = ["xxx.xxx1" , "xxx.xxx2"], role = "vip", prefix = "vip" }, # { domains = ["xxx.xxx1" , "xxx.xxx2"], role = "admin", prefix = "" }, # ] JWT_SECRET = "xxx" # 用于生成 jwt 的密钥, jwt 用于给用户登录以及鉴权 BLACK_LIST = "" # 黑名单,用于过滤发件人,逗号分隔 # 是否允许用户创建邮件, 不配置则不允许 ENABLE_USER_CREATE_EMAIL = true # 允许用户删除邮件, 不配置则不允许 ENABLE_USER_DELETE_EMAIL = true # 允许自动回复邮件 ENABLE_AUTO_REPLY = false # 是否启用 webhook # ENABLE_WEBHOOK = true # 前端界面页脚文本 # COPYRIGHT = "Dream Hunter" # DISABLE_SHOW_GITHUB = true # 是否显示 GitHub 链接 # 默认发送邮件余额,如果不设置,将为 0 # DEFAULT_SEND_BALANCE = 1 # NO_LIMIT_SEND_ROLE = "vip" # 可以无限发送邮件的角色 # Turnstile 人机验证配置 # CF_TURNSTILE_SITE_KEY = "" # CF_TURNSTILE_SECRET_KEY = "" # telegram bot 最多绑定邮箱数量 # TG_MAX_ADDRESS = 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 ,否则无法识别(

配置邮件转发

  1. 配置对应域名的 电子邮件 DNS 记录, 如果是多个域名,需要配置多个域名的 电子邮件 DNS 记录
  2. 在将电子邮件地址绑定到您的 Worker 之前,您需要启用电子邮件路由并拥有至少一个经过验证的电子邮件地址。
  3. 配置每个域名的 Cloudflare Email Routing catch-all 发送到 worker

Pages前端

Wokers和Pages→创建→Pages→上传资产

  1. 这个页面里的‘输入地址’输入api网址,就是刚才workers里的https://xxx.aaa.dev或者你自己的域名,然后点击生成后下载压缩包后上传到这个pages
  2. 手动下载这个压缩包,修改压缩包里面的 index-xxx.js 文件 ,xx 是随机的字符串
    搜索 https://temp-email-api.xxx.xxx ,替换成你worker 的域名,然后压缩成新的zip文件,然后上传
    在自定义域里可以用自己的域名

配置发送邮件

  1. 使用 Cloudflare Workers 给已认证的邮箱发送邮件
    admin 后台 账号配置 已验证地址列表(可通过 cf 内部 api 发送邮件)
  2. 使用 resend 发送邮件
    注册 Resend 根据提示添加 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的话建议看官方文档搭建 SMTP IMAP 代理服务 | 临时邮箱文档
不是因为我看不懂
绝对不是(
而且cf的smtp服务好像只能给同一个cf邮局内的邮件发送,所以还是用resend吧(

鸣谢


官方文档
github链接

31 个赞

再补一点githubaction部分的 :face_with_peeking_eye:,方便后续更新

2 个赞

季度泥得菜花:bili_057:

1 个赞

那个乱码有没有办法解决,tg机器人收到的信息,wasm不会整,再就是mini app.求大佬赐教。

1 个赞

awesome

感谢大佬分享。

1 个赞

感谢佬的教程

1 个赞

我用路由转发挺方便的

2 个赞

感谢佬的分享

2 个赞

cloudflare真啥都能干,省去一台vps。

2 个赞

可以,感谢整理