sendmsg/README.md
2026-06-08 03:52:55 -07:00

317 lines
9.6 KiB
Markdown

# sendmsg
**Universal message sender for Signal and SMS/iMessage.**
`sendmsg` is a command-line tool for sending messages via the [Signal REST API](https://github.com/bbernhard/signal-cli-rest-api) or locally via macOS [Messages](https://apps.apple.com/app/messages/id1092291483) (iMessage/SMS) through the [`imsg`](https://github.com/DocWho76/imsg) CLI.
It supports individual direct messages, Signal group broadcasts, file attachments, and bulk sending from CSV files — all with a single, consistent interface.
---
## Table of Contents
- [Architecture](#architecture)
- [Dependencies](#dependencies)
- [Installation](#installation)
- [Usage](#usage)
- [Signal Messages](#signal-messages)
- [SMS / iMessage](#sms--imessage)
- [Bulk Send from CSV](#bulk-send-from-csv)
- [Management Commands](#management-commands)
- [CSV Format](#csv-format)
- [Configuration](#configuration)
- [Examples](#examples)
---
## Architecture
```
┌─────────────────────────────────────────────────────────┐
│ sendmsg (CLI) │
│ Python 3 script with argparse-based argument parsing │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ --signal │ │ --sms │ │
│ │ │ │ │ │
│ │ POST to │ │ Call `imsg send` CLI │ │
│ │ Signal REST │ │ │ │
│ │ API │ │ │ │
│ └──────┬───────┘ └────────────┬─────────────┘ │
│ │ │ │
│ ▼ │ │
│ (Docker) ▼ │
│ ┌───────────────────────┐ ┌─────────────────────┐ │
│ │ signal-cli-rest-api │ │ │ │
│ │ http://localhost:8080 │ │ macOS Messages │ │
│ │ (or SIGNAL_REST_URL) │ │ │ │
│ └───────────────────────┘ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
```
**Signal path:** `sendmsg` → HTTP POST → `signal-cli-rest-api` → Docker container → Signal network.
**SMS/iMessage path:** `sendmsg` → subprocess call → `imsg` CLI → macOS Messages framework → carrier/Apple.
---
## Dependencies
### Required
| Dependency | Version | Purpose |
|---|---|---|
| Python 3 | 3.9+ | Script runtime |
| macOS 12+ | Monterey or later | Required for iMessage/SMS support |
### Signal (optional — only needed for `--signal`)
| Dependency | Version | Purpose |
|---|---|---|
| Docker | 24+ (Colima on Apple Silicon) | Container runtime |
| `signal-cli-rest-api` | latest | Signal REST API server |
| `signal-cli` (via container) | latest | Signal protocol implementation |
### SMS/iMessage (optional — only needed for `--sms`)
| Dependency | Version | Purpose |
|---|---|---|
| `imsg` CLI | latest | macOS Messages / SMS bridge |
### System
- **macOS** — The script is designed for macOS; SMS/iMessage uses the native Messages app.
- **Network access** — Required to reach the Signal REST API endpoint.
---
## Installation
1. **Place the script:**
```bash
cp sendmsg /usr/local/bin/sendmsg
chmod +x /usr/local/bin/sendmsg
```
2. **Ensure dependencies are installed:**
**For Signal:**
```bash
# Verify signal-cli-rest-api is running
curl -s http://localhost:8080/v1/accounts | python3 -m json.tool
```
**For SMS/iMessage:**
```bash
# Verify imsg is installed and available
imsg send --help
```
3. **Test the script:**
```bash
sendmsg --help
```
---
## Usage
```
sendmsg [OPTIONS]
Messaging methods (choose one):
--signal Send via Signal
--sms Send via SMS/iMessage (macOS Messages)
--csv FILE Bulk send from a CSV file
Management commands (choose one):
--list-signal List linked Signal accounts
--link-signal Link a new device to your Signal account
```
### Signal Messages
```bash
# Send a text message
sendmsg --signal --to +18885551212 --text "Hello from Signal!"
# Send to a group
sendmsg --signal --recipients group.TestGroupHash --text "Hello everyone!"
# Send with an attachment
sendmsg --signal --to +18885551212 --text "Check this out" --attach ~/photo.jpg
# Send multiple messages (concatenated with newlines)
sendmsg --signal --to +18885551212 --text "Line 1" --text "Line 2"
```
### SMS / iMessage
```bash
# Send via iMessage (auto-detected)
sendmsg --sms --to +18885551212 --text "Hello via iMessage!"
# Force SMS service
sendmsg --sms --to +18885551212 --text "Hello via SMS!" --service sms
# Send with an attachment
sendmsg --sms --to +18885551212 --text "Photo attached" --file ~/photo.jpg
```
### Bulk Send from CSV
```bash
sendmsg --csv messages.csv # Send all rows
sendmsg --csv messages.csv --delay 2 # Wait 2 seconds between sends
```
### Management Commands
```bash
# List linked Signal accounts
sendmsg --list-signal
# Link a new device
sendmsg --link-signal
sendmsg --link-signal --name "my-laptop"
```
---
## CSV Format
Create a CSV file with the following columns:
| Column | Required | Description |
|---|---|---|
| `method` | Yes | `signal` or `sms` |
| `recipient` | Yes | Phone number, group ID (for Signal), or empty for group sends |
| `name` | No | Display name shown during status output (e.g., "Alice", "Marketing Group") |
| `message` | Yes | The message text to send |
| `account` | No | Signal account phone number (defaults to `+156****1603` or `$SIGNAL_ACCOUNT`) |
| `service` | No | SMS service: `imessage`, `sms`, or `auto` (SMS only) |
| `file` | No | Path to an attachment file (relative or absolute) |
| `delay` | No | Seconds to wait after this row is sent (e.g., `3`) |
### Example CSV
```csv
method,recipient,name,message,account,service,file,delay
signal,+156****1603,Alice,Hello via Signal,+156****1603,,,
signal,group.ZzBHd3NZO...,Team Alert,,,,-1
sms,+123****7890,Bob,SMS test,,,~/pic.jpg,
signal,+156****1603,Carol,With delay,,,-3
```
### Status Output
During a bulk send, each row prints its name (if provided):
```
[1/4] SIGNAL → Alice (+156****1603)
[2/4] SIGNAL → Team Alert (group.ZzBHd3NZO...)
[3/4] SMS → Bob (+123****7890)
[4/4] SIGNAL → Carol (+156****1603)
```
If no `name` is provided, the recipient is shown instead.
---
## Configuration
### Load settings from sendmsg config file in ~/.sendmsg.conf, with env var fallback.
Config file format (INI-style):
[settings]
signal_rest_url = http://localhost:8080
signal_default_account = +1234567890
### Environment Variables
| Variable | Default | Description |
|---|---|---|
| `SIGNAL_REST_URL` | `http://localhost:8080` | URL of the Signal REST API server |
| `SIGNAL_ACCOUNT` | `+1234567890` | Default Signal account phone number |
### Override Example
```bash
export SIGNAL_REST_URL=http://localhost:8082
export SIGNAL_ACCOUNT=+18885551212
sendmsg --csv messages.csv
```
---
## Examples
### Daily Broadcast
```csv
method,recipient,name,message,account,service,file,delay
signal,group.ZzBHd3NZO...,Daily Update,Good morning team! Here's your daily briefing.,+18002222222,,,
```
### Personalized Outreach
```csv
method,recipient,name,message,account,service,file,delay
signal,+18885551111,John,Hi John, hope you're doing well!
sms,+18885552222,Jane,Hey Jane, just checking in!
signal,+18885553333,Alex,Alex, don't forget about the meeting tomorrow at 3pm!
```
### With Attachments
```csv
method,recipient,name,message,account,service,file,delay
signal,+18885551111,John,Here's the report you asked for,+18002222222,,,~/Downloads/report.pdf
sms,+18885552222,Jane,Photo from the event,,,~/Photos/event.jpg,
```
### With Delays
```csv
method,recipient,name,message,account,service,file,delay
signal,+18885551111,Alice,First message,,,
signal,+18885552222,Bob,Second message,,,3
signal,+18885553333,Charlie,Third message,,,
```
---
## Error Handling
- **Unknown method:** Rows with invalid `method` values are skipped and reported in the summary.
- **Empty message:** Rows without a `message` are skipped and reported.
- **Failed sends:** Failed attempts are counted and listed in the summary.
- **Exit codes:** The script exits with `1` if any rows fail, `0` on full success.
---
## Summary Output
After processing all rows, a summary is printed:
```
==================================================
📊 CSV Send Summary
==================================================
Total rows: 4
✅ Success: 3
❌ Failed: 1
Errors:
• Row 2: failed to send
==================================================
```
---
*For support or issues, see https://xkcd.com/627/*