Send SMS and MMS Messages In C

Today we'll use C, libcurl, and some POSIX APIs to send SMS and MMS messages using the Twilio REST API.  Outside of a (at least mostly) POSIX-compliant build environment, you'll also need libcurl for the code in this guide.

Let's get started!

Sign up for a Twilio Account (or Sign In)

Before exercising the Twilio API, you'll need to either create an account, or login to an existing account.

Don't have an account?  Sign up for a free Twilio trial.

Find or Purchase a SMS-Capable Number

This demo requires a Twilio phone number with SMS (and MMS) capabilities.  You can either use a phone number that you already have, or purchase a new one with SMSes enabled.

Here's how SMS-capable numbers appear in your number list:

Checking a Twilio Phone Number for SMS Capability

And here's how you can search for a new number with SMS (or MMS, if you select it as well) capabilities:

Buy a SMS-Capable Twilio Phone Number

Prerequisites for This C SMS Sending Guide

This guide targets POSIX Compliant environments, and was tested with clang-800.0.42.1 on Mac OSX 10.11, gcc 4.9.2 on Raspbian (kernel 4.4.34-v7+) and gcc 5.4.0 in Cygwin 2.877 on Windows 7 64-Bit.  At a minimum, we'll need:

libcurl was available on the Mac already.  On the Raspberry Pi, you can install a suitable version with:

sudo apt-get install libcurl4-openssl-dev

In Windows 7, I was able to install libcurl with Cygwin Setup:

Installing libcurl-devel and curl in Cygwin

Building c_sms

Here's our example Makefile, which was usable in all three environments.

On most *NIX-type systems (including in Cygwin), building is probably as easy as:

git clone https://github.com/TwilioDevEd/twilio_c_sms.git
cd twilio_c_sms
make

You might need to make minor edits to the Makefile to build c_sms in your environment.  Most commonly, you'll change the library search paths or the compiler.

Send an SMS or MMS Message with C

We've just built c_sms, which can be called from the command line and will attempt to send an SMS or MMS before exiting.  twilio.c includes a function, twilio_send_message, which is easily adaptable to your own codebase (of course, you will need to add validation and safety before using it in production.  For example, note that as is you can add more parameters through the variables!).

Let's look at how twilio_send_message works.  

  • First, we prepare our account credentials and HTTP Parameters to be consumed by the Twilio API.
  • Second, we need to prepare libcurl to execute a HTTP POST to the Twilio API.  The curl_easy_setopt function calls instruct libcurl to post with the url and body we set, and use our Account and Auth Token details.
  • Third, we execute our POST then clean up with the lines:
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);​
    
  • Fourth, we check for any errors from either libcurl or the Twilio API.

Here's the code for twilio_send_message in C:

Loading Code Samples...
Language
#include <string.h>
#include <curl/curl.h>

#include "twilio.h"

/*
* _twilio_null_write is a portable way to ignore the response from 
* curl_easy_perform
*/
size_t _twilio_null_write(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    return size * nmemb;
}

/*
* twilio_send_message gathers the necessary parameters for a Twilio SMS or MMS.
* 
* Inputs:
*         - account_sid: Account SID from the Twilio console.
*         - auth_token: Authorization from the Twilio console.
*         - to_number: Where to send the MMS or SMS
*         - from_number: Number in your Twilio account to use as a sender.
*         - message_body: (Max: 1600 characters) The body of the MMS or SMS 
*               message which will be sent to the to_number.
*         - verbose: Whether to print all the responses
* 
*  Optional:
*         - picture_url: If picture URL is not NULL and is a valid image url, a
                MMS will be sent by Twilio.
*/
int twilio_send_message(char *account_sid,
                        char *auth_token,
                        char *message,
                        char *from_number,
                        char *to_number,
                        char *picture_url,
                        bool verbose)
{

        // See: https://www.twilio.com/docs/api/rest/sending-messages for
        // information on Twilio body size limits.
        if (strlen(message) > 1600) {
            fprintf(stderr, "SMS send failed.\n"
                    "Message body must be less than 1601 characters.\n"
                    "The message had %zu characters.\n", strlen(message));
            return -1;
        }

        CURL *curl;
        CURLcode res;
        curl_global_init(CURL_GLOBAL_ALL);
        curl = curl_easy_init();

        char url[MAX_TWILIO_MESSAGE_SIZE];
        snprintf(url,
                 sizeof(url),
                 "%s%s%s",
                 "https://api.twilio.com/2010-04-01/Accounts/",
                 account_sid,
                 "/Messages");

        char parameters[MAX_TWILIO_MESSAGE_SIZE];
        if (!picture_url) {
            snprintf(parameters,
                     sizeof(parameters),
                     "%s%s%s%s%s%s",
                     "To=",
                     to_number,
                     "&From=",
                     from_number,
                     "&Body=",
                     message);
        } else {
            snprintf(parameters,
                     sizeof(parameters),
                     "%s%s%s%s%s%s%s%s",
                     "To=",
                     to_number,
                     "&From=",
                     from_number,
                     "&Body=",
                     message,
                     "&MediaUrl=",
                     picture_url);
        }


        curl_easy_setopt(curl, CURLOPT_POST, 1);
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, parameters);
        curl_easy_setopt(curl, CURLOPT_USERNAME, account_sid);
        curl_easy_setopt(curl, CURLOPT_PASSWORD, auth_token);

        if (!verbose) {
                curl_easy_setopt(curl, 
                                 CURLOPT_WRITEFUNCTION, 
                                 _twilio_null_write);
        }

        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);

        long http_code = 0;
        curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);

        if (res != CURLE_OK) {
                if (verbose) {
                        fprintf(stderr,
                                "SMS send failed: %s.\n",
                                curl_easy_strerror(res));
                }
                return -1;
        } else if (http_code != 200 && http_code != 201) {
                if (verbose) {
                        fprintf(stderr,
                                "SMS send failed, HTTP Status Code: %ld.\n",
                                http_code);
                }
                return -1;
        } else {
                if (verbose) {
                        fprintf(stderr,
                                "SMS sent successfully!\n");
                }
                return 0;
        }

}
Setting up required HTTP Parameters and authentication, preparing libcurl, POSTing to the Twilio REST API, and checking the response.
Using libcurl to Send a Message with C and Twilio

Setting up required HTTP Parameters and authentication, preparing libcurl, POSTing to the Twilio REST API, and checking the response.

Running c_sms

Once c_sms is built, calling it from the command line is easy.  Simply pass in your account credentials, from & to numbers, and a message body and you'll be lighting up a phone.  Here's an example session:

account_sid=ACXXXXXXXXXXXXXXXXXXXXXX
auth_token=your_auth_token
bin/c_sms -a $account_sid -s $auth_token -t "+18005551212" -f "+18005551213" -m "Hello, World!"
# Optionally, use '-p http://some/path/to/img.jpg' to send an MMS.

Do You See What I C?  Time For Your Own Creation

45+ years and billions of lines of code later, it's obvious that Dennis Ritchie designed a language to go the distance.  Now Twilio can come with you on your C-journey with just a few helper libraries and your SMS and MMS use case.  

We hope this is a good starting point; please let us know what you build on Twitter!

Paul Kamp

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
#include <string.h>
#include <curl/curl.h>

#include "twilio.h"

/*
* _twilio_null_write is a portable way to ignore the response from 
* curl_easy_perform
*/
size_t _twilio_null_write(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    return size * nmemb;
}

/*
* twilio_send_message gathers the necessary parameters for a Twilio SMS or MMS.
* 
* Inputs:
*         - account_sid: Account SID from the Twilio console.
*         - auth_token: Authorization from the Twilio console.
*         - to_number: Where to send the MMS or SMS
*         - from_number: Number in your Twilio account to use as a sender.
*         - message_body: (Max: 1600 characters) The body of the MMS or SMS 
*               message which will be sent to the to_number.
*         - verbose: Whether to print all the responses
* 
*  Optional:
*         - picture_url: If picture URL is not NULL and is a valid image url, a
                MMS will be sent by Twilio.
*/
int twilio_send_message(char *account_sid,
                        char *auth_token,
                        char *message,
                        char *from_number,
                        char *to_number,
                        char *picture_url,
                        bool verbose)
{

        // See: https://www.twilio.com/docs/api/rest/sending-messages for
        // information on Twilio body size limits.
        if (strlen(message) > 1600) {
            fprintf(stderr, "SMS send failed.\n"
                    "Message body must be less than 1601 characters.\n"
                    "The message had %zu characters.\n", strlen(message));
            return -1;
        }

        CURL *curl;
        CURLcode res;
        curl_global_init(CURL_GLOBAL_ALL);
        curl = curl_easy_init();

        char url[MAX_TWILIO_MESSAGE_SIZE];
        snprintf(url,
                 sizeof(url),
                 "%s%s%s",
                 "https://api.twilio.com/2010-04-01/Accounts/",
                 account_sid,
                 "/Messages");

        char parameters[MAX_TWILIO_MESSAGE_SIZE];
        if (!picture_url) {
            snprintf(parameters,
                     sizeof(parameters),
                     "%s%s%s%s%s%s",
                     "To=",
                     to_number,
                     "&From=",
                     from_number,
                     "&Body=",
                     message);
        } else {
            snprintf(parameters,
                     sizeof(parameters),
                     "%s%s%s%s%s%s%s%s",
                     "To=",
                     to_number,
                     "&From=",
                     from_number,
                     "&Body=",
                     message,
                     "&MediaUrl=",
                     picture_url);
        }


        curl_easy_setopt(curl, CURLOPT_POST, 1);
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, parameters);
        curl_easy_setopt(curl, CURLOPT_USERNAME, account_sid);
        curl_easy_setopt(curl, CURLOPT_PASSWORD, auth_token);

        if (!verbose) {
                curl_easy_setopt(curl, 
                                 CURLOPT_WRITEFUNCTION, 
                                 _twilio_null_write);
        }

        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);

        long http_code = 0;
        curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);

        if (res != CURLE_OK) {
                if (verbose) {
                        fprintf(stderr,
                                "SMS send failed: %s.\n",
                                curl_easy_strerror(res));
                }
                return -1;
        } else if (http_code != 200 && http_code != 201) {
                if (verbose) {
                        fprintf(stderr,
                                "SMS send failed, HTTP Status Code: %ld.\n",
                                http_code);
                }
                return -1;
        } else {
                if (verbose) {
                        fprintf(stderr,
                                "SMS sent successfully!\n");
                }
                return 0;
        }

}