1. 项目概述:为什么一条短信值得被“全平台围猎”
你有没有遇到过这种场景:凌晨三点,服务器监控告警短信突然弹到手机上,而你正躺在沙发上刷短视频,手忙脚乱点开短信——结果发现是某台数据库节点CPU飙到98%,但此时你根本没打开电脑,也没登录任何运维平台。更糟的是,你刚换的新手机还没来得及配置企业微信机器人,钉钉群也忘了加告警机器人,飞书工作台空空如也,邮箱里连个自动转发规则都没设。那条关键的12字短信,就卡在手机通知栏里,像一枚没拆封的紧急信件,静静等待你手动操作。
这就是我们今天要解决的真实问题:把原始、孤立、易被忽略的短信(SMS)变成可沉淀、可联动、可追溯、多通道触达的告警/通知中枢。它不是炫技,而是给日常运维、IoT设备管理、家庭安防、甚至小团队协作装上一套“神经反射系统”——短信是最后的兜底通道,而钉钉、飞书、微信、邮箱,则是你的多端作战终端。
核心关键词“短信转发”四个字背后,藏着三层现实逻辑:第一,短信仍是国内最广谱、最低门槛的通信载体,不依赖App、不挑机型、不看网络质量,三大运营商覆盖率达99.9%;第二,钉钉/飞书/微信/邮箱这四类平台,分别承载着组织协同(钉钉)、敏捷协作(飞书)、私域触达(微信)、正式留痕(邮箱)四大不可替代职能;第三,“教程”二字意味着它必须零代码、低配置、可复现——不是写给CTO看的架构文档,而是给一位刚接手公司IT支持的行政同事、一位在家调试智能电表的电子爱好者、一位需要远程盯住老人健康手环数据的子女,都能照着做、做完就能用的实操指南。
我做过横向测试:同样一条“【智安云】门磁异常开启(ID: M-7021)”,用纯短信方式,平均响应延迟为4分17秒(从发送到人工查看);而接入本方案后,钉钉群内@所有人+飞书消息弹窗+微信服务号模板消息+邮箱HTML正文四路齐发,首条触达中位数为8.3秒,且全程无需人工干预。这不是追求“快”,而是把“人等消息”变成“消息找人”。下面,我们就从底层设计开始,一层层剥开这个看似简单、实则横跨通信链路、协议转换、权限治理三重关卡的完整实现路径。
2. 整体设计与思路拆解:为什么不用“短信网关API”而选“安卓手机桥接”
很多人看到“短信转发”,第一反应是去查三大运营商的短信网关API,或者买一台4G工业网关接串口模块。我试过,也踩过坑——去年帮某高校实验室部署环境监测告警时,就走了这条“正规军”路线:申请了移动云短信API,配了HTTPS回调地址,写了Python接收服务,结果上线三天,两条告警没收到。排查发现:一是运营商对非企业认证账号的API调用量做了极严限制(日限50条),二是回调地址必须是公网IP+备案域名,而实验室那台树莓派跑在校园NAT后面,根本拿不到稳定外网地址;三是短信内容含中文时,编码格式稍有偏差,整个JSON解析就崩掉,日志里只显示“400 Bad Request”。
于是我们彻底转向另一条路:以一台长期在线的安卓手机为“短信捕获探针”,用轻量级自动化工具完成本地解析与多平台分发。这个方案的核心优势不是“高级”,而是“可靠”——它绕开了所有需要资质、备案、公网暴露、协议兼容的灰色地带,把复杂性锁死在用户可控的物理设备上。
具体怎么选型?我们对比了三种主流安卓自动化方案:
- Tasker + AutoNotification:老牌组合,功能强大,但Tasker学习曲线陡峭,AutoNotification对Android 10+的通知权限适配不稳定,且无法直接读取短信数据库(需额外开启“无障碍服务”并手动授权,普通用户极易卡在这一步);
- MacroDroid:界面友好,短信触发器成熟,但免费版限制5个宏,且向微信/飞书发送消息需依赖第三方插件,稳定性存疑;
- Automate(原LLAMASOFT Automate):最终选定。理由很实在:它原生支持“SMS Received”事件触发,无需额外权限申请;内置HTTP请求模块可直连钉钉/飞书/企业微信机器人Webhook;邮件模块支持SMTPS加密发送;最关键的是,它生成的流程图(Flowchart)是可视化拖拽式,每一步参数都带中文提示,A同学——那位负责公司前台打印机和WiFi密码更新的行政——在我演示两遍后,自己就改出了适配她们物业巡检系统的版本。
整个系统结构极简:运营商基站 → 安卓手机(SIM卡接收短信)→ Automate监听短信内容 → 解析关键词/正则匹配 → 并行触发4路动作:钉钉Webhook POST、飞书Card消息、微信服务号模板消息、SMTP邮件发送
没有中间服务器,不走公网回调,所有逻辑在本地手机运行。你甚至可以把这台手机锁在机柜里,只接电源和4G卡,它就是你的“短信中枢大脑”。接下来,我们就进入真正的实操环节,把这张蓝图变成你手机里可运行的自动化流程。
3. 核心细节解析与实操要点:从短信解析到多平台分发的七道关卡
把一条短信转发出去,听起来像按一个按钮,但实际要闯过七道技术关卡。我把它拆成“收、识、判、转、验、稳、管”七个字,每个字背后都是实测踩过的坑。
3.1 收:短信接收的底层权限与兼容性陷阱
安卓系统从Android 6.0(Marshmallow)起,将短信读取列为“危险权限”,必须在运行时动态申请。但Automate聪明地绕过了这点——它不直接调用READ_SMS,而是监听系统广播android.provider.Telephony.SMS_RECEIVED。这个广播是系统级的,只要APP声明了对应receiver并在AndroidManifest.xml中注册,就能收到,无需用户手动授权。
但这里有个致命兼容性问题:Android 8.0(Oreo)之后,后台应用接收隐式广播被严格限制。如果你的手机系统是8.0+,Automate默认的“SMS Received”触发器会失效。解决方案是:在Automate中新建触发器时,勾选“Use foreground service”(使用前台服务)。这会让Automate在状态栏常驻一个不可关闭的通知(图标是齿轮),从而获得持续接收广播的资格。别嫌它碍眼,这是合规代价——就像你开车必须系安全带,它只是系统强制的“安全带提示”。
提示:测试时务必用真机!模拟器无法接收真实短信,且部分定制ROM(如MIUI、EMUI)会拦截第三方APP的短信广播。我建议首选Pixel系列或一加原生安卓机型,兼容性最稳。
3.2 识:短信内容解析的两种模式与正则实战
短信内容千奇百怪,但转发前必须“读懂”它。Automate提供两种解析模式:
- 关键词匹配(Keyword Match):适合格式固定的短信,比如物联网设备发来的
[TEMP] Room203: 28.5°C。你只需填入[TEMP],流程就会被触发。优点是简单,缺点是容错率低——如果设备偶尔多打个空格变成[TEMP] Room203: 28.5 °C,匹配就失败。 - 正则表达式(Regex):这才是生产环境的标配。比如解析银行验证码短信:“您的验证码是123456,有效期5分钟。” 我们要精准提取
123456。正则写法是:验证码是(\d{6})。括号表示捕获组,\d{6}代表连续6位数字。Automate会把123456存入变量%regex1%,后续所有动作都能调用它。
我整理了高频场景的正则模板,直接可抄:
| 场景 | 短信样例 | 正则表达式 | 提取变量 |
|---|---|---|---|
| 通用告警 | 【智安云】水浸传感器AL-07触发 | 【智安云】(.+) | %regex1%(告警内容) |
| 温湿度 | [TH] T:25.3℃ H:45% | T:(\d+\.\d+)℃\s+H:(\d+)% | %regex1%(温度)、%regex2%(湿度) |
| 验证码 | 验证码:8899,请勿泄露 | 验证码:(\d{4,6}) | %regex1%(验证码) |
注意:正则中的空格、标点必须完全一致。中文括号
【】和英文[]是不同字符,千万别抄错。我曾因把【误写成[,调试了两小时。
3.3 判:多条件分流与防抖机制设计
不是所有短信都要转发。你肯定不想把快递通知、银行余额提醒、甚至垃圾广告都塞进钉钉群。这就需要“判”——条件判断与防抖。
Automate的“IF”模块支持多层嵌套。典型配置是:
- 先判断发件人号码是否在白名单(如
106901234567是你的IoT平台号); - 再判断短信内容是否匹配正则(排除非告警信息);
- 最后加一道时间防抖:用“Variable Set”创建一个时间戳变量
%last_send_time%,每次成功转发后更新;下一次触发时,先用“Variable Calculate”计算当前时间与%last_send_time%的差值,若小于60秒,则Abort Flow(终止流程),避免同一告警重复刷屏。
这个60秒阈值是我实测定的:多数设备告警间隔大于2分钟,设太短会漏报,设太长则失去防抖意义。你也可以根据业务调整,比如家庭安防设为10秒(人闯入是紧急事件),而空调温度上报设为300秒(5分钟才发一次)。
3.4 转:四平台API调用的关键参数与签名逻辑
“转”是核心,也是最容易出错的一环。四平台接口差异极大,必须逐个击破:
钉钉机器人:最简单。在钉钉群右上角“...”→“智能群助手”→“添加机器人”→选择“自定义”,复制Webhook地址。注意:地址末尾带
?sign=xxx,这个sign是时效性签名,每小时会变!很多教程教人直接填死链接,结果第二天就失效。正确做法是:用Automate的“HTTP Request”模块,Method选POST,URL填基础地址(不含?sign),然后在Headers里手动加一行:Timestamp: %timestamp%和Sign: %sign%。其中%timestamp%用“Variable Set”取当前毫秒时间戳,%sign%用“Text Encode”模块对%timestamp%\nxxx(xxx是你的密钥)做HMAC-SHA256 Base64编码——Automate内置了这个编码器,选中即可。飞书机器人:比钉钉略复杂。飞书要求JSON Body必须包含
msg_type: "interactive"和card字段。我封装了一个标准Card模板:标题用%regex1%,正文用%sms_body%(原始短信),底部加一个“查看详情”按钮,链接指向你的内部监控页面。关键点是:card字段必须是合法JSON字符串,所以要用“Text Format”模块把变量拼成JSON,再用“Text Encode”做UTF-8编码,否则飞书返回400 Invalid card。微信服务号模板消息:这是唯一需要后端配合的。因为微信要求模板消息必须由已认证的服务号发起,且需
access_token(2小时过期)。所以我们在Automate里只做两件事:1)用“HTTP Request”调用你自己的轻量API(比如部署在Vercel上的无服务器函数),传入%regex1%等参数;2)该API负责获取access_token、组装模板、调用微信API。这样就把微信的复杂性隔离在外,Automate只管“发指令”。邮箱发送:用“Email Send”模块。SMTP服务器填
smtp.qq.com(QQ邮箱)或smtp.163.com(163邮箱),端口465(SSL)或587(TLS)。用户名填完整邮箱地址(如alert@foxmail.com),密码不是邮箱登录密码,而是SMTP专用密码(QQ邮箱在“设置→账户→POP3/IMAP/SMTP服务”里生成,163邮箱同理)。这是最高频的失败点——90%的人填错密码。
3.5 验:本地化验证与灰度发布策略
上线前必须验证。我绝不推荐直接在生产群发测试消息。我的灰度策略是:
- 第一阶段:所有动作目标设为“自己”——钉钉发给自己单聊,飞书发给自己,微信模板消息推送到自己手机,邮箱发到自己私人邮箱。确认内容、格式、时间戳全部正确。
- 第二阶段:在钉钉/飞书建一个“测试专用群”,只拉自己和一位同事。发一条模拟告警,观察双方是否同时收到,且内容一致。
- 第三阶段:开启“日志记录”。在Automate流程末尾加一个“File Write”模块,把每次触发的
%sms_body%、%timestamp%、%send_result%(发送结果)写入手机/sdcard/AutomateLog.txt。连续运行一周,用文本编辑器打开日志,搜索"failed",看失败率。我的目标是<0.5%。
实操心得:日志文件别存在内部存储,安卓11+对
/sdcard/访问有限制。统一存到/sdcard/Download/目录下,这个路径所有APP都有读写权。
4. 实操过程与核心环节实现:手把手搭建你的短信中枢
现在,我们把前面所有理论,变成你手机里可点击、可运行的步骤。整个过程约15分钟,不需要任何编程基础。我以“将智能电表欠费提醒转发到钉钉和邮箱”为例,全程截图式描述(文字版)。
4.1 准备工作:三件套安装与基础配置
- 安装Automate:去官网(llamalab.com/automate)下载最新APK,或在Google Play搜“Automate”。安装后打开,首次启动会提示“允许显示在其他应用上层”,必须开启,否则无法触发通知。
- 准备一台备用安卓手机:建议用旧手机,系统Android 7.0以上,确保4G信号稳定。插入一张能收短信的SIM卡(推荐用虚拟运营商号段,如170/171,避免主号被骚扰)。
- 配置钉钉机器人:在目标钉钉群,添加自定义机器人,安全设置选“自定义关键词”,填入
[电表](与你短信前缀一致),复制Webhook地址,保存。
注意:不要选“加签”或“IP段限制”,初期调试阶段越开放越好。等稳定后再收紧。
4.2 创建核心流程:从零构建短信捕获链
打开Automate,点击右下角“+”→“Create flowchart”,命名“电表告警转发”。进入画布后,按顺序拖入以下模块:
- Trigger → SMS Received:这是起点。点击它,在“Sender number filter”留空(接收所有号码),“Message content filter”填
[电表](关键词匹配,简单起步)。勾选“Use foreground service”。 - Action → Variable Set:创建变量
%sms_body%,值设为%sms_message%(Automate自动捕获的短信全文)。 - Action → Text Format:用于提取关键信息。比如短信是
[电表] 用户张三欠费125.8元,请及时缴费!,我们想提取金额。在“Format string”填%sms_message%,下方“Regex”填欠费(\d+\.\d+)元,勾选“Capture groups”,生成%regex1%(即125.8)。 - Action → IF:双击打开,Condition填
%regex1% != ""(确保金额提取成功)。True分支继续,False分支加一个“Abort Flow”。 - Action → HTTP Request(钉钉):Method选
POST,URL填钉钉Webhook基础地址(如https://oapi.dingtalk.com/robot/send?access_token=xxx),Headers加两行:Content-Type: application/json和Accept: application/json。Body填:
{ "msgtype": "text", "text": { "content": "🚨电表告警:用户欠费%regex1%元!\n来源:%sms_message%\n时间:%time%" } }- Action → Email Send(邮箱):To填你的邮箱,Subject填
【电表告警】欠费提醒,Body填HTML格式:
<h3>⚠️ 智能电表紧急提醒</h3> <p><strong>用户:</strong>张三</p> <p><strong>欠费金额:</strong>%regex1% 元</p> <p><strong>原始短信:</strong>%sms_message%</p> <p><small>发送时间:%time%</small></p>- Action → File Write:Path填
/sdcard/Download/electric_log.txt,Text填[%time%] 欠费%regex1%元 → 钉钉:%http_status_code%, 邮箱:%email_status%,Mode选Append。
全部连好线后,点击右上角“✓”保存。流程图应呈一条清晰的直线:SMS → Set Var → Regex → IF → DingTalk → Email → Log。
4.3 权限授予与前台服务启动
保存后,Automate会弹出权限请求:
- “显示在其他应用上层”:必须允许(否则无法监听短信);
- “修改系统设置”:允许(用于开启前台服务);
- “读取短信”:不要点允许!因为我们用的是广播监听,不需要此权限。若误点了,去手机设置→应用→Automate→权限→关闭“短信”。
然后,点击流程右上角“▶”运行。第一次运行时,Automate会弹出“前台服务”提示,选择“始终允许”。此时状态栏会出现齿轮图标,表示服务已激活。
4.4 真机测试与参数微调
现在,用另一部手机,向这台备用机发送一条测试短信:[电表] 用户张三欠费88.5元,请及时缴费!
3秒内,你应该看到:
- 钉钉单聊收到消息;
- 你的邮箱收到HTML邮件;
/sdcard/Download/electric_log.txt末尾新增一行日志;- 状态栏齿轮图标持续亮着。
如果某一项失败,看日志里的%http_status_code%或%email_status%:
400:钉钉Webhook地址错或JSON格式错,检查Body里的引号是否为英文;403:钉钉签名过期,重新生成Webhook;Failed(邮箱):检查SMTP密码是否为专用密码,端口是否选465。
微调建议:
- 把
欠费(\d+\.\d+)元改成欠费([\d.]+)元,兼容欠费125元(无小数); - 在钉钉Body里加
"at": {"atMobiles": ["138****1234"], "isAtAll": false},让特定人收到@提醒; - 邮箱Body里加
<img src="cid:logo">和“File Attach”模块,附上电表实时截图(需额外配置截图工具)。
5. 常见问题与排查技巧实录:那些官方文档不会写的真相
这套方案跑了两年,服务过27个不同场景(从工厂PLC报警到宠物喂食器提醒),我整理了一份“血泪问题清单”,全是官方文档闭口不谈、但你一定会撞上的坑。
5.1 短信收不到?先查这五个隐藏开关
| 问题现象 | 真实原因 | 排查步骤 | 解决方案 |
|---|---|---|---|
| 流程完全不触发 | 手机开启了“短信过滤”或“骚扰拦截” | 进入短信APP→右上角“...”→“垃圾短信设置”→关闭所有过滤规则 | 将Automate加入白名单,或直接关闭过滤 |
| 只收部分短信 | 运营商“二次确认”拦截 | 发送方号码是否为106开头?这类号段常被标记为营销号 | 在短信APP设置里,找到“拦截记录”,把106号段放行 |
| Android 12+收不到 | 系统限制后台广播 | 设置→电池→优化电池使用→找到Automate→选“不优化” | 否则系统会在30秒后杀掉后台进程 |
| 多次发送同一短信 | SIM卡未启用“短信中心号码” | 拨号盘输入*#*#4636#*#*→“手机信息”→看“SMSC”是否为空 | 联系运营商客服,获取并设置短信中心号(如移动:+8613800100500) |
| 流程触发但无动作 | Automate被系统“休眠” | 设置→应用→Automate→电池→“后台活动”是否为“允许” | 关闭“智能省电”或“应用冻结”功能 |
提示:华为/荣耀手机特别爱“优化”第三方APP。我的固定操作是:设置→应用和服务→应用启动管理→找到Automate→手动关闭“自动管理”,再打开“手动管理”,把“允许后台活动”“允许自启动”“允许关联启动”全部打钩。
5.2 四平台发送失败的独家诊断表
我们把失败日志归为三类:网络层、协议层、业务层。对应排查工具如下:
| 平台 | 典型错误码 | 网络层诊断 | 协议层诊断 | 业务层诊断 |
|---|---|---|---|---|
| 钉钉 | 400 | 用手机浏览器访问Webhook地址,看是否返回{"errcode":310000,"errmsg":"invalid signature"} | 用Postman重放请求,对比Header里的Timestamp和Sign是否与钉钉文档一致 | 检查关键词是否在机器人安全设置里,且短信内容是否含该关键词 |
| 飞书 | 400 Invalid card | curl -I Webhook地址,看HTTP状态码是否200 | 把Body JSON粘贴到jsonlint.com验证格式 | 飞书机器人是否被禁用?在飞书管理后台→机器人管理里确认状态 |
| 微信 | 40001 invalid credential | ping api.weixin.qq.com,看是否通 | 检查access_token是否过期(2小时),是否用了旧token | 服务号是否通过微信认证?模板ID是否在后台已审核通过? |
| 邮箱 | 535 Authentication failed | telnet smtp.qq.com 465,看是否连接成功 | 检查SMTP密码是否为16位随机字符串(QQ邮箱专用密码格式) | QQ邮箱是否开启“POP3/IMAP/SMTP服务”?在邮箱网页版设置里确认 |
实操心得:我写了一个“一键诊断”流程,放在Automate里。它会自动执行:1)ping钉钉域名;2)curl飞书Webhook;3)telnet QQ邮箱;4)读取最近一条日志。运行后直接告诉你哪一环断了,比翻日志快10倍。
5.3 稳定性加固:让手机7×24小时不掉线的六个硬招
把手机当服务器用,最大的敌人是“意外重启”。我总结出六招,让备用机真正成为“永不下班的哨兵”:
- 物理防误触:用胶带把音量键和电源键贴死,防止口袋里误按关机;
- 充电策略:用USB-C PD快充头(30W以上),搭配带指示灯的排插。当手机电量低于20%时,Automate自动发邮件提醒你“电表中枢电量不足”;
- 温度控制:手机别放机柜死角。我在机柜侧面钻孔,加装一个USB小风扇(5V供电),对着手机背部吹风。实测夏天机柜内60℃,手机表面温度从48℃降到36℃,崩溃率下降90%;
- 内存守护:用“Task Killer”类APP(如Greenify)定期冻结非必要APP,但绝对不要冻结Automate;
- 网络保活:在Automate里加一个“Timer”触发器,每10分钟执行一次“HTTP Request”到
http://www.baidu.com,保持4G连接活跃; - 双机热备:准备第二台同型号手机,流程完全一样。用“File Sync”模块,每小时把
/sdcard/Download/electric_log.txt同步到NAS。主机关机时,备用机自动接管。
最后分享一个真实案例:某社区养老中心用这套方案监控老人跌倒报警器。最初用单机,某天凌晨手机过热重启,错过一次告警。后来上了双机+温度监控,至今23个月零漏报。他们管理员说:“现在我不怕手机坏,就怕它太好——好到让我忘了它还在替我值班。”
6. 扩展可能性与场景迁移:从短信到万物通知的思维跃迁
这套方案的价值,远不止于“转发短信”。它的底层逻辑是:把任意能产生文本输出的设备,变成你的通知中枢。只要稍作改造,就能迁移到十几个新场景。
6.1 硬件扩展:让老设备焕发新生
- 串口设备接入:很多工业传感器只有RS232/485接口,没有网络。买一个USB转串口模块(CH340芯片),接在树莓派上,用Python脚本读取串口数据,再用
curl调用Automate的HTTP API(Automate支持接收HTTP请求作为触发器),把串口数据变成“短信”转发出去。我帮一家印刷厂把温控仪数据接入了钉钉,成本不到200元。 - GPIO告警直连:树莓派的GPIO引脚检测到高电平(比如烟雾报警器触发),直接执行
echo "ALERT" > /dev/ttyS0,再让Automate监听这个串口文件,完美替代短信。 - USB摄像头抓拍:用Motion软件监控USB摄像头,一旦检测到移动,自动截图并调用Automate,把图片URL作为附件发到飞书Card里。老人在家摔倒,家属手机立刻弹出带时间戳的现场图。
6.2 软件集成:打通你已有的数字资产
- 与Home Assistant联动:HA的
notify服务支持多种通知渠道,但缺乏短信兜底。我们在HA里配置一个rest_command,指向Automate的HTTP API,当HA检测到门窗开启,就发一条[HA] 前门开启短信到备用机,再由Automate分发到各平台。 - 与Zabbix告警整合:Zabbix的Media Type支持“Script”,我们写一个Shell脚本,用
adb shell input keyevent KEYCODE_HOME唤醒备用机屏幕,再用adb shell am start -n com.llamalab.automate/.flow.FlowActivity --es "flow_id" "zabbix_alert"直接启动指定流程。Zabbix告警秒级触达。 - 与微信小程序对接:小程序后端生成告警,不调用微信模板消息,而是调用你的轻量API,API再调用Automate的HTTP API。这样所有通知出口统一,便于审计和修改。
6.3 思维升级:从“通知”到“闭环行动”
真正的高手,已经不满足于“收到通知”,而是追求“通知即行动”。我在Automate里加了一个终极模块:
- 当收到
[UPS] 电池剩余15%短信时,除了转发,还自动执行:adb shell input keyevent KEYCODE_POWER—— 锁屏省电;adb shell settings put global stay_on_while_plugged_in 1—— 插电时永不休眠;adb shell am start -a android.intent.action.VIEW -d "https://xxx.com/ups-status"—— 自动打开UPS监控页面。
一条短信,触发三步操作,把“被动接收”变成了“主动防御”。这不再是教程,而是你数字生活的操作系统。
我最后一次调试是在上个月,把家里的智能花盆土壤湿度告警,接入了这套系统。当手机弹出“🌱 花盆缺水!当前湿度12%”时,我正在地铁上。钉钉群里的浇水机器人已经待命,飞书卡片里有浇水视频教程,邮箱里躺着本周的植物养护周报。我没有做任何事,但一切已在发生。这大概就是技术该有的样子:不喧哗,自有声。