messenger
Send a text message to a batch of users listed in a CSV
Messenger is a light-weight Node app that lets you send a single text message to a list of users. The front-end is built with Vue.js and Twilio is used to send the SMS messages.
Users CSV File
Users are parsed from a local CSV file, located inside the server/numbers
folder. The app looks inside this folder for a file named users.csv
and expects a CSV with the following column names:
firstName | lastName | phoneNumber | |
---|---|---|---|
John | Doe | john.doe@example.com | 555-555-5555 |
These four columns must exist in any order inside the CSV. Any additional columns are allowed and will be ignored when parsing the file. Additionally, the phone number can be in any format as long as it constitutes a valid US phone number.
Check out the test.csv
for an example of how this file might look.
Dynamic Users File
The app looks for a file named users.csv
by default, but another file can be used by adding the PHONE_NUMBERS_FILE
environment variable. This allows you to segment groups of users and change between them on the fly without redeploying the application. See the next section on environment variables for more details.
Environment Variables
There are a number of required and optional environment variables used by the server. We use a module called dotenv to emulate these when running the app locally. It should look something like this:
TWILIO_ACCOUNT_SID=<YOUR_TWILIO_SID>
TWILIO_AUTH_TOKEN=<YOUR_TWILIO_AUTH_TOKEN>
TWILIO_NUMBER=<YOUR_TWILIO_PHONE_NUMBER>
PHONE_NUMBERS_FILE=test
MESSAGE_BATCH=250
PIN=<YOUR_MESSENGER_PIN>
TWILIO_ACCOUNT_SID
: An application SID is the way that a Twilio application is identified.TWILIO_AUTH_TOKEN
: Acts as the password for your Twilio application.TWILIO_NUMBER
: The Twilio number from which you would like to send the SMS messages.PHONE_NUMBERS_FILE
(optional): The CSV file where users will be parsed from when the server starts. For instance, if this value was set toprod
the server will look for users inside the fileserver/numbers/prod.csv
.MESSAGE_BATCH
(optional): Sometimes when we have a large number of users, we want to batch the messages into several payloads so that we can monitor any potential issues as they are sent. This is one way to mitigate the message queues that act as a downstream bottleneck when sending SMS messages. This value defaults to 250, but using this variable we can set it to any number we would like.PIN
: As an extra level of security, we require a PIN for any incomingPOST /messages
request. As the app may be made available through a public endpoint, this ensures that anyone who comes across the URL cannot send messages to your users without the knowledge of this PIN.DATABASE_URL
(optional): The URL of the PostgreSQL DB storing the list of previously sent messages. If not present, the URLpostgres://localhost:5432/messenger
will be used.
Running Locally
Prerequisites
- Node.js and npm
- PostgreSQL
- Twilio account and phone number
- Make sure that the phone number has SMS capabilities
Installing
git clone https://github.com/jakepeyser/messenger.git
cd messenger
npm install
This will copy the project to your local machine and install all runtime dependencies.
You will also need to create a .env
file at the root of the project to store your environment variables. See the environment variables section for more details.
Running the app
npm run dev
This will start the Node server in "watch" mode, so that it automatically restarts when source files are changed. The server will start, parse the specified CSV file, and await further requests.
Running in Prod
Running the application in Prod is similar to running it locally:
npm install
npm start
Also, make sure to add the necessary environment variables to your production environment.
API
GET /heartbeat
Check to make sure the app is running
Responses
- 200 - Server is running smoothly
- 500 - Something is wrong
GET /messages
Get a list of previously sent messages
Query Params
- page (integer): The page of results to return
- per (integer): The number of results per page
Responses
-
200 - Page retrieved successfully
totalPages: 5, messages: [ { "name": "John Doe", "email": "john.doe@example.com", "number": "+1 (555) 555-5555", "success": true, "message": "Message sent" }, { "name": "Jane Doe", "email": "jane.doe@example.com", "number": "+12345", "success": false, "message": "The 'To' number +12345 is not a valid phone number." } ]
-
500 - Error occurred while retrieving messages
POST /messages
Send a message to a batch of users
Request Body
{
"text": "Example Message",
"pin": "SECRET_PIN"
}
Responses
-
201 - Messages were sent
{ "responses": [ { "name": "John Doe", "email": "john.doe@example.com", "number": "+1 (555) 555-5555", "success": true, "message": "Message sent" }, { "name": "Jane Doe", "email": "jane.doe@example.com", "number": "+12345", "success": false, "message": "The 'To' number +12345 is not a valid phone number." } ], "numSent": 2, "done": false }
-
401 - Incorrect PIN
-
500 - Error occurred while sending messages
Disclaimer
Please be wary of Twilio's SMS pricing when testing and running this app! Although sending an individual text is relatively cheap, the aggregate cost can often creep up on you if the number of users increases and you neglect to consider the impact on cost.
This app has only been tested to work with US mobile phone numbers, so I cannot promise it will work when texting phone numbers with other country codes!