NdoleStudio/httpsms
GitHub: NdoleStudio/httpsms
通过 HTTP API 调用 Android 手机实现短信收发的自托管 SMS 网关服务。
Stars: 3462 | Forks: 565
# httpSMS
[](https://github.com/NdoleStudio/httpsms/actions/workflows/web.yml)
[](https://github.com/NdoleStudio/httpsms/actions/workflows/api.yml)
[](https://github.com/NdoleStudio/httpsms/graphs/contributors)
[](https://github.com/NdoleStudio/httpsms/blob/master/LICENSE)
[](CODE_OF_CONDUCT.md)
[](https://scrutinizer-ci.com/g/NdoleStudio/httpsms/?branch=main)
[](https://uptime.betterstack.com/?utm_source=status_badge)
[](https://github.com/sponsors/ndolestudio)
[](https://discord.gg/kGk8HVqeEZ)
[httpSMS](https://httpsms.com) 是一项服务,允许您将 Android 手机用作 SMS 网关来发送和接收 SMS 消息。
您只需向简单的 HTTP API 发送请求,它就会触发您的 Android 手机发送 SMS。您的 Android 手机上接收到的 SMS 消息也可以转发到您的 webhook endpoint。
快速入门指南 👉 [https://docs.httpsms.com](https://docs.httpsms.com)
## 目录
- [为什么?](#why)
- [Web UI](#web-ui)
- [API](#api)
- [Android App](#android-app)
- [聊天/论坛](#chatforum)
- [功能](#features)
- [端到端加密](#end-to-end-encryption)
- [Webhook](#webhook)
- [背压机制](#back-pressure)
- [消息过期](#message-expiration)
- [API Clients](#api-clients)
- [流程](#flows)
- [发送 SMS 消息](#sending-an-sms-message)
- [自托管部署 - Docker](#self-host-setup---docker)
- [1. 设置 Firebase](#1-setup-firebase)
- [2. 设置 SMTP 邮件服务](#2-setup-smtp-email-service)
- [3. 设置 Cloudflare Turnstile](#3-setup-cloudflare-turnstile)
- [4. 下载代码](#4-download-the-code)
- [5. 设置环境变量](#5-setup-the-environment-variables)
- [6. 构建并运行](#6-build-and-run)
- [7. 创建系统用户](#7-create-the-system-user)
- [8. 构建 Android App](#8-build-the-android-app)
- [集成测试](#integration-testing)
- [许可证](#license)
## 为什么?
我来自喀麦隆,我想要一种使用 API 自动发送和接收 SMS 消息的方法。
遗憾的是,许多国家/地区不支持购买虚拟手机号码,而且我找不到一个现成且好用的解决方案,能让我通过直观的 HTTP API 使用手机来发送/接收 SMS 消息。
## Web UI
Web 界面 https://httpsms.com 是使用 [Nuxt](https://nuxtjs.org/) 和 [Vuetify](https://vuetifyjs.com/en/) 构建的。
它作为单页应用托管在 Firebase 上。源代码位于 [web](./web) 目录中。
## API
API https://api.httpsms.com 是使用 [Fiber](https://gofiber.io/)、Go 语言和 [CockroachDB](https://www.cockroachlabs.com/) 数据库构建的。
它作为 Serverless 应用程序在 Google Cloud Run 上运行。API 文档可以在这里找到 https://api.httpsms.com/index.html
```
// Sending an SMS Message using Go
client := htpsms.New(htpsms.WithAPIKey(/* API Key from https://httpsms.com/settings */))
client.Messages.Send(context.Background(), &httpsms.MessageSendParams{
Content: "This is a sample text message",
From: "+18005550199",
To: "+18005550100",
})
```
## Android App
[Android App](https://apk.httpsms.com/HttpSms.apk) 是一个使用 Kotlin 并遵循 Material Design 原则构建的原生应用程序。
在开始发送和接收 SMS 消息之前,必须先将此应用安装在 Android 手机上。
[
](https://github.com/NdoleStudio/httpsms/releases/)
## 聊天/论坛
## 功能
### 端到端加密
您可以使用军用级别的 [AES-256 加密](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) 算法对您的消息进行端到端加密。您的加密密钥仅存储在您的手机上,因此即使是服务器也无法查看您的 Android 手机上发送和接收的 SMS 消息的内容。
### Webhook
### 背压机制
为了不滥用 Android 上的 SMS API,您可以设置速率限制(例如每分钟 3 条消息)。这样一来,即使您调用 API 向 100 人发送消息,它也只会以每分钟 3 条消息的速率发送。
### 消息过期
有时手机未能及时收到推送通知,导致无法发送 SMS 消息。您可以设置消息的有效超时时间,如果消息在超时时间过后过期,您将会收到通知。
## API Clients
- [x] Go: https://github.com/NdoleStudio/httpsms-go
- [x] JavaScript/TypeScript: https://github.com/NdoleStudio/httpsms-node
## 流程
### 发送 SMS 消息
```
sequenceDiagram
User->>+httpSMS API: Call /v1/messages/send API
httpSMS API-->>+Push Queue: Schedule notification about new message
httpSMS API-->>-User: Respond with 202 (Accepted)
Push Queue-->>+httpSMS API: [Async] Send notification request
httpSMS API-->>-Android App: Send push notification about new message
Android App-->>httpSMS API: [Async] Fetch message
Android App-->>Android App: Send Message using Android SMS API
Android App-->>httpSMS API: [Async] Send result of sending SMS
Android App-->>httpSMS API: [Async] Send Delivery Report
```
## 自托管部署 - Docker
### 1. 设置 Firebase
- httpSMS 应用程序使用 [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) 向您的 Android 手机发送推送通知,以触发发送 SMS 消息。
访问 [Firebase 控制台](https://console.firebase.google.com/) 并创建一个新项目,然后按照[这里的步骤](https://firebase.google.com/docs/web/setup#register-app) 获取您的 Firebase Web SDK 配置凭据。
例如,我创建了一个名为 `httpsms-docker` 的 Firebase 项目,这是我的 Web SDK 配置
```
const firebaseConfig = {
apiKey: "AIzaSyAKqPvj51igvvNNcRtxxxxx",
authDomain: "httpsms-docker.firebaseapp.com",
projectId: "httpsms-docker",
storageBucket: "httpsms-docker.appspot.com",
messagingSenderId: "668063041624",
appId: "1:668063041624:web:29b9e3b702796xxxx",
measurementId: "G-18VRYL2xxxx",
};
```
- 在 [Firebase 控制台](https://console.firebase.google.com/u/0/) 中启用 `Email/Password` 登录,打开 **Authentication** 部分。在“登录方式”选项卡中,启用 `Email/password` 登录方式并点击 `Save`。
- Firebase 的 `email/password` 登录方式存在 [一个 bug](https://github.com/firebase/firebaseui-web/issues/1040),这会阻止您登录。目前的解决方法是在 Firebase 控制台中 [禁用电子邮件枚举保护](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection#disable)。
- 按照[这里的步骤](https://firebase.google.com/docs/admin/setup#initialize_the_sdk_in_non-google_environments) 生成您的 Firebase 服务账号凭据,并将凭据保存在一个名为 `firebase-credentials.json` 的文件中,我们将使用此文件通过 Firebase Admin SDK 进行身份验证。
- 使用[此处的说明](https://support.google.com/firebase/answer/7015592?hl=en#android&zippy=%2Cin-this-article) 生成您的 Android `google-services.json` 文件,我们稍后将使用它来配置 Android App。
### 2. 设置 SMTP 邮件服务
httpSMS 应用程序使用 [SMTP](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) 向用户发送电子邮件,例如,当您的 Android 手机长时间离线时。
您可以使用 [mailtrap](https://mailtrap.io/) 这样的服务来创建用于开发目的的 SMTP 服务器。
### 3. 设置 Cloudflare Turnstile
消息搜索路由 (`/v1/messages/search`) 受 [Cloudflare Turnstile](https://developers.cloudflare.com/turnstile/get-started/) 验证码保护,以防止滥用。您需要设置一个 Turnstile widget 才能使消息搜索功能正常工作。
1. 前往 [Cloudflare 仪表板](https://dash.cloudflare.com/) 并导航到 **Turnstile**。
2. 添加一个新站点,并为您的自托管域名进行配置(例如,用于本地开发的 `localhost`)。
3. 记下 **Site Key** 和 **Secret Key** —— 您将分别在前端和后端的环境变量中用到它们。
### 4. 下载代码
克隆 httpSMS GitHub 仓库
```
git clone https://github.com/NdoleStudio/httpsms.git
```
### 5. 设置环境变量
- 将 `web` 目录中的 `.env.docker` 文件复制到 `.env`
```
cp web/.env.docker web/.env
```
- 使用上面第 1 步中的 Firebase Web SDK 配置,更新 `web` 目录中 `.env` 文件里的环境变量
```
FIREBASE_API_KEY=
FIREBASE_AUTH_DOMAIN=
FIREBASE_PROJECT_ID=
FIREBASE_STORAGE_BUCKET=
FIREBASE_MESSAGING_SENDER_ID=
FIREBASE_APP_ID=
FIREBASE_MEASUREMENT_ID=
# 来自步骤 3 的 Cloudflare Turnstile site key
CLOUDFLARE_TURNSTILE_SITE_KEY=
```
- 将 `api` 目录中的 `.env.docker` 文件复制到 `.env`
```
cp api/.env.docker api/.env
```
- 使用您的 Firebase 服务账号凭据、SMTP 服务器详细信息以及 Cloudflare Turnstile secret key 更新 `api` 目录中 `.env` 文件里的环境变量。
```
# SMTP email server 设置
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_HOST=
SMTP_PORT=
# Firebase service account credentials
FIREBASE_CREDENTIALS=
# 这是来自你的 firebase web 配置的 `projectId`
GCP_PROJECT_ID=
# 来自步骤 3 的 Cloudflare Turnstile secret key
CLOUDFLARE_TURNSTILE_SECRET_KEY=
```
- 不用理会 `EVENTS_QUEUE_USER_API_KEY` 和 `EVENTS_QUEUE_USER_ID` 设置。我们稍后会进行设置。
### 6. 构建并运行
- 使用 `docker-compose.yml` 文件构建并运行 API、Web UI、数据库和缓存。构建和下载所有 Docker 镜像需要一段时间。
完成后,您将能够通过 http://localhost:3000 访问 Web UI,并通过 http://localhost:8000 访问 API
```
docker compose up --build
```
### 7. 创建系统用户
- 应用程序使用系统用户的概念来异步处理事件。您应该在数据库的 `users` 表中手动创建此用户。确保使用与您的 `.env` 文件中的 `EVENTS_QUEUE_USER_ID` 和 `EVENTS_QUEUE_USER_API_KEY` 相同的 `id` 和 `api_key`。
INSERT INTO users (id, api_key, email ) VALUES ('your-system-user-id', 'your-system-api-key', 'system@domain.com');
### 8. 构建 Android App。
- 在 [Android Studio](https://developer.android.com/studio) 中构建 Android App 之前,您需要使用在第 1 步中获得的文件替换 `android/app` 目录中的 `google-services.json` 文件。您需要这样做才能使 Firebase FCM 消息正常工作。
## 集成测试
该项目包含端到端集成测试,用于验证完整的 SMS 发送/接收生命周期。测试在 Docker 中运行完整技术栈(API、PostgreSQL、Redis),并附带一个模拟 Android 设备的手机模拟器。
📖 **完整文档:** [`tests/README.md`](tests/README.md)
**快速运行:**
```
cd tests
bash generate-firebase-credentials.sh
export FIREBASE_CREDENTIALS=$(jq -c . firebase-credentials.json)
docker compose up -d --build --wait
docker compose wait seed && sleep 2
go test -v -timeout 120s ./...
docker compose down -v
```
每次向 `main` 分支推送/提交 PR 时,集成测试也会在 CI 中自动运行。
## 许可证
本项目基于 GNU AFFERO GENERAL PUBLIC LICENSE 版本 3 进行许可 - 详见 [LICENSE](LICENSE) 文件
## 目录
- [为什么?](#why)
- [Web UI](#web-ui)
- [API](#api)
- [Android App](#android-app)
- [聊天/论坛](#chatforum)
- [功能](#features)
- [端到端加密](#end-to-end-encryption)
- [Webhook](#webhook)
- [背压机制](#back-pressure)
- [消息过期](#message-expiration)
- [API Clients](#api-clients)
- [流程](#flows)
- [发送 SMS 消息](#sending-an-sms-message)
- [自托管部署 - Docker](#self-host-setup---docker)
- [1. 设置 Firebase](#1-setup-firebase)
- [2. 设置 SMTP 邮件服务](#2-setup-smtp-email-service)
- [3. 设置 Cloudflare Turnstile](#3-setup-cloudflare-turnstile)
- [4. 下载代码](#4-download-the-code)
- [5. 设置环境变量](#5-setup-the-environment-variables)
- [6. 构建并运行](#6-build-and-run)
- [7. 创建系统用户](#7-create-the-system-user)
- [8. 构建 Android App](#8-build-the-android-app)
- [集成测试](#integration-testing)
- [许可证](#license)
## 为什么?
我来自喀麦隆,我想要一种使用 API 自动发送和接收 SMS 消息的方法。
遗憾的是,许多国家/地区不支持购买虚拟手机号码,而且我找不到一个现成且好用的解决方案,能让我通过直观的 HTTP API 使用手机来发送/接收 SMS 消息。
## Web UI
Web 界面 https://httpsms.com 是使用 [Nuxt](https://nuxtjs.org/) 和 [Vuetify](https://vuetifyjs.com/en/) 构建的。
它作为单页应用托管在 Firebase 上。源代码位于 [web](./web) 目录中。
## API
API https://api.httpsms.com 是使用 [Fiber](https://gofiber.io/)、Go 语言和 [CockroachDB](https://www.cockroachlabs.com/) 数据库构建的。
它作为 Serverless 应用程序在 Google Cloud Run 上运行。API 文档可以在这里找到 https://api.httpsms.com/index.html
```
// Sending an SMS Message using Go
client := htpsms.New(htpsms.WithAPIKey(/* API Key from https://httpsms.com/settings */))
client.Messages.Send(context.Background(), &httpsms.MessageSendParams{
Content: "This is a sample text message",
From: "+18005550199",
To: "+18005550100",
})
```
## Android App
[Android App](https://apk.httpsms.com/HttpSms.apk) 是一个使用 Kotlin 并遵循 Material Design 原则构建的原生应用程序。
在开始发送和接收 SMS 消息之前,必须先将此应用安装在 Android 手机上。
[
](https://github.com/NdoleStudio/httpsms/releases/)
## 聊天/论坛
## 功能
### 端到端加密
您可以使用军用级别的 [AES-256 加密](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) 算法对您的消息进行端到端加密。您的加密密钥仅存储在您的手机上,因此即使是服务器也无法查看您的 Android 手机上发送和接收的 SMS 消息的内容。
### Webhook
### 背压机制
为了不滥用 Android 上的 SMS API,您可以设置速率限制(例如每分钟 3 条消息)。这样一来,即使您调用 API 向 100 人发送消息,它也只会以每分钟 3 条消息的速率发送。
### 消息过期
有时手机未能及时收到推送通知,导致无法发送 SMS 消息。您可以设置消息的有效超时时间,如果消息在超时时间过后过期,您将会收到通知。
## API Clients
- [x] Go: https://github.com/NdoleStudio/httpsms-go
- [x] JavaScript/TypeScript: https://github.com/NdoleStudio/httpsms-node
## 流程
### 发送 SMS 消息
```
sequenceDiagram
User->>+httpSMS API: Call /v1/messages/send API
httpSMS API-->>+Push Queue: Schedule notification about new message
httpSMS API-->>-User: Respond with 202 (Accepted)
Push Queue-->>+httpSMS API: [Async] Send notification request
httpSMS API-->>-Android App: Send push notification about new message
Android App-->>httpSMS API: [Async] Fetch message
Android App-->>Android App: Send Message using Android SMS API
Android App-->>httpSMS API: [Async] Send result of sending SMS
Android App-->>httpSMS API: [Async] Send Delivery Report
```
## 自托管部署 - Docker
### 1. 设置 Firebase
- httpSMS 应用程序使用 [Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) 向您的 Android 手机发送推送通知,以触发发送 SMS 消息。
访问 [Firebase 控制台](https://console.firebase.google.com/) 并创建一个新项目,然后按照[这里的步骤](https://firebase.google.com/docs/web/setup#register-app) 获取您的 Firebase Web SDK 配置凭据。
例如,我创建了一个名为 `httpsms-docker` 的 Firebase 项目,这是我的 Web SDK 配置
```
const firebaseConfig = {
apiKey: "AIzaSyAKqPvj51igvvNNcRtxxxxx",
authDomain: "httpsms-docker.firebaseapp.com",
projectId: "httpsms-docker",
storageBucket: "httpsms-docker.appspot.com",
messagingSenderId: "668063041624",
appId: "1:668063041624:web:29b9e3b702796xxxx",
measurementId: "G-18VRYL2xxxx",
};
```
- 在 [Firebase 控制台](https://console.firebase.google.com/u/0/) 中启用 `Email/Password` 登录,打开 **Authentication** 部分。在“登录方式”选项卡中,启用 `Email/password` 登录方式并点击 `Save`。
- Firebase 的 `email/password` 登录方式存在 [一个 bug](https://github.com/firebase/firebaseui-web/issues/1040),这会阻止您登录。目前的解决方法是在 Firebase 控制台中 [禁用电子邮件枚举保护](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection#disable)。
- 按照[这里的步骤](https://firebase.google.com/docs/admin/setup#initialize_the_sdk_in_non-google_environments) 生成您的 Firebase 服务账号凭据,并将凭据保存在一个名为 `firebase-credentials.json` 的文件中,我们将使用此文件通过 Firebase Admin SDK 进行身份验证。
- 使用[此处的说明](https://support.google.com/firebase/answer/7015592?hl=en#android&zippy=%2Cin-this-article) 生成您的 Android `google-services.json` 文件,我们稍后将使用它来配置 Android App。
### 2. 设置 SMTP 邮件服务
httpSMS 应用程序使用 [SMTP](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) 向用户发送电子邮件,例如,当您的 Android 手机长时间离线时。
您可以使用 [mailtrap](https://mailtrap.io/) 这样的服务来创建用于开发目的的 SMTP 服务器。
### 3. 设置 Cloudflare Turnstile
消息搜索路由 (`/v1/messages/search`) 受 [Cloudflare Turnstile](https://developers.cloudflare.com/turnstile/get-started/) 验证码保护,以防止滥用。您需要设置一个 Turnstile widget 才能使消息搜索功能正常工作。
1. 前往 [Cloudflare 仪表板](https://dash.cloudflare.com/) 并导航到 **Turnstile**。
2. 添加一个新站点,并为您的自托管域名进行配置(例如,用于本地开发的 `localhost`)。
3. 记下 **Site Key** 和 **Secret Key** —— 您将分别在前端和后端的环境变量中用到它们。
### 4. 下载代码
克隆 httpSMS GitHub 仓库
```
git clone https://github.com/NdoleStudio/httpsms.git
```
### 5. 设置环境变量
- 将 `web` 目录中的 `.env.docker` 文件复制到 `.env`
```
cp web/.env.docker web/.env
```
- 使用上面第 1 步中的 Firebase Web SDK 配置,更新 `web` 目录中 `.env` 文件里的环境变量
```
FIREBASE_API_KEY=
FIREBASE_AUTH_DOMAIN=
FIREBASE_PROJECT_ID=
FIREBASE_STORAGE_BUCKET=
FIREBASE_MESSAGING_SENDER_ID=
FIREBASE_APP_ID=
FIREBASE_MEASUREMENT_ID=
# 来自步骤 3 的 Cloudflare Turnstile site key
CLOUDFLARE_TURNSTILE_SITE_KEY=
```
- 将 `api` 目录中的 `.env.docker` 文件复制到 `.env`
```
cp api/.env.docker api/.env
```
- 使用您的 Firebase 服务账号凭据、SMTP 服务器详细信息以及 Cloudflare Turnstile secret key 更新 `api` 目录中 `.env` 文件里的环境变量。
```
# SMTP email server 设置
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_HOST=
SMTP_PORT=
# Firebase service account credentials
FIREBASE_CREDENTIALS=
# 这是来自你的 firebase web 配置的 `projectId`
GCP_PROJECT_ID=
# 来自步骤 3 的 Cloudflare Turnstile secret key
CLOUDFLARE_TURNSTILE_SECRET_KEY=
```
- 不用理会 `EVENTS_QUEUE_USER_API_KEY` 和 `EVENTS_QUEUE_USER_ID` 设置。我们稍后会进行设置。
### 6. 构建并运行
- 使用 `docker-compose.yml` 文件构建并运行 API、Web UI、数据库和缓存。构建和下载所有 Docker 镜像需要一段时间。
完成后,您将能够通过 http://localhost:3000 访问 Web UI,并通过 http://localhost:8000 访问 API
```
docker compose up --build
```
### 7. 创建系统用户
- 应用程序使用系统用户的概念来异步处理事件。您应该在数据库的 `users` 表中手动创建此用户。确保使用与您的 `.env` 文件中的 `EVENTS_QUEUE_USER_ID` 和 `EVENTS_QUEUE_USER_API_KEY` 相同的 `id` 和 `api_key`。
INSERT INTO users (id, api_key, email ) VALUES ('your-system-user-id', 'your-system-api-key', 'system@domain.com');
### 8. 构建 Android App。
- 在 [Android Studio](https://developer.android.com/studio) 中构建 Android App 之前,您需要使用在第 1 步中获得的文件替换 `android/app` 目录中的 `google-services.json` 文件。您需要这样做才能使 Firebase FCM 消息正常工作。
## 集成测试
该项目包含端到端集成测试,用于验证完整的 SMS 发送/接收生命周期。测试在 Docker 中运行完整技术栈(API、PostgreSQL、Redis),并附带一个模拟 Android 设备的手机模拟器。
📖 **完整文档:** [`tests/README.md`](tests/README.md)
**快速运行:**
```
cd tests
bash generate-firebase-credentials.sh
export FIREBASE_CREDENTIALS=$(jq -c . firebase-credentials.json)
docker compose up -d --build --wait
docker compose wait seed && sleep 2
go test -v -timeout 120s ./...
docker compose down -v
```
每次向 `main` 分支推送/提交 PR 时,集成测试也会在 CI 中自动运行。
## 许可证
本项目基于 GNU AFFERO GENERAL PUBLIC LICENSE 版本 3 进行许可 - 详见 [LICENSE](LICENSE) 文件标签:Android, DSL, EVTX分析, HTTP API, 搜索引擎查询, 日志审计, 消息转发, 短信网关, 请求拦截, 通信服务