Table of Contents
- Introduction
- Things you’ll need
- Twilio Function
- Studio Flow
- Configure Your Twilio Number
- *Update
- Additional Resources
Introduction
While the Voicemail Twimlet has email forwarding built in, many of our customers find it limiting and ask if there's a way to forward recordings to email without the Twimlet or a web server.
This document shows how to forward your recordings to email using Twilio Studio, Functions, and SendGrid.
Things you’ll need
A Twilio account and a phone number that can receive calls.
A SendGrid account with a verified sender.
SendGrid Account
In order to use the SendGrid API to send emails we need a SendGrid API key. Create a SendGrid account (if you don't have one already), confirm your email address, then head to the API Keys area in the SendGrid dashboard and create an API Key with Full Access.
Be sure to save the API Key Secret to your notepad.
Verified Sender
You also need to verify one of your emails to send from it with SendGrid. To do this, go to the Senders page under Marketing, click Create New Sender, fill out the information, then go to that email inbox and click the link in the verification email.
Twilio Function
Now let's write your Function. Your Function will initialize a SendGrid mail client and use it to email your voicemail recording URL.
Configuration
To make requests with SendGrid's API, we need a way to authenticate. To do this, we'll use your SendGrid API Secret.
- Open up your Twilio console and head to the Functions configure section.
- Add a new environment variable called `SENDGRID_API_SECRET` and paste in your API Key Secret (begins with SG).
We also need to make environment variables for the email addresses you’ll be sending To / From.
- Create a `TO_EMAIL_ADDRESS` variable and enter the email to receive your voicemails.
Create the variable `FROM_EMAIL_ADDRESS` and enter one of the verified sender emails in your SendGrid account.
NOTE: It’s best to use two of your personal emails when testing. Emails from a company domain (e.g. @twilio.com) can be blocked if not verified properly.
In addition, to the Environment Variables, we need to include the “@sendgrid/mail” library in our Dependencies on the same page.
- Scroll down to dependencies, add "@sendgrid/mail" and the version 6.3.1, then save.
Write the Function
*NOTE: This method does not support transcribing your recordings. If you're interested in transcription, please see the Update section below.
1. Now head to the Functions management page and create a new function.
2. Pick the Blank template and proceed.
3. Add a name and path for your function.
4. The Function is included below. It works out of the box, so feel free and copy, paste, and save. If you'd like to understand what's happening, read on.
//Initialize SendGrid Mail Client
const sgMail = require('@sendgrid/mail');
// Define Handler function required for all Twilio Functions
exports.handler = function(context, event, callback) {
// Build SG mail request
sgMail.setApiKey(context.SENDGRID_API_SECRET);
// Define message params
const msg = {
to: context.TO_EMAIL_ADDRESS,
from: context.FROM_EMAIL_ADDRESS,
text: `Recording URL is: ${event.url}`,
subject: `New Voicemail from: ${event.From}`,
};
// Send message
sgMail.send(msg)
.then(response => {
console.log("Neat.")
callback();
})
.catch(err => {
console.log("Not neat.")
callback(err);
});
};
How your Function works
There’s a bunch of code there, and it might not be immediately obvious what we’re doing. Here’s the play-by-play on how it works.
- At the top of your Function, we initialize the `@sendgrid/mail` module which will help us craft a mail request to SendGrid.
- We then call Twilio's handler function, which is required for all Twilio Functions. For more information about how the handler function works and what the context, event, and callback arguments are used for, check out the docs here.
- Next, we build the SendGrid request per the guidelines in the docs here.
- Since Twilio Functions are written in Javascript, we use the SendGrid Node.js library.
- The first thing we do when building our request is use the setApiKey() method which will authenticate our request. Inside it, we place our API Secret, which we pull from the Function context.
- Next, we build our message parameters. Again, we pull our to and from emails from context, and we also reference a couple variables, `url` and `From`, from the event argument of our Function. We’ll cover how exactly we’re passing these into our Function when we build our flow, but just know that the event argument is where you’ll reference variables passed into a Function.
- Lastly, we call the send() method to actually send the request to SendGrid for delivery. Inside the promise handler, we print a message to let us know the request was accepted, then we embed our empty Function callback() which is required in every Twilio Function. Below that we add a catch statement so we can know what’s wrong if SendGrid fails our request.
Studio Flow
The last piece of our app is the Studio Flow, which we'll use for our voicemail. Studio makes it easy to setup a Voicemail with the Say/Play and Record Voicemail widgets, so that's what we'll do.
Create Your Flow
Just like we did in the Function section, you can import a pre-built Flow that only needs a couple changes following the steps in this section. If you'd prefer to build your flow from scratch, skip ahead to the next section.
- Go to the Manage Flows Studio page, then click either the red Create new Flow button (if this is your first Flow) or the red plus (‘+’) sign (if it’s not your first Flow).
- Give your Flow a name and click Next.
- Select “Start from scratch” in the menu, and click Next again.
Build your Voicemail
1. Drag a Say/Play widget onto your canvas and connect this to the Incoming Call port of your Trigger.
a. Configure this widget to say or play your voicemail greeting. If you plan to have your user end their message with a button press, make to include this instruction.
2. Drag a Record Voicemail widget onto the canvas and connect this to the Audio Complete port of your Say/Play widget.
a. Configure your voicemail widget as you like. In mine, I end the recording with the press of # or 5 seconds of silence, do not trim silence, and play a beep.
3. Lastly, drag a Run Function widget onto your canvas and connect this to the Recording Complete port.
a. Select the Default Service (all Twilio Functions built in the console will be included in the Default Service).
b. Select the Function you just created in the Function URL dropdown.
c. Now create the Function Parameters we use in your Function. Function parameters are passed as additional parameters into the Function you call and taken from the event argument.
i. Click Add, set the Key field to "url", and set the value to the recording URL {{widgets.record_voicemail_1.RecordingUrl}}
ii. Click Add again, set the Key filed to From, and set the value to {{contact.channel.address}}, which is the caller's number.
4. Your flow should now look about like this.
5. (OPTIONAL) Add functionality to support instances where no audio is heard in your recording or if it fails. You can also add a goodbye message to play the user after the recording their voicemail and before the call is dropped.
Configure Your Twilio Number
And that's it! Now just configure the Incoming Call webhook of your Twilio Number to use the Studio Flow you just created.
- Click the number you want to use for your voicemail in your Active Numbers here.
- Scroll down to the A CALL COMES IN dropdown in the Voice section and select Studio Flow.
- Select your new Flow in the Select a Flow dropdown to the right.
- Hit Save at the bottom, and you’ll be all set to test!
If everything went smoothly, you should now hear your voicemail greeting when you call your Twilio number, and the voicemail you leave should be emailed to you.
*NOTE: Voicemails with a short duration (e.g. under 1 second) may be analyzed as a caller hangup instead of a complete recording. Keep this in mind when testing and leave a voicemail of at least 3 seconds.
*Update
The original version of this post did not support transcription. Follow the steps below if you would like to send the transcribed recording in your email in addition to the recording URL.
1. Modify your function so the text field in your email includes the transcription text. In addition, modify the recording URL since we are now taking this from the transcription callback. You can see the transcription callback parameters here: https://www.twilio.com/docs/voice/twiml/record#attributes-transcribecallback-parameters.
The new function should look like this:
//Initialize SendGrid Mail Client
const sgMail = require('@sendgrid/mail');
// Define Handler function required for all Twilio Functions
exports.handler = function(context, event, callback) {
// Build SG mail request
sgMail.setApiKey(context.SENDGRID_API_SECRET);
// Define message params
const msg = {
to: context.TO_EMAIL_ADDRESS,
from: context.FROM_EMAIL_ADDRESS,
text: `New Voicemail from: ${event.From}.\n Transcription is: ${event.TranscriptionText}\n Recording URL is: ${event.RecordingUrl}`,
subject: `New Voicemail from: ${event.From}`,
};
// Send message
sgMail.send(msg)
.then(response => {
console.log("Neat.")
callback();
})
.catch(err => {
console.log("Not neat.")
callback(err);
});
};
2. Modify the Record Voicemail widget in your Flow.
a. Enable TRANSCRIBE AUDIO TO TEXT.
b. Set the TRANSCRIPTION CALLBACK URL to the URL of your Function.
3. Remove the Run Function widget from your Flow as this is no longer needed.
Your Flow should now look something like this:
Additional Resources
You may find it useful to build additional functionality around this app. For example, you may want to forward your calls to your work number during business hours, but use the voicemail otherwise. To set something like this up, check out this Twilio Blog Post:
https://www.twilio.com/blog/2018/06/custom-javascript-twilio-functions-code-studio-flows.html.