虽然现在已经有不少工具能实现接收短信并转发至 Telegram, 但总感觉差点意思。毕竟别人写的东西再怎么万能, 也不如自己写的顺手。很多奇思妙想, 只有自己亲手造轮子才能实现。
网上常见的 Python 示例其实并不算完整
- 只会监听新短信, 在脚本启动前收到的短信它不会去处理
- 对于分段短信 (长短信被拆成几条的那种), 它不会自动拼接, 还会乱序打印
所以, 干脆自己写一个: 既能支持多分段短信, 也能读取历史短信, 并在第一时间转发到 Telegram
安装依赖
不要使用 python-gsmmodem, 它已经不再维护。使用新的 python-gsmmodem-new
pip install python-gsmmodem-new
pip install python-telegram-bot
Python 文件部分
收到短信后会自动转发至 Telegram
文件名: python-gsmmodem-advanced-read.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from datetime import datetime
from gsmmodem.modem import GsmModem, Sms
from gsmmodem.pdu import Concatenation
from telegram import Bot
# ========== 配置区 ==========
PORT = '/dev/ttyUSB0'
BAUDRATE = 115200
PIN = None # SIM 卡 PIN (如果有的话)
# Telegram Bot 配置
TELEGRAM_BOT_TOKEN = '你的 BotToken'
TELEGRAM_CHAT_ID = '你的 ChatID' # 可以是个人 ID 或群 ID
# SOCKS5 代理配置
request_kwargs = {
'proxy_url': 'socks5://127.0.0.1:1080', # 代理地址
'urllib3_proxy_kwargs': {
# 如果代理需要用户名密码, 填写这两个
# 'username': 'proxyuser',
# 'password': 'proxypass',
}
}
# ============================
concat_sms = {}
bot = Bot(token=TELEGRAM_BOT_TOKEN, request_kwargs=request_kwargs)
# 转发消息到 Telegram
def send_to_telegram(text: str):
try:
bot.send_message(chat_id=TELEGRAM_CHAT_ID, text=text)
print("Forwarded to Telegram")
except Exception as e:
print(f"Telegram send failed: {e}")
# 处理单条短信, 包括长短信拼接
def handleSms(sms: Sms):
concat = None
message = None
# 检查是否是长短信的一部分
if sms.udh:
for i in sms.udh:
if isinstance(i, Concatenation):
concat = i
break
if concat:
ref = concat.reference
if ref not in concat_sms:
concat_sms[ref] = {}
concat_sms[ref][concat.number] = sms.text
print(u'== Partial message received ==\n[{0}/{1}] ref={2}\n'.format(
len(concat_sms[ref]), concat.parts, ref))
# 如果所有分段都收齐了 → 拼接
if len(concat_sms[ref]) == concat.parts:
sortedParts = [concat_sms[ref][i] for i in sorted(concat_sms[ref])]
message = "".join(sortedParts)
del concat_sms[ref]
else:
message = sms.text
if message:
out = (u'== SMS message received ==\nFrom: {0}\nTime: {1}\nMessage:\n{2}\n'
.format(sms.number, sms.time, message))
print(out)
# 转发到 Telegram
tg_text = f"📩 新短信\n\n来自: {sms.number}\n时间: {sms.time}\n\n{message}"
send_to_telegram(tg_text)
# 可选: 保存到文件
# date = datetime.today().strftime('%Y%m%d%H%M%S%f')
# with open(f'/path/to/messages/{date}.txt', 'w') as f:
# f.write(out)
def main():
print('Initializing modem...')
modem = GsmModem(PORT, BAUDRATE, smsReceivedCallbackFunc=handleSms)
modem.smsTextMode = False
modem.connect(PIN)
# 启动时读取并删除存量短信
modem.processStoredSms(delete=True)
print('Waiting for new SMS message...')
try:
# 无限等待, 但能响应 Ctrl+C
modem.rxThread.join(2**31)
except KeyboardInterrupt:
print("\nProgram terminated by user (Ctrl+C)")
finally:
print("Closing modem...")
modem.close()
if __name__ == '__main__':
main()
启动监听
运行以下命令
$> python3.6 python-gsmmodem-advanced-read.py
Initializing modem...
Waiting for new SMS message...
保持此进程在后台运行即可, 例如使用 screen
原文
接收短信并转发至 Telegram
Read long SMS with python-gsmmodem (and send SMS with same running script)