Add support for fromName, update README
All checks were successful
/ test (push) Successful in 5s

This commit is contained in:
phil 2024-12-03 18:32:59 +01:00
parent 6d8743e183
commit f6d0916dec
4 changed files with 69 additions and 19 deletions

View file

@ -1,12 +1,12 @@
# About sms-handler # About sms-handler
[sms-handler](https://philo.ydns.eu/code/Philome/sms-handler) is a simple companion service of the [sms-handler](https://philo.ydns.eu/code/Philome/sms-handler) is a simple companion service of the
[SMS Forward](https://gitlab.com/pierreduchemin/smsforward) app to send notification mails on reception of SMSes. *SMS to URL Forwarder* app available on [F-Droid](https://f-droid.org/en/packages/tech.bogomolov.incomingsmsgateway/),
to send notification mails on reception of SMSes.
Main audience: people who run a server on the public internet, configured with an email server Main audience: people who run a server on the public internet, configured with an email server
or configured as a relay. or configured as a relay.
## Installation ## Installation
```sh ```sh
@ -20,6 +20,12 @@ sudo apt install -y pipx
PIP_EXTRA_INDEX_URL=https://pypi.org/simple/ pipx install --index-url https://philo.ydns.eu/code/api/packages/Philome/pypi/simple/ sms-handler PIP_EXTRA_INDEX_URL=https://pypi.org/simple/ pipx install --index-url https://philo.ydns.eu/code/api/packages/Philome/pypi/simple/ sms-handler
``` ```
*sms-handler* can be run with any unprivileged user.
However due to standard security schemes, opening a port in the range 1-1024
is allowed to privileged users only (such as *root*).
Use `sudo` to install as root if *sms-handler* is to be configured
with a reserved port.
## Configuration ## Configuration
Configuration is done by environment variables, prefixed by `SMS_HANDLER_`: Configuration is done by environment variables, prefixed by `SMS_HANDLER_`:
@ -29,12 +35,26 @@ Configuration is done by environment variables, prefixed by `SMS_HANDLER_`:
* `SMS_HANDLER_MAIL_SERVER`: address of the mail server (default: localhost) * `SMS_HANDLER_MAIL_SERVER`: address of the mail server (default: localhost)
* `SMS_HANDLER_MAIL_SERVER_PORT`: port of the mail server (default: 25) * `SMS_HANDLER_MAIL_SERVER_PORT`: port of the mail server (default: 25)
* `SMS_HANDLER_MAIL_SERVER_START_TLS`: initiate mail server connection with TLS (default: no) * `SMS_HANDLER_MAIL_SERVER_START_TLS`: initiate mail server connection with TLS (default: no)
* `SMS_HANDLER_MAIL_TEMLATE`: used to format the body of the mails * `SMS_HANDLER_MAIL_TEMPLATE`: used to format the body of the mails
* `SMS_HANDLER_MAIL_ENABLE`: no or false to disable mails (default: yes) * `SMS_HANDLER_MAIL_ENABLE`: no or false to disable mails (default: yes)
The default settings work with a mail server runs on the localhost, The default settings work with a mail server runs on the localhost,
and mails are sent to the user that owns the process. and mails are sent to the user that owns the process.
The `SMS_HANDLER_MAIL_TEMPLATE` variable is used with Python `str.format()`.
The field names are the same as the default JSON setting in the *SMS to URL Forwarder* app.
The default setting formats emails as below:
```text
{text}
---
From: {from} {fromName}
Sent: {sentStamp:%c}
Received: {receivedStamp:%c}
Sim: {sim}
```
### SMS handler app configuration ### SMS handler app configuration
Set the *Webhook URL* with as `https://your.server.name:8025/sms-handle`. Set the *Webhook URL* with as `https://your.server.name:8025/sms-handle`.
@ -78,19 +98,24 @@ WantedBy=default.target
## Run behind a reverse proxy ## Run behind a reverse proxy
*sms-handler* can run behind a reverse proxy (Nginx, Apache, etc) *sms-handler* can run behind a reverse proxy (Nginx, Apache, Lighttpd, HAProxy, Caddy, Traefik, etc),
for HTTPs support. The URI (configured in the *SMS Forward* app) can be prefixed eg. for HTTPs support. The URI (configured in the *SMS to URL Forwarder* app) can be prefixed
to dispatch different applications on the same server. to dispatch different applications on the same server.
Example for [Caddy](https://caddyserver.com/): [Caddy](https://caddyserver.com/) is suggested as it is straightforward to set up, with this Caddyfile extract:
```caddyfile ```text
handle /sms-handler/* { my.example.com {
handle /sms-handler/* {
uri strip_prefix /sms-handler uri strip_prefix /sms-handler
reverse_proxy 192.168.100.2:8025 reverse_proxy 127.0.0.1:8025
}
} }
``` ```
Replace the public host name `my.example.com` and
the destination IP:port `127.0.0.1:8025` for your setup.
## Development and test ## Development and test
*sms-handler* is packaged with [uv](https://docs.astral.sh/uv/). *sms-handler* is packaged with [uv](https://docs.astral.sh/uv/).
@ -106,17 +131,24 @@ uv sync
pytest -s tests/basic.py pytest -s tests/basic.py
``` ```
The *sms-handler* source has a CI test workflow for [Forgejo](https://forgejo.org/). The *sms-handler* source includes a CI test workflow for [Forgejo](https://forgejo.org/).
## Compatibility
*sms-handler* is also compatible with
[this fork of *SMS to URL Forwarder*](>https://github.com/scottmconway/android_income_sms_gateway_webhook)
which includes also the sender's name.
## Alternatives ## Alternatives
For a more flexible way to use *SMS Forward* For a more flexible way to use a tool like *SMS to URL Forwarder*,
(available on [FDroid](https://f-droid.org/packages/com.pierreduchemin.smsforward/)), a pub/sub service like [ntfy](https://ntfy.sh/) should be considered.
use the [ntfy](https://ntfy.sh/) pub/sub service. It makes it easy It makes it easy to integrate with other components
to integrate with other tools, for notification on various devices and automation. for notification on various devices and automation.
## License, etc ## License, etc
*sms-handler* is BSD licensed. Suggestions and contributions are welcome. *sms-handler* is BSD licensed. Suggestions and contributions are welcome.
<a href="https://liberapay.com/Philo/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a> <a href="https://liberapay.com/Philo/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>

View file

@ -1,6 +1,6 @@
[project] [project]
name = "sms_handler" name = "sms_handler"
version = "0.0.2" version = "0.0.4"
#dynamic = ["version"] #dynamic = ["version"]
description = "Listen to messages from the SMS Forwarder app on Android and send mail" description = "Listen to messages from the SMS Forwarder app on Android and send mail"
readme = "README.md" readme = "README.md"

View file

@ -31,7 +31,7 @@ class MailSettings(BaseSettings):
"""\ """\
{text} {text}
--- ---
From: {from} From: {from} {fromName}
Sent: {sentStamp:%c} Sent: {sentStamp:%c}
Received: {receivedStamp:%c} Received: {receivedStamp:%c}
Sim: {sim} Sim: {sim}
@ -45,7 +45,8 @@ class Settings(BaseSettings):
class SmsAlert(BaseModel): class SmsAlert(BaseModel):
from_: str = Field(alias="from") from_: str = Field(alias="from") # "from" is reserved word in Python, use an alias
fromName: str = ""
text: str text: str
sentStamp: datetime sentStamp: datetime
receivedStamp: datetime receivedStamp: datetime
@ -61,7 +62,7 @@ def send_mail(smsAlert: SmsAlert):
msg["Subject"] = f"SMS from {smsAlert.from_}" msg["Subject"] = f"SMS from {smsAlert.from_}"
msg["From"] = settings.mail.sender msg["From"] = settings.mail.sender
msg["To"] = settings.mail.to msg["To"] = settings.mail.to
fmt = dict(smsAlert) fmt = dict(smsAlert) # Make a dict for sms
fmt["from"] = fmt.pop("from_") fmt["from"] = fmt.pop("from_")
msg.set_content(settings.mail.template.format_map(fmt)) msg.set_content(settings.mail.template.format_map(fmt))
return send( return send(

View file

@ -19,3 +19,20 @@ def test_handle_sms():
) )
assert response.status_code == 200 assert response.status_code == 200
assert response.json() == "OK" assert response.json() == "OK"
def test_handle_sms_with_fromName():
with TestClient(app) as client:
response = client.post(
"/handle-sms",
json={
"text": "Hello!",
"from": "12345678",
"fromName": "foobar",
"sentStamp": "1234",
"receivedStamp": "1235",
"sim": "2",
},
)
assert response.status_code == 200
assert response.json() == "OK"