📱 我只想在常用手机上收到旧号码的验证码,不想再带一部手机。目标是旧 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,备份现有配置后合并路由,不覆盖原站点。
服务器交给智能体做什么
- 安装参考实现并初始化私有配置:程序放
/opt/sms-relay,配置和 SQLite 放/var/lib/sms-relay。初始化脚本询问收件箱密码,生成独立的上传令牌与会话签名密钥;已有配置不会被覆盖。 - 接入现有 HTTPS:把包内
location片段合并到自己域名的 HTTPSserver中;运行nginx -t通过后 reload。配置服务账户、目录权限和 systemd 自启。 - 先验证服务:
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,动作按以下顺序:
- 保存快捷指令输入的原始 Message 对象,用“设定变量”保存为
OriginalMessage,再取Content、Sender、Recipients、Name,不要先把整个输入变成纯文本。 - 获取“当前日期”,格式用 ISO 8601 并开启“时间”,写入
uploaded_at。这是上传时刻,不是短信发送时间。 - “获取 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 样本在锁屏下都只上传一次。最初能用、优化中漏传、授权后恢复,是三个不同阶段。

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

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 秒内真正收到的相同短信也可能合并。手机上传没有离线队列,重启后首次解锁前未验证。只要接受这些边界,这篇文章的输入就是环境与凭据,输出应是能用真实短信验收的完整链路。
