利用cloudflarework+pages部署收发邮件系统-附邮箱API接码
← 返回博客列表

利用cloudflarework+pages部署收发邮件系统-附邮箱API接码

2024/12/23·技术教程·未分类

最终效果 视频教程 项目官方文档 https://temp-mail-docs.awsl.uk/zh/guid

最终效果

图片[1]|5v|5v

视频教程

项目官方文档

https://temp-mail-docs.awsl.uk/zh/guide/ui/d1.html

项目github仓库

https://github.com/dreamhunter2333/cloudflare_temp_email

前期准备

两个二级域名:55v.net

前端域名:mail.55v.net

后端接口域名:mail-api.55v.net

1.数据库设置

  • 在works和pages中选D1数据库
  • 创建数据库起名字dbmail
  • 创建后进入到mail数据库,然后打开consol标签

-把 https://github.com/dreamhunter2333/cloudflare_temp_email/blob/main/db/schema.sql这个schema.sql文件中的内容复制到donsol中,然后点击Execute按钮

  • 数据库创建完成

2.后端部署

  • 还是在在works和pages中,创建应用程序,选workers
  • 起名字mail-api,保存,然后点右下角完成.
  • 然后界面中右上角点edit code.
  • 点击 Settings -> Runtime, 修改 Compatibility flags, 增加 nodejs_compat
  • 然后再左边点击文件按钮,右键点works.js然后删除.
  • 再下载works.js
  • 右键点击,出现上传,把下载的works.js上传上去,然后右上角部署
  • 再来到项目的settings–>Variables中,添加4个文本变量
ADMIN_PASSWORDS =["1234"]      #管理员密码
PASSWORDS =["1234"]        #网站访问密码,建议不用设置
DOMAINS =["55v.net"]                 #邮箱主域名
JWT_SECRET =["qqqqwwwweee"]
TELEGRAM_BOT_TOKEN=TGbot的token 建议设置
  • 在KV Namespace Bindings中添加一个KV

创建一个KV,起名字kvmail

  • 然后再回到workers设置这里Variable name添加KV 大写.选择创建的KV库kvmail

添加D1数据库

  • 同样在settings–>Variable中,添加DB大写.选择最开始创建的D1数据库dbmail

然后添加自定义域名

最后再进行部署一次. 后端验证

  • 后端设置完成后,可以通过访问后端域名的url及目录进行验证,例如我的域名
  • mail-api.55v.net返回结果OK
  • mail-api.55v.net/health_check 返回结果OK
  • 则说明后端配置完成.后期可随时在变量中增删内容

3.前端部署

3.邮件路由设置

  • 来到https://dash.cloudflare.com 面板首页,然后选择需要使用的域名进入.
  • 左边选择Email菜单,在Email Routing中选择Routing ruls中Catch-all address

激活,并且edit.

  • 其中的Action选择的是Send to a Worker ,目标选择后端的worker名字
  • 验证:截止到现在登录前端url已经可以

4.发送邮件设置

  • https://resend.com/domains进行域名验证
  • 然后在API-Key 中创建一个api,全部权限,然后把密码拷贝
  • 到后端的Worker中Settings–>Environment Variables–>添加一个密钥变量
  • RESEND_TOKEN = 上一步拷贝出来的密码

截止到以上步骤,就可以完整的收发邮件了.

如果需要更方便的朋友,强烈建议挂上Telegram机器人

5.Telegram机器人

  • 创建机器人(具体方法自己搜.)
  • 拿到用于这个项目的机器人token,还有telegram的账户id.
  • 到后端的Worker中Settings–>Environment Variables–>添加一个文本变量
  • TELEGRAM_BOT_TOKEN = 机器人token
  • 在邮件的管理后台,机器人中填入账户管理员id.(电报随便搜一下ID查询机器人查看自己的ID),以后所有邮件都会通过机器人发给你的飞机ID(不管是设定的邮箱还是没设定的别名邮箱都能接收)
  • 图片[3]|5v|5v

图片[4]|5v|5v

6.功能讲解与配置

图片[5]|5v|5v

账号:就是邮箱

邮箱凭证:就是邮箱的密钥,只要有密钥就可以接收这个邮箱的邮件,连用户账密都不需要

用户:就是web端的用户,用户可以和邮箱做绑定,那么这个用户就可以接收这些邮箱的邮件,这里不建议设置用户,所以我把用户设置的运行用户注册关了

使用方式:

  • 用户拿到邮箱凭证就可以在网页端接收邮件,也可以在飞机Bot上绑定这个邮箱凭证,以后飞机也能接收这个邮箱,所以用户使用网页端就很多余,除非要通过这个邮箱发邮件
  • 发邮件,拿到邮箱凭证想发邮件需要想管理员申请,管理员可以设置这个邮箱的发件额度(resend每天的发件额度是100)

6.邮箱接码api

这是我自己后期加的一个需求,因为并不是所有人都用飞机接邮件,所以用api接码是最简单的

  • 注册一个pythonanywhere(免费的python代码api,三个月激活一次,主要是为了解析邮件格式,workers代码解析不了邮件格式),也可以直接用我的接口,代码如下
# A very simple Flask Hello World app for you to get started with...

from flask import Flask, request, Response, jsonify
import email
from email.policy import default
import base64


app = Flask(__name__)

@app.route('/decode', methods=['POST'])
def get_email_main():
    try:
        # 获取请求中的 JSON 数据
        data = request.json.get('encodedEmail')
        if not data:
            return jsonify({"error": "Missing 'data' parameter."}), 400

        # Base64 解码
        raw_email = base64.b64decode(data).decode('utf-8')
        message = email.message_from_string(raw_email, policy=default)

        # 提取发件人、收件人和主题
        from_address = message["From"]
        to_address = message["To"]
        subject = message["Subject"]
        date = message["Date"]

        # 提取邮件内容
        def get_email_content(msg):
            if msg.is_multipart():
                for part in msg.iter_parts():
                    content_type = part.get_content_type()
                    if content_type == "text/plain" or content_type == "text/html":
                        return part.get_content()
            else:
                return msg.get_content()

        content = get_email_content(message)

    # 打印结果
        print(f"发件人: {from_address}")
        print(f"收件人: {to_address}")
        print(f"发件时间: {date}")
        print(f"主题: {subject}")
        print(f"内容: {content}")



        # 返回解码后的数据
        return jsonify({"from_address": from_address,"to_address": to_address,"date": date,"subject": subject,"content": content})
    except Exception as e:
        return jsonify({"error": str(e)}), 500
  • 然后再创建一个workers,代码如下,能看明白的可自行编辑条件,我设置的是查询最近的一封邮件
export default {
  async fetch(request) {
    // 解析 URL 和查询参数
    const url = new URL(request.url);
    const key = url.searchParams.get("key");

    if (!key) {
      return new Response("Missing 'key' in query parameters", { status: 400 });
    }

    // 调用邮件 API
    const apiUrl = `https://mail-api.55v.net/api/mails?limit=1&offset=0`;

    try {
      const apiResponse = await fetch(apiUrl, {
        method: "GET",
        headers: {
          Authorization: `Bearer ${key}`,
          "x-custom-auth": "访问密码", // 如果启用了自定义密码
          "Content-Type": "application/json",
        },
      });
      const resJson = await apiResponse.json();
      const rawEmail = resJson?.results?.[0]?.raw;
      if (!rawEmail) {
        return new Response("邮件列表为空", { status: 404 });
      }
      const encodedEmail = btoa(rawEmail);
      // POST 编码后的内容到目标 URL
      const postUrl = `https://mail5v.pythonanywhere.com/decode`;
      const postResponse = await fetch(postUrl, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ encodedEmail }),
      });


      // 返回目标服务器的响应
      const postResult = await postResponse.json();
      return new Response(JSON.stringify(postResult));
    } catch (error) {
      return new Response(`Error: ${error.message}`, { status: 500 });
    }
  },
};
  • 然后绑定域名,GET访问,前面是我绑定的域名,后面拼接邮箱凭证
https://5vmail.cmcnca.com/?key=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZGRyZXNzIjoieHN0YzVzY3NAY21jbmNhLmNvbSIsImFkZHJlc3NfaWQiOjExNH0.gT2TYjEnY9oXN0Onl9l_TieyKzfrfj-KnU_LHi4UTlE
  • 生成邮箱
import requests


res = requests.post(
    "https://mail-api.55v.net/admin/new_address",
    json={
        "enablePrefix": False,
        "name": "dsfssgfgda22aaa",  #邮箱前缀
        "domain": "cmcnca.com",
    },
    headers={
        'x-admin-auth': "123456",   #管理员密码
        "Content-Type": "application/json"
    }
)
resutl = res.json()

print(resutl['address']+"----https://5vmail.cmcnca.com/?key="+resutl['jwt'])