MMS Tutorial: Ruby SDK
Articles - 5 min read

MMS Tutorial: Ruby SDK

How to send and receive an MMS using Ruby SDK
MMS, or multimedia messaging lets you send gifs, photos, audio, and videos, or texts longer than 160 characters to enhance communication with end users.
Some useful MMS use cases across various industries include:
  • Customer Service: Businesses are leveraging MMS to streamline the customer service experience. Sharing product images or delivering instructions via audio saves time on back and forth chatter.
  • Ticketing: MMS allows businesses to send QR codes to customers for a digital ticketing experience.
Lucky for you, we’ve updated our MMS quickstart developer docs in Ruby SDK so that you can get up and running, send and receive your first MMS on the Telnyx platform in just 30 minutes -- are you ready?
First, let’s start with an outline of the content we will be covering in this post.
  1. Introduction
  2. Setup
    a. Install packages
    b. Setting environment variables
    c. .env file*
    d. App.rb*
    e. Setup Sinatra Server
  3. Receiving Webhooks
    f. Basic Routing and Functions
  4. Media Download and Upload Functions
    g. Inbound message handling
    h. Outbound message handling
    i. Final app.rb
  5. Usage

1. Introduction

This tutorial will walk you through the set up and process of building an application in Ruby that can receive an inbound MMS on the Telnyx platform. Inbound messages include an attachment link in the webhook, and the application will be able to:
  • Download the remote attachment locally
  • Uploads the same attachment to AWS3 (or any other media storage location that you choose to save the media)
  • Sends the attachment back to the number that originally sent the message
Before you get started, make sure you’re familiar with these technologies:
  • Completed or familiar with the Receiving SMS & MMS Quickstart
  • A working Messaging Profile on our portal, with a SMS and MMS enabled phone number
  • Ruby & Gem installed
  • Familiarity with Sinatra
  • Ability to receive webhooks with something like ngrok
  • AWS account set up with proper profiles and groups with IAM for S3 -- more information in the Quickstart Previously created S3 with public permissions available
If those prerequisites are good to go, let’s go ahead and get started!

2.Setup

Install packages

First, install packages via Gem/Bundler. This will create a GemFile file with the packages needed to run the application.
1
2
3
4
5
6
7
gem install telnyx
gem install sinatra
gem install dotenv
gem install ostruct
gem install json
gem install aws-sdk
gem install down

Setting environment variables

The following environment variables need to be set:
VariableDescription
TELNYX_API_KEYYour Telnyx API Key
TELNYX_PUBLIC_KEYYour Telnyx Public Key
TELNYX_APP_PORTDefaults to 8000 The port the app will be served
AWS_PROFILEYour AWS profile as set in ~/.aws
AWS_REGIONThe region of your S3 bucket
TELNYX_MMS_S3_BUCKETThe name of the bucket to upload the media attachments

.env file

We’ll be using the dotenv package to manage variables. Make a copy of the file below, add your credentials, and save as .env in your root directory.
1
2
3
4
5
6
TELNYX_API_KEY=
TELNYX_PUBLIC_KEY=
TENYX_APP_PORT=8000
AWS_PROFILE=
AWS_REGION=
TELNYX_MMS_S3_BUCKET=

App.rb

We’ll be using a single app.rb to build the MMS application.
1
touch app.rb

Setup Sinatra Server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require 'sinatra'
require 'telnyx'
require 'dotenv/load'
require 'json'
require 'ostruct'
require 'aws-sdk-s3'
require 'down'

if __FILE__ == $0
  TELNYX_API_KEY=ENV.fetch("TELNYX_API_KEY")
  TELNYX_APP_PORT=ENV.fetch("TELNYX_APP_PORT")
  AWS_REGION = ENV.fetch("AWS_REGION")
  TELNYX_MMS_S3_BUCKET = ENV.fetch("TELNYX_MMS_S3_BUCKET")
  Telnyx.api_key = TELNYX_API_KEY
  set :port, TELNYX_APP_PORT
end

get '/' do
  "Hello World"
end

3. Receiving Webhooks

Now, it’s time to set up an endpoint to receive webhooks for inbound messages and outbound message delivery receipts (DLR).

Basic Routing and Functions

Here’s a basic overview of the application:
  1. Verify webhook & create TelnyxEvent
  2. Extract information from the webhook
  3. Iterate over any media and download/re-upload to S3 for each attachment
  4. Send the message back to the phone number from which it came
  5. Acknowledge the status update (DLR) of the outbound message

Media Download and Upload Functions

The following functions are for managing attachments:
  • Download_file saves the content from a URL to disk
  • Upload_file uploads the file passed to AWS S3 (and makes object public)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def upload_file(file_path)
  s3 = Aws::S3::Resource.new(region: AWS_REGION)
  name = File.basename(file_path)
  obj = s3.bucket(TELNYX_MMS_S3_BUCKET).object(name)
  obj.upload_file(file_path, acl: 'public-read')
  obj.public_url
end

def download_file(uri)
  temp_file = Down.download(uri)
  path = "./#{temp_file.original_filename}"
  FileUtils.mv(temp_file.path, path)
  path
end

Inbound Message Handling

Now that the functions for managing the media are in place, you’re ready to receive your first MMS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def deserialize_json(json)
  object = JSON.parse(json, object_class: OpenStruct)
  object
end

post '/messaging/inbound' do
  webhook = deserialize_json(request.body.read)
  dlr_uri = URI::HTTP.build(host: request.host, path: '/messaging/outbound')
  to_number = webhook.data.payload.to[0].phone_number
  from_number = webhook.data.payload.from.phone_number
  media = webhook.data.payload.media
  file_paths = []
  media_urls = []
  if media.any?
    media.each do |item|
      file_path = download_file(item.url)
      file_paths.push(file_path)
      media_url = upload_file(file_path)
      media_urls.push(media_url)
    end
  end

  begin
    telnyx_response = Telnyx::Message.create(
        from: to_number,
        to: from_number,
        text: "Hello, world!",
        media_urls: media_urls,
        use_profile_webhooks: false,
        webhook_url: dlr_uri.to_s
    )
    puts "Sent message with id: #{telnyx_response.id}"
  rescue Exception => ex
    puts ex
  end
end

Outbound Message Handling

As we defined our webhook_url path to be /messaging/outbound we'll need to create a function that accepts a POST request to that path within messaging.js.
1
2
3
4
post '/messaging/outbound' do
  webhook = deserialize_json(request.body.read)
  puts "Received message DLR with ID: #{webhook.data.payload.id}"
end

Final app.rb

Now, let’s put it all together!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
require 'sinatra'
require 'telnyx'
require 'dotenv/load'
require 'json'
require 'ostruct'
require 'aws-sdk-s3'
require 'down'

if __FILE__ == $0
  TELNYX_API_KEY=ENV.fetch("TELNYX_API_KEY")
  TELNYX_APP_PORT=ENV.fetch("TELNYX_APP_PORT")
  AWS_REGION = ENV.fetch("AWS_REGION")
  TELNYX_MMS_S3_BUCKET = ENV.fetch("TELNYX_MMS_S3_BUCKET")
  Telnyx.api_key = TELNYX_API_KEY
  set :port, TELNYX_APP_PORT
end

get '/' do
  "Hello World"
end

def deserialize_json(json)
  object = JSON.parse(json, object_class: OpenStruct)
  object
end

def upload_file(file_path)
  s3 = Aws::S3::Resource.new(region: AWS_REGION)
  name = File.basename(file_path)
  obj = s3.bucket(TELNYX_MMS_S3_BUCKET).object(name)
  obj.upload_file(file_path, acl: 'public-read')
  obj.public_url
end

def download_file(uri)
  temp_file = Down.download(uri)
  path = "./#{temp_file.original_filename}"
  FileUtils.mv(temp_file.path, path)
  path
end

post '/messaging/inbound' do
  webhook = deserialize_json(request.body.read)
  dlr_uri = URI::HTTP.build(host: request.host, path: '/messaging/outbound')
  to_number = webhook.data.payload.to[0].phone_number
  from_number = webhook.data.payload.from.phone_number
  media = webhook.data.payload.media
  file_paths = []
  media_urls = []
  if media.any?
    media.each do |item|
      file_path = download_file(item.url)
      file_paths.push(file_path)
      media_url = upload_file(file_path)
      media_urls.push(media_url)
    end
  end

  begin
    telnyx_response = Telnyx::Message.create(
        from: to_number,
        to: from_number,
        text: "Hello, world!",
        media_urls: media_urls,
        use_profile_webhooks: false,
        webhook_url: dlr_uri.to_s
    )
    puts "Sent message with id: #{telnyx_response.id}"
  rescue Exception => ex
    puts ex
  end
end

post '/messaging/outbound' do
  webhook = deserialize_json(request.body.read)
  puts "Received message DLR with ID: #{webhook.data.payload.id}"
end

Usage

Start the server ruby app.rb. The final step is to make your application accessible from the internet -- right now, we have a local web server that’s not typically accessible from the public internet.
To work around this, we’ll use a tunneling service which comes with client software that runs on your computer and opens an outgoing permanent connection to a public server. Then, they assign a public URL on that server to your account.
The specific tunneling tool that we’ll use is ngrok; after setting up ngrok setup on your computer, you can add the public URL to your Inbound Setting in the Mission Control Portal. To do this, click the edit symbol ✎ and paste the forwarding address from ngrok into the 'Send a Webhook to this URL' field, and add messaging/inbound to the end of the URL. You can also add an alternate address in the “Failover URL” section, or leave it blank for now.
Congratulations! Your application is ready to use -- you should be able to text a MMS to your phone number and get that same picture back!
Share on Social

Worth checking out

By using the site, you agree to our use of cookies. Accept and close Find out more here.