Building Bots with ROVE using Cisco Spark

Comment

Building Bots with ROVE using Cisco Spark

In the early days of Cisco Spark, Cisco built a quick and easy bot for moving email threads into a Spark Space by blind coping an email destination to the standard reply all email. The bot, would then create a space using the email subject as the name and then add everyone from the email thread for you. This was a great feature, but you always had that little voice in your head where you realized that every email you sent to this phantom 3rd party, had all of your email content and contacts. Cisco eventually killed their email to Spark bot due to other security concerns.

At ROVE, we liked the bot so much that we decided to rebuild the same functionality, but this time guard against the security concerns we had. Using a combination of Microsoft tools available on a standard Office365 subscription and borrowing some more advanced server-less functions from Azure, we can piece together a similar bot. This bot uses a mailbox that is ROVE owned so no more worries of a random 3rd party accessing our email threads and we can add logic into the script as needed for more advanced functions. In our case, we simply lock down the feature to ROVE employee use.

Workflow Overview

Step 1: Reply All to an email thread and add the bot's email address (mail2spark@abc.com) as a BCC.

Step 2: MS Flow tracks the user's inbox for messages and processes them.

Step 3: Flow checks that the email is in the correct BCC location and replies with an error as needed.

Step 4: Flow converts the email to a json formatted payload and posts the data to our Azure Function.

Step 5: Our Function parses the json payload, checks that the From address meets our criteria.

Step 6: Our Function uses the Spark Bot to create a space basing the space name on the email subject and strips any leading REL or FWD: to make it visually appealing.

Step 7: Our Function adds all email recipients to the space and then leaves the space. Anybody that doesn't have a Cisco Spark account will get an invite from Spark.

Step 8: Our Function replies to the original email using that formatted response.

Step 9: Flow responds to the Flow request with an HTML formatted response. 

Step 10: Flow cleans up by marking the email as read and then moves it to the trash.

Detailed Buildout

Step 1: Make a Spark Bot

Go to developer.ciscospark.com and log in with your Cisco Spark credentials. (You can use a free spark account to manage company bots.)

Go to "My Apps" at the top right and then add a bot.

Building Bots with ROVE - My Apps.png

On the next screen, you will give your bot a name, a Spark address and the opportunity to upload an image.

Building Bots with ROVE - New Bot.png

After you have created your bot, you'll get some more information. We aren't too concerned with the Bot ID for this use, but we do need the Bot's Access Token. This token is used to authenticate the API requests and gives you rights for the bot to do stuff. It's a username and password all in one, so do not lose it and do not give it out to anyone.

Step 2: Create an Azure Function

Azure Function are server less apps that can be built in an array of different programming languages. Consumption plan's are billed based on per-second resource consumption and executions. Consumption plan pricing includes a monthly free grant of 1 million requests and 400,000 GB's of resource consumption per month. So we should be able to fit into the free tier for this use.

Create a new function, select PHP as the language and select all the default options. On the main function screen, you can add in the following script replacing the Spark Token, any withROVE propaganda and bot names as needed. Then click the "Get function URL"  in the top right. We'll need that later.

Building Bots with ROVE Get function URL.png

<?php

$sparkToken = "<Spark Token Here>";

function send_to_spark($method,$uri,$data) {

    global $sparkToken;

    switch ($method) {
        case "get":
            $uri = $uri."?".$data;
            $options = array(
                    'http' => array(
                        'header'  => "Authorization: Bearer ".$sparkToken." \r\nContent-type: application/x-www-form-urlencoded\r\n",
                        'method'  => 'GET',
                    ),
                );
                break;
        case "delete":
            $uri = $uri."/".$data;
            $options = array(
                    'http' => array(
                        'header'  => "Authorization: Bearer ".$sparkToken." \r\nContent-type: application/x-www-form-urlencoded\r\n",
                        'method'  => 'DELETE',
                    ),
                );
                break;
        case "post":
            $options = array(
                'http' => array(
                    'header'  => "Authorization: Bearer ".$sparkToken." \r\nContent-type: application/json\r\n",
                    'method'  => 'POST',
                    'content' => json_encode($data),
                ),
            );
            break;
    }

    $context  = stream_context_create($options);
    $result = json_decode(file_get_contents("https://api.ciscospark.com/v1/".$uri, false, $context));

    return $result;
}
$jsonData = json_decode(file_get_contents(getenv('req')));

“//If from is not a withrove account then send error” == “//If from is not an account in your orginization then send error
if ( preg_match("/@withrove.com/",$jsonData->from) && ! preg_match("/rove2spark@withrove.com/",$jsonData->to) ) {
  //Start building email response
  $httpResponse = "<html><body>";

  //Create room using the email subject - strip RE: and FWD:
  $roomName = preg_replace("/^[Ff][Ww][Dd]:/","",preg_replace("/^[Rr][Ee]:/","",strip_tags($jsonData->subject)));
  $sparkData = array("title"=>$roomName
                            ,"type"=>"group"
                            );
  $createRoom = send_to_spark("post","rooms",$sparkData);

  //Convert to: from: cc: fields to email list and add to room
  $sparkContacts = explode(';',$jsonData->to.';'.$jsonData->from.';'.$jsonData->cc);
  array_pop($sparkContacts);
  foreach ( $sparkContacts as $userEmail ) {
      if ( $userEmail != "rove2spark@withrove.com" && $userEmail != "" ){
        $sparkData = array("roomId"=>$createRoom->id
                ,"personEmail"=>$userEmail
                );
        $roomMember = @send_to_spark("post","memberships",$sparkData);
      }
  }

  //send welcome message
  $sparkMessage  = "rove2spark is an internal use Bot for moving email threads to Cisco Spark.\n";
  $sparkMessage .= "For use, reply all and BCC rove2spark@withrove.com.\n";
  $sparkData = array("roomId"=>$createRoom->id
            ,"text"=>$sparkMessage
            );
  send_to_spark("post","messages",$sparkData);

  //Add email body to the room
  $emailBody = preg_replace('/&nbsp;/','',preg_replace("/[\r\n]{1,}/","\n",strip_tags(base64_decode($jsonData->body))));
  $sparkData = array("roomId"=>$createRoom->id
            ,"text"=>$emailBody
            );
  send_to_spark("post","messages",$sparkData);

    //Remove bot from room
    $getMembership = send_to_spark("get","memberships","personEmail=rove2spark@sparkbot.io&roomId=".$createRoom->id);
    $deleteMembership = send_to_spark("delete","memberships",$getMembership->items[0]->id);


  //Build HTML email response
  $httpResponse .= "The space \"".$roomName."\" has been created and members added.  ";
  $httpResponse .= "Follow up the conversation on <a href='https://web.ciscospark.com'>Cisco Spark</a>.<br><br>";
  $httpResponse .= "To use rove2spark, replay-all to an email thread and BCC rove2spark@withrove.com.<br>";
  $httpResponse .= "</body></html>";
} else {
  $httpResponse = "ERROR";
}
file_put_contents(getenv('res'), $httpResponse);

?>

Under the "Integrate" section of the function we want to set the mode to "Standard" and select "POST" as the only available HTTP method.

Building Bots with ROVE_HTTP method.png

Step 3: Build a Mailbox

Nothing fancy is needed here. Just an email box.

Step 4: Create a Flow

Here is an overview of the Flow we'll be building.

Building Bots with ROVE Create a Flow.png

In the Office365 web portal when logged in as the user go to Flow and then create a new Flow. Next we select what trigger is used to kick off this Flow. In our case when an email arrives.

Step 1

Step 1

Step 2

Step 2

Step 3

Step 3

Flow is used to add a basic outline for the email handling. First, we define when our flow is triggered. In our case, we are going to filter anything that hits our user's inbox, but we can get more specific if needed.

Building Bots with ROVE When a New Email Arrives.png

Next, we create a condition to check that our email bot is not in the To or CC field. If this happens, the bot would continue to build spaces every time someone hit reply all to an email thread which would decrease the willingness to use the bot pretty greatly. If they are not in the BCC field we end the flow by replying to the email explaining how to correctly use the bot and delete the email.

@not(contains(concat(triggerBody()?['To'], triggerBody()?['CC']), 'mail2spark'))

Building Bots with ROVE BCC Email.png

If the email passes that check then we build a HTTP step that triggers a REST API to our Azure Function. We take the email and send it as a json formatted post for our function to process.

Building Bots with ROVE Azure Function.png

To format the body, we use this long confusing string to concatename the different fields together and add formatting. Base64 encoding of the body protects us from any special characters and stuff that might mess with the json formatting.

concat('{

                   "to":"',triggerBody()?['To'],'",

                   "bcc":"',triggerBody()?['BCC'],'",

                   "cc":"',triggerBody()?['CC'],'",

                   "from":"',triggerBody()?['From'],'",

                   "subject":"',replace(triggerBody()?['subject'],'"',

                   "body":"',base64(triggerBody()?['Body']),'",),

'''"}')

The Azure Function will reply back with one of two responses. A simple "ERROR" response will tell flow to reply back with a generic email saying that the process failed and explaining how to use the bot. If the room has been built correctly, then the response will be an HTML formatted message that we will use to send as a Reply All to the original email thread.

Building Bots with ROVE Reply All Email Thread.png

At the end of each condition flow, we do some cleanup and mark the message as read and delete the original email which keeps our mailbox nice and clean.

Step 5: Test and Tune

At this point, your bot and email scripts should be functional.


MEET JON SNIPES, Senior Technical Consultant at ROVE

Jon Snipes Senior Technical Consultant at ROVE.jpg

After working as a butcher for several grocery chains in the region, Jon decided to make a career move and earned an Associates Degree in Network Administration. Since then he has gained focused experience with Cisco Collaboration products working for Cisco TAC on CME/CUE gateways and deploying collaboration solutions for Cisco Gold partners. In 2016, he completed his CCIE Collaboration. His focus is on Voice and Video deployments in complex call routing environments as well as developing applications to leverage Cisco APIs to fulfill advanced call routing needs and device/user provisioning.

You can find more of Jon's work at:

https://mycollablab.org

Comment

They Say it Takes a Village, Sometimes it Takes a Nation

Comment

They Say it Takes a Village, Sometimes it Takes a Nation

As many of us have our eyes on the news, our hearts break for the devastation that we see as Hurricane Harvey wreaks havoc through Houston and the surrounding area. In our ever increasingly fast paced world, that moment of heartache can be met with the distraction of a calendar meeting reminder, a call coming through, or a coworker's voice calling your name. When a tragic event seems so far away, yet so close to home, I'm grateful to live an age of technology that allows me to reach out from right where I'm at.  

Below are some options on how you can provide relief to the families in Houston from your desk today, or from your dinner table with your family tonight. These are only two of many options to make an impact, so if you have time, do a little bit of research to see which global or local charity may make the most heartfelt contribution to you!

Salvation Army

As Hurricane Harvey causes widespread damage across Texas, The Salvation Army is ready to provide physical and emotional care to survivors and relief workers. Salvation Army disaster teams from across the country are mobilizing and, even after disaster response efforts are over, The Salvation Army will remain in communities impacted by this terrible storm, supporting long-term disaster recovery efforts and providing ongoing assistance to those in need.  Click here

American Red Cross

The American Red Cross is helping the people affected by Hurricane Harvey in Texas and all across the Gulf coast. Shelters are open, truck loads of supplies are being distributed and volunteers in place.  Click here

Thank you to all the first responders and individuals who have their hands full in Houston, and to all those that are helping equip them with the resources and care that those affected by Hurricane Harvey need the most!

 

Nicole White, Marketing & CRM Lead

@nicole_d_white

Comment

Accelerate Container Deployment Testing with Azure Container Instances

Comment

Accelerate Container Deployment Testing with Azure Container Instances

Microsoft recently announced a new service called Azure Container Instances. This is an amazing offering that is now part of the Microsoft Azure lineup.  Azure Container instances provides Azure consumers with a simple and fast way to deploy containers for testing and development of applications.  There is no longer a need to learn complex programing modules to configure containers.  MS Azure Containers also allows the bursting and scaling of container instances as well as flexible billing such as per second billing.

In this blog post, I am going to show you how easy it is to get your first test container operational using Azure Container Instances. First thing’s first, we need to launch our MS Azure Portal with our assigned credentials:

CLICK TITLE TO READ MORE...

Comment

ROVE Achieves Advanced Security Architecture Specialization from Cisco

Comment

ROVE Achieves Advanced Security Architecture Specialization from Cisco

ROVE a Security Integrator, announced today that it has achieved the Advanced Security Architecture Specialization from Cisco. This specialization recognizes ROVE for fulfilling the requirements to sell, design and deploy comprehensive Cisco® Security Architecture solutions.

Certification indicates that ROVE has invested in the training required to deliver differentiated business value through the integrated, open foundation of the security architecture. Cisco Advanced Security Architecture Specialized Partners work with new and existing technologies to align components of this architecture with their customers’ strategic goals, helping transform business processes, boost organizational efficiency and accelerate the time to market.

To see how ROVE can provide these services to your organization, contact info@withrove.com.

Comment

Are you ready? Cisco Live 2017!

Comment

Are you ready? Cisco Live 2017!

Hey everyone!   The dynamic Cisco Champion duo of Paul Campbell (@paulmc3) and Robert Hawley (@writeerase) are heading out to Cisco Live again this year representing ROVE!

Did you catch our recap from 2016?  If not, click here! This year we're going to switch it up a little bit and post a daily blog update highlighting the news of the day as best we can!

Now, down to business! Last year was my first Cisco Live and I learned a lot.  I'd like to provide 5 top tips for Cisco Live from my perspective.

CLICK TITLE TO READ MORE...

Comment

Netapp! Welcome to the HCI Party!

2 Comments

Netapp! Welcome to the HCI Party!

As if the hyper converged market wasn’t already crowded enough with offerings from EMC, Cisco, Nutanix, and Simplivity, NetApp has finally thrown their hat into the ring today with a SolidFire based solution.  In my opinion SolidFire is an awesome product and I am happy to see NetApp finally doing more with it post-acquisition.  Based on the messaging and configuration options it is apparent they are targeting enterprise-scale workloads instead of edge use cases. 

Let’s dig in.

CLICK TITLE TO READ MORE...

2 Comments

1 Comment

Integrate Fortinet Firewalls to enhance Cisco ACI security

Welcome to a quick blog about enhancing your Cisco ACI security by integrating Fortinet Firewalls through L4-L7 service insertion.  

First, let's take a look at the topology we want to setup (pictured below, who doesn't like pictures?).  Underneath a single tenant and single VRF, we have two separate bridge domains called LAB_DATA and FortiTest.  LAB_DATA has three EPGs, and FortiTest has only one.  Underneath LAB_DATA's bridge domain we have two subnets configured.

CLICK TITLE TO READ MORE...

1 Comment

Physical Server Protection with Rubrik

Comment

Physical Server Protection with Rubrik

Rubrik within a VMware environment has always been an easy sell. The product demos well and customers respond positively to how easy it is to set up and manage.  As with many other Virtualization focused data protection products however, protecting physical servers that still exist has been an issue.  As a result, many organizations use a secondary set of backup tools to handle the physical servers or an overly complex solution that does both physical and virtual.  As IT organizations search for simplicity and a better way to protect their data, Rubrik is definitely delivering.  As a former backup administrator, I always had to choose the backup product that stunk less and was never really impressed with any of the options that I had. I’m not sure it’s possible to make data protection sexy, but Rubrik gets REALLY close.

CLICK TITLE TO READ MORE...

Comment

Cisco CloudCenter Summary

Comment

Cisco CloudCenter Summary

had the opportunity to attend a 4 day partner Cisco Cloudcenter (formerly known as CliQr) class. For those not familiar with CloudCenter, it is an Application-Defined Cloud Management Platform that allows users to easily deploy and manage any application on any supported cloud, (private, AWS, Azure, Google, etc.)

CloudCenter has a simple architecture that consists of 2 primary components:

CLICK TITLE TO LEARN MORE...

Comment

Goodbye VGA & HDMI Cable! Wireless DESKTOP Sharing is now available with Cisco Spark!

Comment

Goodbye VGA & HDMI Cable! Wireless DESKTOP Sharing is now available with Cisco Spark!

We’ve been able to use Cisco’s Wireless Proximity feature for quite some time on Telepresence room systems registered to on-premise infrastructure (Unified Communications Manager or VCS) to share content (desktop screen, power point presentations, etc.), but this has been a much-requested feature for those of us who have taken the plunge into the world of Cisco’s cloud-based telephony platform called Spark.  Removing clutter from the conference room table top has been a goal of all our customers who are fed up with VGA and HDMI cables strewn all over the place.  A cable for sharing content has been required with room endpoints registered to the Spark service … until now!

CLICK TITLE TO READ MORE...

Comment

Member Login
Welcome, (First Name)!

Forgot? Show
Log In
Enter Member Area
My Profile Not a member? Sign up. Log Out