Programming a Twilio phone menu with TwiML & some PHP

Twilio allows your web application to easily make and receive phone calls and SMS text messages using a simple web service API and basic web programming skills like HTTP, XML, and REST. You can build hosted IVR, PBX and SMS applications with no up front costs and a very competitive pricing

With so many possibilities and mash-ups ideas, the sky is the limit to the things you can do with Twilio … however, in its most basic forms (and most popular usage I believe) Twilio lets you build a simple phone menu in no time at all.

I’m sure we will be utilizing Twilio in the future for some cool & rad Code in Chaos projects, but for now, we made a simple phone menu with a company directory that forwards the caller to the person’s personal phone number and a message recording option that will let the caller record a two minute message, then emails that message along with the caller ID information to a specified email address.

its a very simple implementation, we though we’d share it, since we found the Twilio samples a bit too complicated than what they should be, they rely on too many files for something that can be achieved with just one.

index.php
<? header('Content-Type: text/xml') ?>
<? include 'email.php' ?>
<?= '<?xml version="1.0" encoding="utf-8"?>' ?>
<Response>
    <? if (!array_key_exists('Digits', $_REQUEST)): ?>
        <Say voice="woman">You have reached Code in Chaos.</Say>
        <Redirect method="GET">index.php?Digits=0</Redirect>
    <? else: ?>
        <? if (array_key_exists('RecordingUrl', $_REQUEST)): ?>
            <? email($_REQUEST['RecordingUrl']) ?>
            <Say voice="woman">Thank you, we will contact you as soon as possible. Goodbye.</Say>
            <Hangup/>
        <? elseif (array_key_exists('Dial', $_REQUEST)): ?>
            <? switch (@$_REQUEST['Digits']):
                case '0': ?>
                    <Redirect method="GET">index.php?Digits=1</Redirect>
                    <? break ?>

                <? case '1': ?>
                    <Dial timeout="15" hangupOnStar="true">+16477007703</Dial>
                    <Say voice="woman">Failed to connect your call, please try again later. Goodbye.</Say>
                    <Hangup/>
                    <? break ?>

                <? case '*': ?>
                    <Redirect method="GET">index.php?Digits=0</Redirect>
                    <? break ?>

                <? default: ?>
                    <Say voice="woman">Invalid Entry.</Say>
                    <Redirect method="GET">index.php?Digits=1</Redirect>
            <? endswitch ?>
        <? else: ?>
            <? switch ($_REQUEST['Digits']):
                case '0': ?>
                    <Gather numDigits="1" timeout="10" action="index.php" method="POST">                        
                        <Say voice="woman">Main menu.</Say>
                        <Pause length="1"/>
                        <Say voice="woman">Press 1 for the company's directory.</Say>
                        <Say voice="woman">Press 2 to leave a message.</Say>
                        <Say voice="woman">Press 0 to repeat this menu.</Say>
                        
                    </Gather>

                    <? if (array_key_exists('Repeated', $_REQUEST)): ?>
                        <Say voice="woman">Goodbye.</Say>
                        <Hangup/>
                    <? else: ?>
                        <Redirect method="GET">index.php?Digits=0&Repeated=true</Redirect>
                    <? endif ?>
                    <? break ?>

                <? case '1': ?>
                    <Gather numDigits="1" timeout="10" action="index.php?Dial=true" method="POST">
                        <Say voice="woman">Company Directory.</Say>
                        <Pause length="1"/>                        
                        <Say voice="woman">For Ahmad Nassri, press 1.</Say>
                        <Pause length="2"/>
                        <Say voice="woman">Press 0 to repeat this menu.</Say>
                        <Say voice="woman">Press star to return to the main menu.</Say>
                    </Gather>

                    <? if (array_key_exists('Repeated', $_REQUEST)): ?>
                        <Say voice="woman">Goodbye.</Say>
                        <Hangup/>
                    <? else: ?>
                        <Redirect method="GET">index.php?Digits=1&Repeated=true</Redirect>
                    <? endif ?>
                    <? break ?>

                <? case '2': ?>
                    <Say voice="woman">Record your message after the tone, when finished, press the star key.</Say>
                    <Pause length="1"/>
                    <Say voice="woman">Please leave your name, number and email address and the reason for your call.</Say>
                    
                    <Record timeout="10" maxLength="120" action="index.php" method="POST" finishOnKey="*"/>
                    <? break ?>

                <? default: ?>
                    <Say voice="woman">Invalid Entry</Say>
                    <Redirect method="GET">index.php?Digits=0</Redirect>
            <? endswitch ?>
        <? endif ?>
    <? endif ?>
</Response>
email.php
<?php
function email($url) {
    $message = sprintf('<b>Caller:</b> %s<br/> <b>City:</b> %s<br/> <b>State:</b> %s<br/> <b>Country:</b> %s<br/>', $_REQUEST['From'], $_REQUEST['FromCity'], $_REQUEST['FromState'], $_REQUEST['FromCountry']);

    $boundary = uniqid();

    $headers = array(
        'From: Twilio <twilio@codeinchaos.com>',
        'Reply-To: No Reply <noreply@codeinchaos.com>',
        'MIME-Version: 1.0',
        'Content-Type: multipart/mixed; boundary = ' . $boundary,
        ''
    );

    $headers = join("\r\n", $headers);

    //plain text version of message
    $body = array(
        // plain text
        '--' . $boundary,
        'Content-Type: text/plain; charset=ISO-8859-1',
        'Content-Transfer-Encoding: base64',
        '',
        chunk_split(base64_encode(strip_tags($message))),
        // html
        '--' . $boundary,
        'Content-Type: text/html; charset=ISO-8859-1',
        'Content-Transfer-Encoding: base64',
        '',
        chunk_split(base64_encode($message)),
        // attachement
        '--' . $boundary,
        'Content-Type: audio/wav; name=message.wav',
        'Content-Transfer-Encoding: base64',
        'Content-Disposition: attachment',
        '',
        chunk_split(base64_encode(file_get_contents($url)))
    );

    $body = join("\r\n", $body);

    //send the email
    return @mail('contact@codeinchaos.com', 'New Voice Mail (' . $_REQUEST['CallSid'] . ')', $body, $headers);
}