- ✅ Local server is running and can forward a test payload to Telegram.
- ✅ Server logs to SQLite + deduplicates incoming messages (prevents double-forwards on retries).
- ✅ Android app has Login/Signup UI and uses Bearer token auth.
- ⏭️ Next milestone: polish UX + add a simple "view logs" admin page (optional).
- v0 goal: forward incoming SMS (Android device / emulator) to Telegram.
- Server runs locally on your PC on the same Wi‑Fi (no tunneling).
- Message format: clean
From / Time / Body(optionally Markdown)
server/— Python FastAPI webhook serverapp/— Android app (Jetpack Compose)
- Active UI entry:
app/src/main/java/com/example/myapplication/MainActivity.kt - Active navigation:
app/src/main/java/com/example/myapplication/ui/app/AppNav.kt - Active screens:
app/src/main/java/com/example/myapplication/ui/screens/ - If you change UI, edit files in
ui/screens(not old files underui/).
- Open Telegram → search @BotFather
- Send:
/newbot - Follow prompts (name + username)
- Copy the token it gives you →
TELEGRAM_BOT_TOKEN
- Open your bot chat and send:
hi - In a browser, open:
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates - Look for:
result[0].message.chat.id - Copy that number →
TELEGRAM_CHAT_ID
- Add the bot into the group.
- Send a message in the group (e.g.
hi). - Open
getUpdatesagain and find the group chat id (often a negative number).
Recommended: Python 3.11 / 3.12 (best wheel support on Windows).
Check your Python:
python --versionFrom the server/ directory:
cd path\to\Message_reply\server
python -m venv .venv
.\.venv\Scripts\Activate.ps1python -m pip install --upgrade pip
python -m pip install -r requirements.txtCopy .env.example to .env and fill values:
copy .env.example .env
notepad .envRequired keys:
SMS_BRIDGE_SECRETTELEGRAM_BOT_TOKENTELEGRAM_CHAT_ID
Optional:
TELEGRAM_FORMAT=plainormarkdown
Bearer token auth for /sms/incoming:
- Android logs in/signs up via
/auth/loginor/auth/signup - Server returns a token
- Android sends:
Authorization: Bearer <token>
Enable in server/.env:
AUTH_REQUIRED=true
ALLOW_SECRET_AUTH=falseYou can optionally allow the old secret/HMAC method only as a fallback when no Bearer token is present:
ALLOW_SECRET_AUTH=trueSecret/HMAC methods:
- Legacy secret (JSON field)
- Android sends:
{"secret": "..."}in the JSON body - Server validates it against
SMS_BRIDGE_SECRET
- HMAC headers (integrity + replay protection) Android sends headers:
X-Timestamp: <unix seconds>X-Signature: <hex(hmac_sha256(SMS_BRIDGE_SECRET, "<timestamp>.<raw_json_body>"))>
Server verifies:
- timestamp is within
HMAC_WINDOW_SECONDS(default: 120s) - signature matches (constant-time compare)
Enforce HMAC-only (for secret mode):
ALLOW_LEGACY_SECRET=falseAndroid uses WorkManager to queue SMS forwarding and retry with exponential backoff when the server/Telegram is temporarily unavailable. This can introduce a small delay after the server comes back online (expected).
SMS_BRIDGE_SECRETTELEGRAM_BOT_TOKENTELEGRAM_CHAT_IDTELEGRAM_FORMAT=plain|markdownHMAC_WINDOW_SECONDS=120ALLOW_LEGACY_SECRET=true|false
python -m uvicorn main:app --host 0.0.0.0 --port 3000Health check (on the PC):
http://127.0.0.1:3000/health
PowerShell:
$signup = @{
username = "billy"
email = "billy@example.com"
password = "change-me"
} | ConvertTo-Json
$r = Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:3000/auth/signup" -ContentType "application/json" -Body $signup
$token = $r.token
$token$body = @{
from = "+8613800138000"
body = "Test"
receivedAt = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ssK")
} | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:3000/sms/incoming" -ContentType "application/json" -Headers @{ Authorization = "Bearer $token" } -Body $bodyExpected Telegram message format:
Time: <timestamp>
From: <phone number>
Text: <sms body>
Phone: <phone number>
- Find your PC’s LAN IP:
ipconfigLook for IPv4 like 192.168.1.50.
-
Open Windows Firewall for TCP port
3000. -
From Android browser, test:
http://<PC_IP>:3000/health
If it fails:
- PC not listening on 0.0.0.0 (must use the uvicorn command above)
- Windows firewall blocking
- Router “AP isolation” enabled
- Build Android receiver app (or emulator) to capture SMS and POST JSON to:
http://<PC_IP>:3000/sms/incoming
- Add minimal settings on Android:
- Server URL
- Secret