白嫖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_EMAILtrue #允许发送邮件,不配置意味着不允许
ENABLE_USER_DELETE_EMAILtrue #允许删除,不配置同理
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 发送邮件
    注册 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吧(

鸣谢


官方文档
github链接

Comment