SMS Status Callbacks

This script utilizes SMS status callbacks to show a simple delivery status tracker that could begin running before a message campaign goes out and end when a message campaign ends. This tracker will log every message status event to the console and keep a record of any message failures. When the message campaign is complete and the app is ended, all the failures along with relevant information will be downloaded to CSV for later investigation.

You can learn more about SMS callbacks, all of the possible parameters you can use, and how to set them up in our status callback mega guide!

You can read the guide below, or use our recipe to quickly copy the code!

Configuring the code

While the app is running, it will log the status change event of every single message to the console with the following information: MessageStatus, MessageSid, and ErrorCode. This will happen for every outbound message in the same project that includes this script as the StatusCallback URL.

When a message returns a status of failed or undelivered, it will be added to a table that keeps track of all unsuccessful messages along with their MessageSid, MessageStatus, ErrorCode, ErrorMessage, DateSent, To, From, and Body. After every failed/undelivered message, this table will be printed so the updated list can be seen.

When the messaging campaign is over and the Flask app is closed, the whole table will be exported to CSV so that failed/undelivered messages can be easily investigated.

from flask import Flask, request
import logging
import pandas as pd
from signalwire.rest import Client as signalwire_client
import atexit

logging.basicConfig(level=logging.INFO)
app = Flask(__name__)

# create an empty array to keep track of all of our undelivered 
# or failed messages during the time this app is run
undeliveredArray = []

# define actions to take when flask app is closed 
# export dataframe of all failed or undelivered 
# messages to CSV with added detail 
def onExitApp(dataframe):
    dataframe.to_csv('failedAndUndeliveredMessages.csv', index=False, encoding='utf-8')
    print('SMS Callback App Exited')

# authenticate the SignalWire client
client = signalwire_client("ProjectID",
                           "AuthToken",
                           signalwire_space_url='YOUR_SPACE.signalwire.com')

# define route for SMS status callbacks to be posted to 
@app.route("/smsErrorTracker", methods=['POST'])
def newest_message():
    # get message sid, message status, and error code (if it exists) from callback parameters
    # if they don't exist, set to None 
    message_sid = request.values.get('MessageSid', None)
    message_status = request.values.get('MessageStatus', None)
    error_code = request.values.get('ErrorCode', None)
    
    # log every message that comes in to console 
    logging.info('SID: {}, Status: {}, ErrorCode: {}'.format(message_sid, message_status, error_code))
        
    # if the message is undelivered or failed, use message SID to fetch additional data 
    # about the failed message 
    if (message_status == "undelivered" or message_status == "failed"):
        message = client.messages(message_sid).fetch()
        
        # add identifying data from newest message to undelivered array 
        undeliveredArray.append([message_sid, message_status, error_code, message.error_message, message.date_sent, message.to, message.from_, message.body])
        # insert array into dataframe with columns for easier reading 
        df = pd.DataFrame(undeliveredArray, columns=('Message Sid', 'Message Status', 'Error Code', 'Error Message', 'Date Sent', 'To', 'From', 'Body'))
        # print dataframe to string for nicer formatting and set dataframe to our parameter in function for handling app exit 
        print(df.to_string())
        atexit.register(onExitApp, dataframe=df)
        
        # return 200OK 
    return ('', 200)

if __name__ == "__main__":
    app.run()

Running the application

You will need the Flask framework and the SignalWire Python SDK downloaded.

To run the application, execute export FLASK_APP=your_file_name.py then run flask run.


Did this page help you?