Retrieving Debian Server Information VIA SMS with Google Voice

This my little project to retrieve information from my home server via text. The basic structure of this is: SMS Google Voice number with commands and an identifier (like a password) >> Set Google Voice to forward all SMS to email >> use a user crontab and getmail on the server to check for mail every minute (or other user defined amount of time) >> If there’s an email, a script looks for the Identifier >> figure out the information wanted >> use a ruby script to send text.

The Prerequisites:

sudo apt-get install ruby1.8 getmail4 curl

Setting Up Google Voice and Gmail

Personally I created a new account for this because both getmail and the Google SMS script require saving your username and password in an un-encrypted text document. Go to your Gmail settings >> Forwarding and POP/IMAP and change “2. When messages are accessed with POP” to “archive Gmail’s copy”.

Then go to voice.google.com and set up a new number for Google Voice to use. Go to settings >> Voicemail & Text >> and ensure that ” Forward text messages to my email” is checked.

Configuring Getmail

My guide for this part is based on this tutorial. First create a folder called “mail” under your home directory along with four sub folders : “bak”, “cur”, “new”, “tmp”.

mkdir mail ; mkdir ~/mail/bak ; mkdir ~/mail/cur ; mkdir ~/mail/new ; mkdir ~/mail/tmp

This is where the SMSs (In the form of emails) will be stored. Then create a folder under home called “.getmail”

mkdir ~/.getmail

In this folder create a text file named “getmail.gmail”

touch getmail.gmail

Open this with your favorite text editor

nano ~/.getmail/getmail.gmail

And fill it in with the following (note: you must supply your Gmail username and password at this point):

[retriever]
type = SimplePOP3SSLRetriever
server = pop.gmail.com
username = YOURUSERNAME@gmail.com
password = YOURPASSWORD

[destination]
type = Maildir
path = ~/mail/

[options]
# print messages about each action (verbose = 2)
# Other options:
# 0 prints only warnings and errors
# 1 prints messages about retrieving and deleting messages only
verbose = 2
message_log = ~/.getmail/gmail.log

Setting Up the Scripts

I use two scrips. One that’s written in bash that recieves and interprets the SMS and one that’s written in ruby and sends out the SMS. The ruby script is written by Brett Terpstra over at http://brettterpstra.com. You can find the tutorial for this script here.

I created a folder called .text under my home directory to put these two scripts.

mkdir ~/.text

Name the first one voicemail.sms

#!/usr/bin/env ruby -Ku

require 'net/http'
require 'net/https'
require 'open-uri'
require 'cgi'
require 'optparse'
require 'jcode' if RUBY_VERSION < '1.9'

ACCOUNT = 'YOURGMAILACCOUNT' # Set to Google Voice account email for default account
PASSWORD = 'YOURPASSWORD' # Set to Google Voice account password for default account
NUMBERS = ['+1555444333','+1555444222'] # Set one or more numbers for default destination(s)

options = {}
optparse = OptionParser.new do|opts|
opts.banner = "Usage: voicesms.rb -n +15554443333[,+15554442222] -m \"Message to send\" [-u Username:Password]"

options[:numbers] = NUMBERS
opts.on( '-n', '--numbers NUM[,NUM]', 'Phone numbers to SMS (separate multiples with comma)' ) do|numbers|
options[:numbers] = numbers.split(',')
end

options[:message] = false
opts.on( '-m', '--message MESSAGE', 'Message to send' ) do|msg|
options[:message] = msg
end

options[:username] = ACCOUNT
options[:password] = PASSWORD
opts.on( '-u', '--user USERNAME:PASSWORD', 'Google Voice username and password' ) do|creds|
parts = creds.split(':')
options[:username] = parts[0]
options[:password] = parts[1]
end

opts.on( '-h', '--help', 'Display this screen' ) do
puts opts
exit
end
end

optparse.parse!

unless options[:message]
puts "Message required. Use -m \"MESSAGE\"."
puts "Enter `voicesms.rb -h` for help."
exit
end

def postit(uri_str, data, header = nil, limit = 3)
raise ArgumentError, 'HTTP redirect too deep' if limit == 0
url = URI.parse(uri_str)
http = Net::HTTP.new(url.host,443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
response,content = http.post(url.path,data,header)
case response
when Net::HTTPSuccess then content
when Net::HTTPRedirection then postit(response['location'],data,header, limit - 1)
else
puts response.inspect
response.error!
end
end

def getit(uri_str, header, limit = 3)
raise ArgumentError, 'HTTP redirect too deep' if limit == 0
url = URI.parse(uri_str)
http = Net::HTTP.new(url.host,url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
response,content = http.get(url.path,header)
case response
when Net::HTTPSuccess then content
when Net::HTTPRedirection then getit(response['location'],header, limit - 1)
else
response.error!
end
end

data = "accountType=GOOGLE&Email=#{options[:username]}&Passwd=#{options[:password]}&service=grandcentral&source=brettterpstra-CLISMS-2.0"
res = postit('https://www.google.com/accounts/ClientLogin',data)
if res
authcode = res.match(/Auth=(.+)/)[1]
header = {'Authorization' => "GoogleLogin auth=#{authcode.strip}",'Content-Length' => '0'}
newres = getit('https://www.google.com/voice',header)
if newres
rnrse = CGI.escape(newres.match(/'_rnr_se': '([^']+)'/)[1])
#rnrse = CGI.escape(newres.match(/'_rnr_se': '([^']+)'/)[1])
options[:numbers].each {|num|
data = "_rnr_se=#{rnrse}&phoneNumber=#{num.strip}&text=#{CGI.escape(options[:message])}&id="
finalres = postit('https://www.google.com/voice/sms/send/',data,header)
if finalres["ok"]
puts "Message sent to #{num}"
else
puts "Error sending to #{num}"
end
}
else
newres.error!
end
else
res.error!
end

Then make a text file called smartpi.sh and copy these contents in to it.

#!/bin/bash
# A program to listen for SMS, with the aid of crontab, from Google Voice and
#reply with some system, internet, or other data

#Uses a getmail script to grab emails
getmail -r ~/.getmail/getmail.gmail

#Checks for mail and if there is none it doesn't run the rest of the script.
if [ -f ~/mail/new/* ]
then

#Removes and recreates any old tmp file if ones exists
if [ -f ~/.text/tmp ]
then
rm ~/.text/tmp
echo "Deleted Old tmp File"
touch ~/.text/tmp #Recreates tmp
fi

#Searches incoming mail for a the string ##! which denotes the message intended for
#recieving. Saves output to the previously created tmp file.
cat ~/mail/new/* | grep -m 1 '##!' >> ~/.text/tmp

#Defines TEXTER as the sender of the text
TEXTER=$(grep "SMS from" ~/mail/new/* | grep -o [0-9] | tr -d '\n')

#--------------------------------#
#BEGIN USER DEFINED TEXT VARIABLES
#--------------------------------#

#If ip is contained in the text store the ip to tmp
if grep -q ip ~/.text/tmp
then
curl icanhazip.com >> ~/.text/tmp
fi

#If date is contained in the text store it to tmp
if grep -q date ~/.text/tmp
then
date >> ~/.text/tmp
fi

#If space is contained in the text store it to tmp
if grep -q space ~/.text/tmp
then
df -h / >> ~/.text/tmp
fi

#If who is contained in the text store it to tmp
if grep -q who ~/.text/tmp
then
w >> ~/.text/tmp
fi

#If uptime is contained in the text store it to tmp
if grep -q who ~/.text/tmp
then
uptime >> ~/.text/tmp
fi

#-------------------------------#
#END USER DEFINED TEXT VARIABLES#
#-------------------------------#

#Stores the contents of tmp to SMS
SMS=$(cat ~/.text/tmp)

#Backs up emails to ~/mail/bak
mv ~/mail/new/* ~/mail/bak/

#Uses a ruby script to send a $SMS if there is new mail
ruby ~/.text/voicesms.rb -n +"$TEXTER" -m "$SMS"
fi

To copy these with formatting you can get them at:

get.letscollage.com/smartpi.sh

get.letscollage.com/voicesms.rb

Make sure to put your email address and password in the voicesms.rb!

From here you just need to make a cron job to process this script at given times.

Type:

crontab -e

and add the line :

* * * * * sh ~/.text/smartpi.sh

This will check for new texts once a minute. if you want to make that time longer simply add a /<number of minutes to check> to the first asterisk. So every five minutes would be:

*/5 * * * * sh ~/.text/smartpi.sh

And you should be set up to send commands to your server via text message! To set up your own commands use this template:

if grep -q KEYWORD_FOR_COMMAND ~/.text/tmp
then
COMMAND_TO_OUTPUT &gt;&gt; ~/.text/tmp
fi

Where KEYWORD_FOR_COMMAND would be something like “whatdayisit?” and the COMMAND_TO_OUTPUT would be the BASH command “date”. Put your snippet of code in the “DEFINE USER VARIABLE” section of smartpi.sh.

Another thing to note is I use ##! to denote to the smartpi.sh this is a text that I want a reply to. This serves two purposes: one is to filter out the line of the email that it important to me (using grep); two is to make sure no one can just send texts to my server and get replies, it acts as sort of a password. If you want to change this just change the ##! in line 22.

If you have any questions feel free to reply here!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s