Boji / 77liu.top
← 返回时间线

2026/11/01 12:33 / 自动化实践

用 Codex 配置 iPhone 验证码转发

主人编辑 ↗

可交给智能体执行的配置指南:通过 iPhone 镜像建立短信自动化,部署上传与收件箱服务,再接入群机器人。

TL;DR:旧 iPhone 留在家里接电、联网,收到含数字的短信后自动上传服务器,提取验证码并推送飞书。配置时由 Codex 操作 Mac 上的 iPhone 镜像;运行时不需要 Mac。本文给出环境、上传协议、快捷指令结构和验收要求,可连同文末任务说明交给智能体执行。

📱 我只想在常用手机上收到旧号码的验证码,不想再带一部手机。目标是旧 iPhone 锁屏也能转发,Mac 可以关机。

实测设备为 iPhone 13 Pro Max、iOS 18.7.8。下面按实施顺序写;地址、账号、服务器和机器人都替换成读者自己的。

概念插画:旧手机经数字规则筛选,只上传一次,再由服务器通知
数字规则负责触发,服务器负责保存与通知。

1.先准备环境:Xcode 和开发者模式不是前提

Important

🛠️ 本方案用 iPhone 镜像操作系统自带的快捷指令,不安装自编译应用,不需要 Xcode 配对或开启开发者模式。 开发者模式用于运行开发签名应用,与这里的界面配置是两条路线。苹果开发者说明

配置阶段准备好:

  • Mac 与 iPhone 能使用 iPhone 镜像:Mac 为 Apple 芯片或带 T2 的机型,macOS 15+;iPhone 为 iOS 18+,设有锁屏密码。两者同一 Apple 账户并开启双重认证、Wi-Fi 与蓝牙,手机锁屏放在 Mac 附近。镜像条件与连接方法
  • 在 Codex 中安装或启用 Computer Use 插件,并在电脑操控设置中允许“iPhone 镜像”;按提示授予 Mac 屏幕录制与辅助功能权限。先让智能体自检能否读取并点击窗口,不能把纯命令行会话当作已经具备桌面操控。电脑操控说明
  • 一台可 SSH 登录、有 sudo 权限的 Linux 服务器;一个已解析到它、HTTPS 可用的域名;一个你有权添加机器人的飞书或 Lark 群。

运行阶段只需 iPhone 有电、能接收运营商短信、能访问服务器。Wi-Fi 解决上传联网,不代替运营商短信接收条件。

2.先部署服务器,再把机器人接通

🔧 我已有 Ubuntu 22.04、Python 3、Nginx 和 HTTPS 网站。新增的是一个 Python 标准库服务,监听 127.0.0.1:4291,由 Nginx 将 /tool/ 转发给它;SQLite 保存短信,systemd 保持服务运行、开机启动。不需要 Mac 中转,也不需要额外数据库服务。

服务必须具备:令牌鉴权上传、120 秒去重、验证码分类、密码保护的收件箱、机器人发送与失败重试。去重键为设备、发送方、正文与原始时间字段,上传时刻不参与。多机器人分别记录结果,只重试失败目标,最多尝试 5 次。默认只推验证码,可切换全部已接收短信。

下载参考源码包:包含运行文件、systemd、Nginx 片段、新环境初始化脚本、部署说明与测试,不含真实凭据。让智能体先读包内 README,备份现有配置后合并路由,不覆盖原站点。

服务器交给智能体做什么

  1. 安装参考实现并初始化私有配置:程序放 /opt/sms-relay,配置和 SQLite 放 /var/lib/sms-relay。初始化脚本询问收件箱密码,生成独立的上传令牌与会话签名密钥;已有配置不会被覆盖。
  2. 接入现有 HTTPS:把包内 location 片段合并到自己域名的 HTTPS server 中;运行 nginx -t 通过后 reload。配置服务账户、目录权限和 systemd 自启。
  3. 先验证服务:GET https://<你的域名>/tool/api/health 返回 {"ok":true};未登录查询短信应返回 401。打开 /tool/,用刚设置的密码登录。
%%{init: {"themeVariables": {"fontSize": "14px"}, "flowchart": {"nodeSpacing": 8, "rankSpacing": 18, "padding": 6}}}%%
flowchart TD
 A([手机收信]) --> B{含0–9?}
 B -->|否| X([结束])
 B -->|是| C[最小数字]
 C --> D[/HTTPS<br/>上传/]
 D --> E[鉴权·去重<br/>分类·保存]
 E --> F[(收件箱)]
 E -->|符合范围| G[群通知]

我复用了个人网站原有认证;新部署直接设置自己的收件箱密码即可,不需要先搭一套博客编辑后台。收件箱密码、手机上传令牌、机器人 Webhook 是三个不同用途的凭据。

添加群机器人并提供 Webhook

📬 飞书桌面端进入目标群:群设置 → 群机器人 → 添加机器人 → 自定义机器人,设置名称并复制 Webhook。官方指南

将 Webhook、目标标记、推送范围交给 Codex;开启签名校验时,一并提供签名密钥。也可在收件箱“飞书推送设置”里自己填写。若设置关键词校验,允许消息中的 短信转发;若设置 IP 白名单,填写服务器实际出口 IP。

让 Codex 先发不含短信的连接测试,确认落在预期群里,再接手机。示例仅用占位地址:https://open.feishu.cn/open-apis/bot/v2/hook/<ID>;Lark 使用 open.larkoffice.com。真实地址只写私有配置。

实拍:收件箱密码登录与保留登录选项
收件箱需要登录;图中是我复用网站认证后的界面。

手机与服务器只约定这一个上传接口

POST https://<你的域名>/tool/api/ingest,Content-Type: application/json:

json
{
  "token": "<单独生成的上传令牌>",
  "text": "测试验证码 123456",
  "device": "my-iphone",
  "sender": "<发送方>",
  "recipient": "<收件人>",
  "uploaded_at": "2026-11-01T12:00:00+08:00"
}

text 必填,1–16000 字符;元数据均为字符串,可缺省。令牌也可改放 Authorization: Bearer <令牌>,与 JSON token 二选一。另支持 message_name、received_at,取不到原始发送时间就留空。

HTTP 200 表示已接收,例如 {"ok":true,"duplicate":false,"id":22,"category":"verification"};机器人送达要另查 push_status,不能只看 200。重复上传返回 duplicate:true;令牌错误 401、字段错误 400、非 JSON 415、请求体超 64 KiB 为 413。

分类先找“验证码/动态密码/verification code/OTP”等语境,再找附近 4–8 位字母数字码。独立数字串不默认当验证码;有验证语境但提取不到码,仍入验证码类,码为空。全部页保留原文。

3.让 Codex 通过镜像配置 iPhone

Note

🔐 Mac 保持解锁,接收 iPhone 锁屏且暂时不要手动操作。 本人完成镜像首次登录及系统身份验证;连接成功后,Codex 才能在镜像窗口里点按、输入和检查快捷指令。若提示“iPhone 使用中”,先锁屏;若 Mac 被锁定,先在 Mac 上手动解锁。

建立公共上传指令 SMSUpload

让 Codex 打开镜像中的“快捷指令”,新建 SMSUpload,动作按以下顺序:

  1. 保存快捷指令输入的原始 Message 对象,用“设定变量”保存为 OriginalMessage,再取 Content、Sender、Recipients、Name,不要先把整个输入变成纯文本。
  2. 获取“当前日期”,格式用 ISO 8601 并开启“时间”,写入 uploaded_at。这是上传时刻,不是短信发送时间。
  3. “获取 URL 内容”选择 POST、JSON 请求体,按上面的协议填字段与令牌。空的可选属性留空或省略;所有字段都要转换为字符串,不能传联系人或消息对象本身。

🕒 调试时可先用测试字典验证接口,再恢复真实 Message 输入。固定文本样本跑通,不代表发送方等消息属性也取对了。

建立十条信息自动化与九个 Gate

在本机 iOS 18.7.8 上,“信息包含”留空不能继续,因此采用包含 0–9 的十条规则。这是含数字短信的覆盖方案,不等于无条件转发全部短信。

让 Codex 先创建 SMSGate1–SMSGate9:先保存 OriginalMessage,再读取其 Content,用“匹配文本”检查是否含更小数字;匹配成功才调用 SMSUpload,传入原始 Message。

text
Gate1: ^[^0]*$          Gate2: ^[^01]*$
Gate3: ^[^012]*$        Gate4: ^[^0123]*$
Gate5: ^[^01234]*$      Gate6: ^[^012345]*$
Gate7: ^[^0123456]*$    Gate8: ^[^01234567]*$
Gate9: ^[^012345678]*$

具体可以用“重复每一项匹配结果”包住“运行快捷指令”:无匹配就不调用,有匹配最多调用一次。随后在“自动化 → 信息”逐条设置“信息包含 0”至“信息包含 9”,发送人不限定,均选 立即运行。0 直接调用 SMSUpload,1–9 分别调用对应 Gate,始终传入触发消息。

💡 例如 验证码 234567 会启动多条自动化,但只有 Gate2 放行。最小数字负责上传,其余规则自行结束;不需要共享文件,也不用争抢执行顺序。

自动配置结束前,逐条处理首次授权

Important

这次漏传的实际阻塞,是 Gate 首次调用 SMSUpload 的授权尚未完成。 含 0 的测试绕过 Gate,即使成功,也不能证明其余九条可用。逐条触发并允许后,才能验收无人操作的锁屏转发。

Codex 每建完一条就读回触发条件、目标指令和输入变量,记录 0–9 完成状态。系统询问“允许运行另一个快捷指令吗”或网络访问时,由本人按实际提示确认。这不是承诺零人工介入;需要本人确认的步骤不要让智能体反复重试或假报完成。

4.按最短顺序验收与排错

🧪 从另一台手机发送测试短信,服务器查看原文、号码、完整时间、重复计数和每个机器人状态。按这条顺序推进:

服务与机器人连接测试 → 手机试传 → 0–9 单分支 → 多数字互斥 → 退出镜像后的锁屏测试。

  • 单分支:分别发 验证码 000000 至 验证码 999999,验证十条路径,期间完成首次授权。
  • 互斥:发 验证码 222223,只上传一次;再发 测试验证码 234567,批次 8901,覆盖 0–9,确认仍只上传一次。
  • 最终锁屏:退出 iPhone 镜像,不碰接收手机,发 锁屏验收验证码 123456,批次 789 和 锁屏验收验证码 999999。两条均仅一条入库、duplicates=0、机器人 sent才通过;不要把镜像连着时的手动运行当验收。

排错按链路截断:没触发先查自动化与首次授权;无记录查网络、令牌和请求字段;没通知查分类范围与机器人响应。 ISO 只有日期就打开“时间”;数字被判普通短信时,先看有没有验证码语境。

展开实际迭代与测试证据

第一版十条自动化都直接上传,含十个数字的测试短信产生 1 条记录、9 次重复。第二版加入最小数字筛选;处理中途的首次调用授权后,最终多数字及纯 9 样本在锁屏下都只上传一次。最初能用、优化中漏传、授权后恢复,是三个不同阶段。

历史实拍:第一版收件箱合并9次重复上报
第一版收件箱实拍:重复请求由服务器合并,当时尚未补齐发送方。

参考实现的并发去重、分类、元数据、双机器人独立重试和认证均有自动测试。下图为复盘时的实际输出,不是新一轮手机锁屏测试。

实际服务7项与认证3项测试通过
服务与认证测试输出;完整测试文件在源码包内。

5.把本文交给智能体时,附上这段任务说明

以下信息由使用者填写。不必先懂每条命令,但服务器访问、目标群和身份确认仍需要本人提供。

text
请依据本文完成 iPhone 短信上传、私有收件箱与飞书机器人转发。

我的环境:iPhone型号/iOS=[填写];Mac型号/macOS=[填写]。
镜像已能连接;请先检查你是否有桌面操控权限。
服务器SSH主机/用户/端口=[填写],密钥在本机[私有路径]。
HTTPS域名=[填写],现有网站及不得改动的路由=[填写]。
目标机器人标记=[填写],Webhook/签名密钥从本机私有文件[路径]读取。
推送范围=[仅验证码/全部已接收短信];收件箱密码由我在初始化时输入。

先读取本文的参考源码包和README。若无法取得源码,按本文协议实现:
Python标准库+SQLite+systemd+Nginx /tool/,独立上传令牌、密码登录、
120秒去重、验证码分类、各机器人独立重试,不能将私有配置放进静态站。

先验证HTTPS、上传鉴权和目标群测试通知,再通过iPhone镜像建立
SMSUpload、SMSGate1–9、十条立即运行的信息自动化。
逐条核对变量与首次授权,记录完成状态;需要我解锁或确认时明确提示。
最后退出镜像,按本文单分支、多数字与锁屏样本验收。
未获得真实短信记录和机器人成功状态前,不报告端到端完成。
保留原站路由;凭据不入文章、Git、截图或公开日志。

总结

Tip

🎯 最重要的是三件事:备齐环境;上传协议与消息变量对应;逐条授权后做锁屏验收。 Xcode 不是必需环节,Mac 只负责配置。

当前规则可能漏掉无数字短信;120 秒内真正收到的相同短信也可能合并。手机上传没有离线队列,重启后首次解锁前未验证。只要接受这些边界,这篇文章的输入就是环境与凭据,输出应是能用真实短信验收的完整链路。

— 完 —
← 回到时间线