Send SMS and MMS Messages From the ESP8266 in C++

Today we'll coax an ESP8266 to send MMS and SMS messages using C++ and the Arduino IDE.  You'll need an ESP-8266 set up for the Arduino IDE, a serial connection (most likely with a serial to USB adapter or module on-board) and a friendly open, WEP or WPA (1 or 2) wireless network.

Read on, we're going to merge the Internet of Things with the Twilio API!

Sign Into - or Sign Up For - a Twilio Account

Either create a new Twilio account (sign up for a free Twilio trial here), or sign into your existing Twilio account.

Find or Purchase a SMS (and MMS) Capable Number

For this demo, you'll either need to use an SMS and MMS enabled number you own, or purchase a new one with the necessary capabilities.  

First, enter the Twilio Console.  Second, select the hash tag/Phone Numbers ('#') section on the left side, and navigate to your current active numbers.  

Under 'Capabilities', you will see the functions you'll be able to use with your Twilio phone numbers.  For this article, you'll need numbers with either SMS or both SMS and MMS capabilities. 

Checking a Twilio Phone Number for SMS Capability

If you don't currently have a number with SMS or MMS, you'll need to purchase one.  After navigating to the 'Buy a Number' link, click the SMS - and optionally the MMS - checkbox.

Buy a SMS-Capable Twilio Phone Number

Prerequisites for This ESP8266 MMS and SMS in C++ Guide

Espressif's ESP8266, sometimes found on boards costing as little as $2, is an amazing base for your IoT project.  As it boasts TLS 1.2 support, we're excited to share an example of sending messages using the ESP8266 and the Twilio API.

Hardware development introduces many more variables than software development.  We'll do our best to help guide you during the setup stage.  While we unfortunately can't test every setup, please comment if you run into issues.  We - and perhaps other readers - will do our best to help break through any roadblocks.

Board Selection

While it would be impossible to enumerate every ESP8266 board variation that would work with this guide, the repository for Arduino on ESP8266 has a nice list of tested boards.  We'd suggest that you select one of those if you haven't yet picked a dev board.

For the development of this tutorial, we used a Sparkfun Thing and Sparkfun's Basic FTDI breakout as a serial converter for programming.  As the Thing overloads the DTR pin and may have trouble with the serial monitor, we also used another generic serial converter and SoftwareSerial for debugging.  You can disable or enable it by changing the #define USE_SOFTWARE_SERIAL in Twilio_ESP8266_Example.ino.

Arduino IDE

Using the Arduino IDE with the ESP8266 helps us eliminate some of the variables inherent in this type of project.  The ESP-8266 Arduino tie-in includes the Xtensa gcc toolchain, provides the Arduino libraries, and makes it easy to program the ESP-8266.

If you choose to rewrite the code to forego the assumed Arduino environment (perhaps for Espressif's SDK), the most important steps will be to eliminate dependencies on Arduino Strings and making sure you connect to api.twilio.com:443 using TLS 1.2.  This is beyond the scope of this guide, but please share any success you have in the comments.

Building the ESP8266 MMS and SMS Example

(Note that this project has been extended in the receiving and replying to messages from the ESP8266 guide, here)

After cloning this project from our Github repository, you'll have to gather some credentials before you send your first message.  At the top of Twilio_ESP8266_Example.ino we set up a number of globals for connecting to your WiFi network, verifying the SHA1 signature of api.twilio.com (we will be watching for CA verification on the ESP8266), and sending messages with your Twilio account.  

Note that embedding your credentials on a hardware device is only acceptable for prototyping and when you will always retain physical possession of your device. If your device will be in the field, you must use revocable keys or other reversible authentication. For one solution, see our Sync for IoT product, which uses either keys or certificates.

Here is the section you will need to edit:

Loading Code Samples...
Language
/*
 * Twilio SMS and MMS on ESP8266 Example.
 */

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "twilio.hpp"

// Use software serial for debugging?
#define USE_SOFTWARE_SERIAL 0

// Your network SSID and password
const char* ssid = "Your SSID";
const char* password = "Network Password";

// Find the api.twilio.com SHA1 fingerprint, this one was valid as 
// of January 2017.
const char* fingerprint = "47 18 D6 BE F5 D0 BF CE 01 B7 AD BD 96 3A AA 46 F1 8C F1 A5";

// Twilio account specific details, from https://twilio.com/console
// Please see the article: 
// https://www.twilio.com/docs/guides/receive-and-reply-sms-and-mms-messages-esp8266-c-and-ngrok

// If this device is deployed in the field you should only deploy a revocable
// key. This code is only suitable for prototyping or if you retain physical
// control of the installation.
const char* account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const char* auth_token = "Your AUTH TOKEN";

// Details for the SMS we'll send with Twilio.  Should be a number you own 
// (check the console, link above).
String to_number    = "+18005551212";
String from_number = "+18005551212";
String message_body    = "Hello from Twilio and the ESP8266!";

// The 'authorized number' to text the ESP8266 for our example
String master_number    = "+18005551212";

// Optional - a url to an image.  See 'MediaUrl' here: 
// https://www.twilio.com/docs/api/rest/sending-messages
String media_url = "";

// Global twilio objects
Twilio *twilio;
ESP8266WebServer twilio_server(8000);

//  Optional software serial debugging
#if USE_SOFTWARE_SERIAL == 1
#include <SoftwareSerial.h>
// You'll need to set pin numbers to match your setup if you
// do use Software Serial
extern SoftwareSerial swSer(14, 4, false, 256);
#endif

/*
 * Callback function when we hit the /message route with a webhook.
 * Use the global 'twilio_server' object to respond.
 */
 void handle_message() {
        #if USE_SOFTWARE_SERIAL == 1
        swSer.println("Incoming connection!  Printing body:");
        #endif
        bool authorized = false;
        char command = '\0';

        // Parse Twilio's request to the ESP
        for (int i = 0; i < twilio_server.args(); ++i) {
                #if USE_SOFTWARE_SERIAL == 1
                swSer.print(twilio_server.argName(i));
                swSer.print(": ");
                swSer.println(twilio_server.arg(i));
                #endif

                if (twilio_server.argName(i) == "From" and 
                    twilio_server.arg(i) == master_number) {
                    authorized = true;
                } else if (twilio_server.argName(i) == "Body") {
                        if (twilio_server.arg(i) == "?" or
                            twilio_server.arg(i) == "0" or
                            twilio_server.arg(i) == "1") {
                                command = twilio_server.arg(i)[0];
                        }
                }
        } // end for loop parsing Twilio's request

        // Logic to handle the incoming SMS
        String response = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
        if (command != '\0') {
                if (authorized) {
                        switch (command) {
                        case '0':
                                digitalWrite(LED_BUILTIN, LOW);
                                response += "<Response><Message>"
                                "Turning light off!"
                                "</Message></Response>";
                                break;
                        case '1':
                                digitalWrite(LED_BUILTIN, HIGH);
                                response += "<Response><Message>"
                                "Turning light on!"
                                "</Message></Response>";
                                break;
                        case '?':
                        default:
                                response += "<Response><Message>"
                                "0 - Light off, 1 - Light On, "
                                "? - Help\n"
                                "The light is currently: ";
                                response += digitalRead(LED_BUILTIN);
                                response += "</Message></Response>";
                                break;               
                        }
                } else {
                        response += "<Response><Message>"
                        "Unauthorized!"
                        "</Message></Response>";
                }

        } else {
                response += "<Response><Message>"
                "Look: a SMS response from an ESP8266!"
                "</Message></Response>";
        }

        twilio_server.send(200, "application/xml", response);
}

/*
 * Setup function for ESP8266 Twilio Example.
 * 
 * Here we connect to a friendly wireless network, instantiate our twilio 
 * object, optionally set up software serial, then send a SMS or MMS message.
 */
void setup() {
        WiFi.begin(ssid, password);
        twilio = new Twilio(account_sid, auth_token, fingerprint);

        #if USE_SOFTWARE_SERIAL == 1
        swSer.begin(115200);
        while (WiFi.status() != WL_CONNECTED) {
                delay(1000);
                swSer.print(".");
        }
        swSer.println("");
        swSer.println("Connected to WiFi, IP address: ");
        swSer.println(WiFi.localIP());
        #else
        while (WiFi.status() != WL_CONNECTED) delay(1000);
        #endif

        // Response will be filled with connection info and Twilio API responses
        // from this initial SMS send.
        String response;
        bool success = twilio->send_message(
                to_number,
                from_number,
                message_body,
                response,
                media_url
                );

        // Set up a route to /message which will be the webhook url
        twilio_server.on("/message", handle_message);
        twilio_server.begin();

        // Use LED_BUILTIN to find the LED pin and set the GPIO to output
        pinMode(LED_BUILTIN, OUTPUT);

        #if USE_SOFTWARE_SERIAL == 1
        swSer.println(response);
        #endif
}


/* 
 *  In our main loop, we listen for connections from Twilio in handleClient().
 */
void loop() {
        twilio_server.handleClient();
}
Loading Twilio and WiFi credentials from the Twilio Console and your network onto the ESP8266
Setting Credentials on the ESP8266

Loading Twilio and WiFi credentials from the Twilio Console and your network onto the ESP8266

After that, building the example should be as simple as hitting the 'Upload' button in the Arduino IDE.  

If all goes well, you should get a text message with the content of the message_body variable.  If all goes poorly, we've included sample code to debug with SoftwareSerial; depending on your board and setup you will likely need to change it or use the defult Serial library.  Here are the first steps of an example (successful) debugging session with SoftwareSerial:

Connected to WiFi, IP address: 
192.168.1.155
Connecting to host api.twilio.com
Certificate fingerprints match.
Sending http POST: 
POST /2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages HTTP/1.1
Authorization: Basic BASE64ENCODEDSTRINGHERE
Host: api.twilio.com
Cache-control: no-cache
User-Agent: ESP8266 Twilio Example
Content-Type: application/x-www-form-urlencoded
Content-Length: 72
Connection: close

To=+18005551212&From=+18005551212&Body=Hello+from+Twilio+and+the+ESP8266

Sending a Message with the ESP8266

Since we'll be hitting the Twilio REST API directly, this code has some superficial similarities to our SMS in C and C++ examples.  Of course, without a library like libcurl abstracting away the finer details, we have to write some lower level code.  You'll note that we've included code to connect to a WiFi network and verify the SHA1 signature of api.twilio.com.

Most starkly, however, we're crafting a HTTP POST manually:

Loading Code Samples...
Language
#include "twilio.hpp"

/*
 * Send a SMS or MMS with the Twilio REST API
 *
 * Inputs:
 *  - to_number : Number to send the message to
 *  - from_number : Number to send the message from
 *  - message_body : Text to send in the message (max 1600 characters)
 *  - picture_url : (Optional) URL to an image
 *
 * Outputs:
 *  - response : Connection messages and Twilio responses returned to caller
 *  - bool (method) : Whether the message send was successful
 */
bool Twilio::send_message(
        const String& to_number,
        const String& from_number,
        const String& message_body,
        String& response,
        const String& picture_url)
{
        // Check the body is less than 1600 characters in length.  see:
        // https://support.twilio.com/hc/en-us/articles/223181508-Does-Twilio-support-concatenated-SMS-messages-or-messages-over-160-characters-
        // Note this is only checking ASCII length, not UCS-2 encoding; your
        // application may need to enhance this.
        if (message_body.length() > 1600) {
                response += "Message body must be 1600 or fewer characters.";
                response += "  You are attempting to send ";
                response += message_body.length();
                response += ".\r\n";
                return false;
        }

        // URL encode our message body & picture URL to escape special chars
        // such as '&' and '='
        String encoded_body = urlencode(message_body);

        // Use WiFiClientSecure class to create TLS 1.2 connection
        WiFiClientSecure client;
        const char* host = "api.twilio.com";
        const int   httpsPort = 443;

        // Connect to Twilio's REST API
        response += ("Connecting to host ");
        response += host;
        response += "\r\n";
        if (!client.connect(host, httpsPort)) {
                response += ("Connection failed!\r\n");
                return false;
        }

        // Check the SHA1 Fingerprint (We will watch for CA verification)
        if (client.verify(fingerprint.c_str(), host)) {
                response += ("Certificate fingerprints match.\r\n");
        } else {
                response += ("Certificate fingerprints don't match.\r\n");
                return false;
        }

        // Attempt to send an SMS or MMS, depending on picture URL
        String post_data = "To=" + urlencode(to_number) + "&From=" + urlencode(from_number) + \
        "&Body=" + encoded_body;
        if (picture_url.length() > 0) {
                String encoded_image = urlencode(picture_url);
                post_data += "&MediaUrl=" + encoded_image;
        }

        // Construct headers and post body manually
        String auth_header = _get_auth_header(account_sid, auth_token);
        String http_request = "POST /2010-04-01/Accounts/" +
                              String(account_sid) + "/Messages HTTP/1.1\r\n" +
                              auth_header + "\r\n" + "Host: " + host + "\r\n" +
                              "Cache-control: no-cache\r\n" +
                              "User-Agent: ESP8266 Twilio Example\r\n" +
                              "Content-Type: " +
                              "application/x-www-form-urlencoded\r\n" +
                              "Content-Length: " + post_data.length() +"\r\n" +
                              "Connection: close\r\n" +
                              "\r\n" + post_data + "\r\n";

        response += ("Sending http POST: \r\n"+http_request);
        client.println(http_request);

        // Read the response into the 'response' string
        response += ("request sent");
        while (client.connected()) {
        String line = client.readStringUntil('\n');
        response += (line);
        response += ("\r\n");
        }
        response += ("closing connection");
        return true;
}

/* Private function to create a Basic Auth field and parameter */
String Twilio::_get_auth_header(const String& user, const String& password) {
        size_t toencodeLen = user.length() + password.length() + 2;
        char toencode[toencodeLen];
        memset(toencode, 0, toencodeLen);
        snprintf(
                toencode,
                toencodeLen,
                "%s:%s",
                user.c_str(),
                password.c_str()
        );

        String encoded = base64::encode((uint8_t*)toencode, toencodeLen-1);
        String encoded_string = String(encoded);
        std::string::size_type i = 0;

        // Strip newlines (after every 72 characters in spec)
        while (i < encoded_string.length()) {
                i = encoded_string.indexOf('\n', i);
                if (i == -1) {
                        break;
                }
                encoded_string.remove(i, 1);
        }
        return "Authorization: Basic " + encoded_string;
}
Manually crafting a HTTP POST on the ESP8266 in order to send a SMS or MMS.
Sending a SMS or MMS with the ESP8266 in C++

Manually crafting a HTTP POST on the ESP8266 in order to send a SMS or MMS.

We also need to do a number of other things not required (or abstracted away) on the desktop.  You'll note that we've included code to base64 encode your ACCOUNT_SID and AUTH_TOKEN for HTTP Basic Authentication.  Additionally, we've included Steve Nelson's URL encoding and decoding functions to escape special characters in the SMS or MMS body.  Ensure that your eventual application has similar functions, and your own IoT Thing will work right the first time.

From the Internet of Things to the Pockets of Everyone with Twilio

The ESP8266 is a great chip which can act as the brain of your next IoT project, even without much external silicon.  If you'd like to add telephone connectivity to your next project but a *NIX single board computer is too heavy, it's nice to know you've got alternatives.

For whatever you're building next - a monitoring tool, a must-buy wearable, a home automation product - add phone interoperability on the cheap (and with reasonable security) with ESP8266 and the Twilio API.

Paul Kamp
David Prothero

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...
/*
 * Twilio SMS and MMS on ESP8266 Example.
 */

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "twilio.hpp"

// Use software serial for debugging?
#define USE_SOFTWARE_SERIAL 0

// Your network SSID and password
const char* ssid = "Your SSID";
const char* password = "Network Password";

// Find the api.twilio.com SHA1 fingerprint, this one was valid as 
// of January 2017.
const char* fingerprint = "47 18 D6 BE F5 D0 BF CE 01 B7 AD BD 96 3A AA 46 F1 8C F1 A5";

// Twilio account specific details, from https://twilio.com/console
// Please see the article: 
// https://www.twilio.com/docs/guides/receive-and-reply-sms-and-mms-messages-esp8266-c-and-ngrok

// If this device is deployed in the field you should only deploy a revocable
// key. This code is only suitable for prototyping or if you retain physical
// control of the installation.
const char* account_sid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const char* auth_token = "Your AUTH TOKEN";

// Details for the SMS we'll send with Twilio.  Should be a number you own 
// (check the console, link above).
String to_number    = "+18005551212";
String from_number = "+18005551212";
String message_body    = "Hello from Twilio and the ESP8266!";

// The 'authorized number' to text the ESP8266 for our example
String master_number    = "+18005551212";

// Optional - a url to an image.  See 'MediaUrl' here: 
// https://www.twilio.com/docs/api/rest/sending-messages
String media_url = "";

// Global twilio objects
Twilio *twilio;
ESP8266WebServer twilio_server(8000);

//  Optional software serial debugging
#if USE_SOFTWARE_SERIAL == 1
#include <SoftwareSerial.h>
// You'll need to set pin numbers to match your setup if you
// do use Software Serial
extern SoftwareSerial swSer(14, 4, false, 256);
#endif

/*
 * Callback function when we hit the /message route with a webhook.
 * Use the global 'twilio_server' object to respond.
 */
 void handle_message() {
        #if USE_SOFTWARE_SERIAL == 1
        swSer.println("Incoming connection!  Printing body:");
        #endif
        bool authorized = false;
        char command = '\0';

        // Parse Twilio's request to the ESP
        for (int i = 0; i < twilio_server.args(); ++i) {
                #if USE_SOFTWARE_SERIAL == 1
                swSer.print(twilio_server.argName(i));
                swSer.print(": ");
                swSer.println(twilio_server.arg(i));
                #endif

                if (twilio_server.argName(i) == "From" and 
                    twilio_server.arg(i) == master_number) {
                    authorized = true;
                } else if (twilio_server.argName(i) == "Body") {
                        if (twilio_server.arg(i) == "?" or
                            twilio_server.arg(i) == "0" or
                            twilio_server.arg(i) == "1") {
                                command = twilio_server.arg(i)[0];
                        }
                }
        } // end for loop parsing Twilio's request

        // Logic to handle the incoming SMS
        String response = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
        if (command != '\0') {
                if (authorized) {
                        switch (command) {
                        case '0':
                                digitalWrite(LED_BUILTIN, LOW);
                                response += "<Response><Message>"
                                "Turning light off!"
                                "</Message></Response>";
                                break;
                        case '1':
                                digitalWrite(LED_BUILTIN, HIGH);
                                response += "<Response><Message>"
                                "Turning light on!"
                                "</Message></Response>";
                                break;
                        case '?':
                        default:
                                response += "<Response><Message>"
                                "0 - Light off, 1 - Light On, "
                                "? - Help\n"
                                "The light is currently: ";
                                response += digitalRead(LED_BUILTIN);
                                response += "</Message></Response>";
                                break;               
                        }
                } else {
                        response += "<Response><Message>"
                        "Unauthorized!"
                        "</Message></Response>";
                }

        } else {
                response += "<Response><Message>"
                "Look: a SMS response from an ESP8266!"
                "</Message></Response>";
        }

        twilio_server.send(200, "application/xml", response);
}

/*
 * Setup function for ESP8266 Twilio Example.
 * 
 * Here we connect to a friendly wireless network, instantiate our twilio 
 * object, optionally set up software serial, then send a SMS or MMS message.
 */
void setup() {
        WiFi.begin(ssid, password);
        twilio = new Twilio(account_sid, auth_token, fingerprint);

        #if USE_SOFTWARE_SERIAL == 1
        swSer.begin(115200);
        while (WiFi.status() != WL_CONNECTED) {
                delay(1000);
                swSer.print(".");
        }
        swSer.println("");
        swSer.println("Connected to WiFi, IP address: ");
        swSer.println(WiFi.localIP());
        #else
        while (WiFi.status() != WL_CONNECTED) delay(1000);
        #endif

        // Response will be filled with connection info and Twilio API responses
        // from this initial SMS send.
        String response;
        bool success = twilio->send_message(
                to_number,
                from_number,
                message_body,
                response,
                media_url
                );

        // Set up a route to /message which will be the webhook url
        twilio_server.on("/message", handle_message);
        twilio_server.begin();

        // Use LED_BUILTIN to find the LED pin and set the GPIO to output
        pinMode(LED_BUILTIN, OUTPUT);

        #if USE_SOFTWARE_SERIAL == 1
        swSer.println(response);
        #endif
}


/* 
 *  In our main loop, we listen for connections from Twilio in handleClient().
 */
void loop() {
        twilio_server.handleClient();
}
#include "twilio.hpp"

/*
 * Send a SMS or MMS with the Twilio REST API
 *
 * Inputs:
 *  - to_number : Number to send the message to
 *  - from_number : Number to send the message from
 *  - message_body : Text to send in the message (max 1600 characters)
 *  - picture_url : (Optional) URL to an image
 *
 * Outputs:
 *  - response : Connection messages and Twilio responses returned to caller
 *  - bool (method) : Whether the message send was successful
 */
bool Twilio::send_message(
        const String& to_number,
        const String& from_number,
        const String& message_body,
        String& response,
        const String& picture_url)
{
        // Check the body is less than 1600 characters in length.  see:
        // https://support.twilio.com/hc/en-us/articles/223181508-Does-Twilio-support-concatenated-SMS-messages-or-messages-over-160-characters-
        // Note this is only checking ASCII length, not UCS-2 encoding; your
        // application may need to enhance this.
        if (message_body.length() > 1600) {
                response += "Message body must be 1600 or fewer characters.";
                response += "  You are attempting to send ";
                response += message_body.length();
                response += ".\r\n";
                return false;
        }

        // URL encode our message body & picture URL to escape special chars
        // such as '&' and '='
        String encoded_body = urlencode(message_body);

        // Use WiFiClientSecure class to create TLS 1.2 connection
        WiFiClientSecure client;
        const char* host = "api.twilio.com";
        const int   httpsPort = 443;

        // Connect to Twilio's REST API
        response += ("Connecting to host ");
        response += host;
        response += "\r\n";
        if (!client.connect(host, httpsPort)) {
                response += ("Connection failed!\r\n");
                return false;
        }

        // Check the SHA1 Fingerprint (We will watch for CA verification)
        if (client.verify(fingerprint.c_str(), host)) {
                response += ("Certificate fingerprints match.\r\n");
        } else {
                response += ("Certificate fingerprints don't match.\r\n");
                return false;
        }

        // Attempt to send an SMS or MMS, depending on picture URL
        String post_data = "To=" + urlencode(to_number) + "&From=" + urlencode(from_number) + \
        "&Body=" + encoded_body;
        if (picture_url.length() > 0) {
                String encoded_image = urlencode(picture_url);
                post_data += "&MediaUrl=" + encoded_image;
        }

        // Construct headers and post body manually
        String auth_header = _get_auth_header(account_sid, auth_token);
        String http_request = "POST /2010-04-01/Accounts/" +
                              String(account_sid) + "/Messages HTTP/1.1\r\n" +
                              auth_header + "\r\n" + "Host: " + host + "\r\n" +
                              "Cache-control: no-cache\r\n" +
                              "User-Agent: ESP8266 Twilio Example\r\n" +
                              "Content-Type: " +
                              "application/x-www-form-urlencoded\r\n" +
                              "Content-Length: " + post_data.length() +"\r\n" +
                              "Connection: close\r\n" +
                              "\r\n" + post_data + "\r\n";

        response += ("Sending http POST: \r\n"+http_request);
        client.println(http_request);

        // Read the response into the 'response' string
        response += ("request sent");
        while (client.connected()) {
        String line = client.readStringUntil('\n');
        response += (line);
        response += ("\r\n");
        }
        response += ("closing connection");
        return true;
}

/* Private function to create a Basic Auth field and parameter */
String Twilio::_get_auth_header(const String& user, const String& password) {
        size_t toencodeLen = user.length() + password.length() + 2;
        char toencode[toencodeLen];
        memset(toencode, 0, toencodeLen);
        snprintf(
                toencode,
                toencodeLen,
                "%s:%s",
                user.c_str(),
                password.c_str()
        );

        String encoded = base64::encode((uint8_t*)toencode, toencodeLen-1);
        String encoded_string = String(encoded);
        std::string::size_type i = 0;

        // Strip newlines (after every 72 characters in spec)
        while (i < encoded_string.length()) {
                i = encoded_string.indexOf('\n', i);
                if (i == -1) {
                        break;
                }
                encoded_string.remove(i, 1);
        }
        return "Authorization: Basic " + encoded_string;
}