Building a Local SMS Bridge: Syncing Samsung Messages Without Twilio
During a recent development session, I tackled a problem that many engineers encounter when building communication tools: how to read and aggregate SMS data from a local device without relying entirely on cloud-based SMS providers. This post walks through the architecture, decisions, and implementation of samsung_sms_sync.py — a tool designed to bridge Samsung/Android SMS with existing infrastructure.
The Problem Statement
The initial assumption was that all SMS functionality required Twilio credentials. However, during this session, we discovered that a local JADA business line (6199867344) could serve as a data source without external API dependencies. The goal: read SMS messages locally, process them, and generate digests for team members.
This created an interesting architectural challenge: how do you reliably extract SMS data from an Android device and integrate it into an existing Python-based infrastructure without adding third-party dependencies or requiring constant API authentication?
Solution Architecture
Local-First Data Collection
Rather than polling Twilio endpoints, the solution leverages the Android Debug Bridge (ADB) to directly access the device's SMS database. This approach offered several advantages:
- No external API calls: Eliminates Twilio credential management and reduces attack surface
- Real-time access: Direct database queries mean fresher data than API-based polling
- Cost efficiency: No per-message SMS provider fees
- Privacy: Messages stay on-device or in your own infrastructure
The tradeoff is platform specificity — this works for Android devices with ADB enabled, not for Twilio's abstracted carrier integration.
Technical Implementation
File Structure
Two primary artifacts were created in this session:
/Users/cb/Documents/repos/tools/samsung_sms_sync.py— Core sync logic/Users/cb/Library/LaunchAgents/com.cb.samsung-sms-sync.plist— macOS daemon configuration
Samsung SMS Sync Script
The samsung_sms_sync.py script performs these core functions:
- ADB device detection: Verifies Android device connectivity via
adb devices - SMS database queries: Executes SQLite queries against the Android SMS database (typically at
/data/data/com.android.providers.telephony/databases/mmssms.db) - Message parsing: Extracts sender, recipient, timestamp, and body from raw database records
- Digest generation: Aggregates messages by contact and time window
- Email delivery: Sends digests via AWS SES to configured recipients
Key function signature pattern:
def query_sms_database(device_id: str, query: str) -> List[Dict]:
"""Execute SQLite query on Android SMS database via ADB"""
cmd = f"adb -s {device_id} shell sqlite3 /data/data/com.android.providers.telephony/databases/mmssms.db"
# Execute query, parse output, return structured data
This pattern allows filtering by date range (essential for digest generation) and contact number without pulling the entire database.
macOS LaunchAgent Configuration
The plist file at com.cb.samsung-sms-sync.plist configures background execution:
<key>Label</key>
<string>com.cb.samsung-sms-sync</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/python3</string>
<string>/Users/cb/Documents/repos/tools/samsung_sms_sync.py</string>
</array>
<key>StartInterval</key>
<integer>3600</integer>
</array>
The StartInterval key runs the sync every 3600 seconds (1 hour), balancing freshness with resource consumption. This replaces cron-based approaches with native macOS process management.
Integration Points
AWS SES Email Delivery
Digests are sent via AWS Simple Email Service rather than local mail, providing:
- Reliable delivery logging
- SPF/DKIM configuration for domain reputation
- Attachment support for formatted digests
The script constructs email payloads with:
- Recipient extracted from configuration
- Subject line identifying the contact and date range
- HTML-formatted message list with timestamps and sender context
Credential Management
AWS credentials are sourced from ~/.aws/credentials (IAM role-based) rather than hardcoded in the script. The SES send operation requires an IAM principal with ses:SendEmail permission on the configured sender address.
Key Implementation Decisions
Why ADB Instead of Twilio?
This session revealed that for internal operations (reading your own business line), local access is superior because:
- Availability: Works offline; no API rate limits or service degradation
- Debugging: Direct database inspection vs. API response parsing
- Compliance: Messages never leave the device unless explicitly exported
Twilio remains valuable for outbound SMS to arbitrary numbers, but inbound reading of your own device doesn't require it.
Digest-as-Email Over Push Notifications
Rather than real-time SMS notifications, the tool batches messages into hourly digests. This was a deliberate choice to:
- Reduce notification fatigue
- Provide context (all messages from a contact in one email)
- Allow offline review of the digest email
Time-Window Filtering
The script accepts a date range parameter (e.g., "April 25-29") to extract relevant conversations. This pattern proved essential when reviewing specific operational periods without manual message scrolling.
Deployment Steps
- Install ADB:
brew install android-platform-tools - Enable USB debugging: On Samsung device, Settings > Developer Options > USB Debugging
- Verify ADB connection:
adb devices - Place script: Copy to
/Users/cb/Documents/repos/tools/samsung_sms_sync.py - Install LaunchAgent: Copy plist to
~/Library/LaunchAgents/and runlaunchctl load com.cb.samsung-sms-sync.plist