Forward your Voicemail Transcriptions to Email with Python & Flask

This guide will show how you can easily take a voicemail message from incoming callers, transcribe the recording, and email the transcription. We will use the SignalWire Python SDK to record a voicemail and transcribe it along with the MailGun API to send an email.

Setup Your Environment File

  1. Copy from 'example.env' and fill in your values
  2. Save the new file as '.env'

Your file should look something like this, where SIGNALWIRE_SPACE is the full name of your SignalWire Space. e.g.: example.signalwire.com, SIGNALWIRE_PROJECT is your SignalWire Project ID, and SIGNALWIRE_TOKEN is your SignalWire API token.

SIGNALWIRE_SPACE=
SIGNALWIRE_PROJECT=
SIGNALWIRE_TOKEN=
MAILGUN_DOMAIN=
MAILGUN_API_TOKEN=
[email protected]
[email protected]
EMAIL_SUBJECT=Transcribed Voicemail

Step by Step Code Walkthrough

Our first route is the entry point for all incoming calls. In this route, we will use Say to play a quick prompt and Record to take a message. We will redirect to the /hangup route when the recording is finished as specified by the action URL. We will also make use of recording status callbacks and transcription status callbacks so that SignalWire will send an http request to our specified routes when the recordings and transcriptions are complete.

# Entry point for incoming calls, prompts to leave a voice mail for processing.
@app.route('/voice_entry', methods=['GET', 'POST'])
def voice_entry():
    # instantiate voice response 
    response = VoiceResponse()
    
    # play voicemail prompt and record voicemail that will finish on # key 
    response.say("Please leave a message at the beep. Press the pound key when finished.")
    response.record(finishOnKey="#", maxLength="1", action="/hangup", transcribe="true", transcribeCallback="/transcribe_webhook", recordingStatusCallback="/recording_webhook")
    # return response
    return str(response)

Our next route /hangup is the action URL that will execute when the recording is complete. We will play a short message to say goodbye and then use Hangup to end the call.

# Terminates the call
@app.route('/hangup', methods=['GET','POST'])
def hangup():
    # instantiate voice response 
    response = VoiceResponse()
    # say goodbye and hangup 
    response.say('Thank you! Good Bye!')
    response.hangup()
    # return response 
    return str(response)

Now we will define a function send_email(body) that will utilize the MailGun API to send an email using the variables from our .env file.

# Sends the email provided using mailgun
def send_email(body):
    return requests.post(
        "https://api.mailgun.net/v3/" + os.environ['MAILGUN_DOMAIN'] + "/messages",
        auth=("api", os.environ['MAILGUN_API_TOKEN']),
        data={"from": os.environ['EMAIL_FROM'],
              "to": [os.environ['EMAIL_TO']],
              "subject": os.environ['EMAIL_SUBJECT'],
              "text": body })

This route /recording_webhook will be called when the recording is completed. We will use it for information purposes only - for the sake of printing to console all the necessary information about recordings. Read more about recording status callbacks in our status callbacks super guide or check out our snippet for sending recordings via SMS!

# The webhook that is called on recording updates
@app.route('/recording_webhook', methods=['GET','POST'])
def recording_webhook():
    # For information only, and to show what is returned.
    pprint.pprint(request.values)

    return "200"

Our last route/transcribe_webhook will be used to handle the transcription status callback when the transcription is complete. We will use the TranscriptionText parameter as the body in our send_email(body) function.

# The webhook that is called when a transcription is received, this will process the transcription actions.
@app.route('/transcribe_webhook', methods=['GET','POST'])
def transcribe_webhook():
        # get all request values 
    pprint.pprint(request.values)

    # Recording Information
    recording_duration = request.values.get("RecordingDuration")
    recording_url = request.values.get("RecordingUrl")
    
    # Send Email
    send_email(request.values.get('TranscriptionText'))
    return "200"

Build and Run on Docker

  1. Use our pre-built image from Docker Hub
docker pull signalwire/snippets-voicemail-transcription:latest

(or build your own image)

  1. Build your image
docker build -t snippets-voicemail-transcription .
  1. Run your image
docker run --publish 5000:5000 --env-file .env snippets-voicemail-transcription
  1. The application will run on port 5000

Build and Run Natively

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

You may need to use an SSH tunnel for testing this code if running on your local machine. – we recommend ngrok. You can learn more about how to use ngrok here.

Sign Up Here

If you would like to test this example out, you can create a SignalWire account and space here.

Please feel free to reach out to us on our Community Slack or create a Support ticket if you need guidance!


What’s Next

Check out the full code on our SignalWire Github Repo!

Did this page help you?