Google Voice Command Line Script
by trixter on Jul.28, 2009, under Telephony
UPDATE: Aug-20-2009 I added the ability to use a ~/.netrc file (if Net::Netrc is installed, if its not it will not use that
I also fixed the meta following problem. Fixed a couple other bugs – like the username/pass incorrect not reporting that error properly. You should upgrade to the new version now.
UPDATE: Sept-10-2009 I added the ability to send calls/sms messages to named contacts. It will use your google voice contact data, so if you want to use this feature you have to create a contact in google voice and use the nickname that you gave them. I changed the way arguments are passed, run the program for usage information. If you were already using this you will have to adjust how you call the program.
I wrote a perl script that lets you interface with your Google Voice account. You can place a call, cancel a call, and send a SMS message easily. This is ideal for people that want to send SMS messages for system alerts, or for other reasons.
In order to use this script you must first download it. Then edit the username, password and default number variables near the top of the script. Install any missing perl modules based on whatever distribution you have, if you run the script it will tell you what it is missing. Invalid args or no args will give you a help screen.
To send an SMS message to 12345678
./googlevoice.pl sms 12345678 this is a test sms message
To place a call to 12345678 (optionally set the ‘forwarding number’)
./googlevoice.pl call 12345678
./googlevoice.pl call 12345678 90123456
To cancel a call placed through the web (or this script)
./googlevoice.pl cancel
In the future I may access the HTTP based inbox so that you can periodically check for messages, and react to triggers on them. In order to do this you would access the following URLs. If anyone is bored I will gladly accept patches to my script to add this functionality.
Inbox XML:
https://www.google.com/voice/inbox/recent/inbox/
Starred Calls XML:
https://www.google.com/voice/inbox/recent/starred/
All Calls XML:
https://www.google.com/voice/inbox/recent/all/
Spam XML:
https://www.google.com/voice/inbox/recent/spam/
Trash XML:
https://www.google.com/voice/inbox/recent/trash/
Voicemail XML:
https://www.google.com/voice/inbox/recent/voicemail/
SMS XML:
https://www.google.com/voice/inbox/recent/sms/
Recorded Calls XML:
https://www.google.com/voice/inbox/recent/recorded/
Placed Calls XML:
https://www.google.com/voice/inbox/recent/placed/
Received Calls XML:
https://www.google.com/voice/inbox/recent/received/
Missed Calls XML:
https://www.google.com/voice/inbox/recent/missed/
60 Comments for this entry
4 Trackbacks / Pingbacks for this entry
-
VoIP IP Telephony
September 5th, 2009 on 3:50 amTalk Perl To Google Voice…
I found a perl script that can send SMS messages via Google Voice. So now I have this script on my experimental severs (and on a central watchdog server for permanent servers) that alerts me via SMS through Google Voice….
-
gDial Pro - Google Voice App - Page 46 - PreCentral Forums
September 10th, 2009 on 3:42 am[...] out what he's doing. Looks like ?pearl? and I'm not too familiar with that programming language. Google Voice Command Line Script | 0xdecafbad.com looks like he seems to have gotten it to work, now just to figure out how [...]
-
gDial Pro - Google Voice App - Page 47 - PreCentral Forums
September 10th, 2009 on 6:40 pm[...] out what he's doing. Looks like it's written in perl and I'm not too familiar with that language. Google Voice Command Line Script | 0xdecafbad.com looks like he seems to have gotten it to work, now just to figure out how I can probably [...]
-
Mark Waters (mark) 's status on Saturday, 03-Oct-09 16:08:53 CEST - microblog
October 3rd, 2009 on 6:09 am[...] Voice Command Line Script | 0xdecafbad.com – http://www.0xdecafbad.com/?p=87 #bash #command line #google #perl #shell a few seconds ago from [...]

August 12th, 2009 on 1:44 pm
I am working on modifying your script to do inbox calls. So far I’ve got the post processing of the raw JSON in a shell script so I need to port it into the perl code. I tried using the perl JSON parser library, but it turns everything into nested hashes that are a pain to deal with, at least for me. I’m also going to set it up to call the Prowl perl client for iPhone push notifications.
August 12th, 2009 on 1:58 pm
That would be nice. I will integrate your patches if you submit them to me when you are done, or as you get different stages completed.
I am unfamiliar with prowl, so I do not know what changes it would require. I am sure that there is a way to make that optional for non iphone users.
August 14th, 2009 on 6:14 am
A bug have to be fixed in line 130:
$rnr_se = uri_escape($1);
My rnr_se has some especial symbols such as / and + . These have to be translated using the URI escapes.
Great job.
August 14th, 2009 on 8:41 am
Thanks, I added the patch.
August 18th, 2009 on 11:12 am
ERROR: Unable to get the rnr_se value
root@plugcomputer:~#
August 18th, 2009 on 12:36 pm
When script submits authentication form Google sends intermediate page which uses a meta refresh, meaning that the destination URL is in a tag, which WWW::Mechanize doesn’t follow. I had to add this line to get it to work:
$mech->follow_link(tag => ‘meta’); right after line: $mech->click(); in sub auth
Really nice script
August 18th, 2009 on 3:49 pm
Apnjjj: are you using a non US IP address? I have only seen that if its used from outside the US, since right now its only a US (maybe Canada) offering, google redirects and does not let you login.
August 18th, 2009 on 3:51 pm
I will add that, but I did not know that it was required. I have not noticed any problems, since the whole point of the authentication is to just get the rnr_se value and set a cookie. Is the rnr_se not getting read as a result? I will add it anyway because I do not think it will harm anything, and it may help some people.
August 19th, 2009 on 2:48 am
Actually I’ve setup my Google Voice in US, but right now I’m abroad and that is probably why I get this intermediate page with redirect before the main page loads.
Before I added this line: $mech->follow_link(tag => ‘meta’); I also got this “ERROR: Unable to get the rnr_se value”
As you said it shouldn’t cause any problems and will allow to use the script regardless of location.
August 19th, 2009 on 5:02 pm
I had to comment out $mech->follow_link(tag => ‘meta’); in sub auth for it to work on my box.
thanks trixter… you have denied me the pleasure of trying to write my own gvsms utility.
-shyft
August 19th, 2009 on 5:18 pm
shyft: you can always extend it to support boxes so you can process received SMS messages, automagically deal with voicemails, etc.
I will work on making that a conditional, it seems some people require it, others dont.
August 20th, 2009 on 12:15 am
there should be some fixes in the newest version now. See the update notice at the begining of the post for notes on the new auth method which should make it more multi-user friendly.
August 27th, 2009 on 7:30 am
trixter: Yes I am using a Canadian IP address. I have no troubles logging into http://voice.google.com from it. (grandfathered from the grandcentral days)
August 27th, 2009 on 7:40 am
works now though with your new version!
August 27th, 2009 on 7:51 am
I should have clarified, google voice claims its only available to US/CA. Trying from Europe has caused a redirect and failure to access google voice. I havent tried for a couple weeks, but they were fairly adamant about breaking it (even if you already had an account and were on holiday) for people outside North America (I dont know about Mexico, which technically is part of North America).
September 4th, 2009 on 6:17 am
Can anyone confirm that Google Voice effective broke this script? I can’t seem to place any calls anymore, may have something to do with them removing their option of adding a different phone to ring.?
September 4th, 2009 on 7:20 am
been sending text messages to Europe all morning and I just placed a call and it went through.
Maybe it is your account that got closed due to overuse/abuse? Maybe it was a temporary failure? Did you edit the script in any way?
September 4th, 2009 on 12:41 pm
What Perl distribution do you recommend so that this runs properly?
September 4th, 2009 on 1:11 pm
I use the default that comes with eeebuntu. This is perl 5.10. I dont know that it matters, so long as you can install the various modules either from a package manager or via cpan. Are you having a problem with any particular distribution?
September 4th, 2009 on 5:02 pm
I’m not confident that I’m installing the modules properly.
I have 5.10. I’m not sure it matters either. I keep trying to install the additional modules, but I get a message saying it’s “impossible” to install. I figured that was a permissions issue, and trued installing from the root. Still, no dice.
I used a script along the lines of: cpan -i ; cpan -i ; etc. etc.
Could you suggest an order to install them?
September 4th, 2009 on 5:04 pm
Oooh, I had “modulename1″ and “modulename2″ enclosed in brackets (explaining why they didn’t show up on the last comment) to represent the modules.
September 4th, 2009 on 5:10 pm
I dont know what is going on. How I do it is either with apt-get when there is a module present or
perl -MCPAN -e ‘install WWW::Mechanize’
September 5th, 2009 on 3:52 am
Thanks Trixter,
This is so great. I am using it on several servers to send me SMS alerts!
September 5th, 2009 on 9:27 am
I have tried running the script on Ubuntu 9.04 and Debian 5.0 and get the same error :-
Can’t call method “url” on an undefined value at /usr/local/share/perl/5.10.0/WWW/Mechanize.pm line 713.
Any suggestions ?
Thanks
Mark Waters
September 5th, 2009 on 9:39 am
I use ubuntu 9.04, that is what I developed on. This makes me think that there is a variable that is not set right.
Can you email me your script (XXX your username and password only but make no other changes to what you have, if you used the .netrc way you dont have to edit it at all) at trixter AT 0xdecafbad.com so that I can see what is going on?
September 5th, 2009 on 9:44 am
sorry to be a nuisance , but after clearing everything out of the ~/.netrc file except the specific variables it seems to be working.
Thanks for your help (and script)
Mark Waters
September 14th, 2009 on 2:53 pm
Have you put this under a license? I would like to use this in a software project that I hope to release.
September 14th, 2009 on 5:01 pm
Yes, the script is under the MPL (Mozilla Public License), which will be the first 50 or so lines of the script (comments).
Basically this means that you cannot make it part of a GPL project, but can LGPL, BSD, MPL, or pretty much anything except GPL.
September 18th, 2009 on 7:33 pm
Has anyone here tried to integrate this script into asterisk?
If so, is there a tutorial somewhere I might could read.
Thanks
September 18th, 2009 on 8:03 pm
Integrating into asterisk would depend on what you want to do. If for example you wanted to be able to send SMS messages via XMPP/Simple (sip instant messaging) it would not be trivial at all. If you just wanted to send a message, you could use the system command.
With FreeSWITCH.org, a open source softswitch I think is better than asterisk (higher cps rate, higher concurrent call rate, *fully* RFC compliant SIP stack, TLS/SRTP, and an eventing system that dances circles around asterisk) it would not be that difficult to integrate this into a more unified solution. You would be able to receive a sip instant message, or xmpp (jabber/google talk) and send it off.
September 19th, 2009 on 1:11 am
Ok. Thanks for the reply. I got to browsing the code for my setup and figured it out. Just had to make sure all the cpan modules were installed and then modify my extensions_custom.conf. I was using the default pygooglevoice in PiaF distro, and it was giving me trouble. That’s when I found your site. I am looking at trying to squeeze my setup into a WRT54G or most likely a NSLU2. Do you think FreeSWITCH would run on this old 500Mhz P3 I am using now? (i know “where’d you did that outta the trash @)
September 19th, 2009 on 1:20 am
yes, FreeSWITCH will run on a system that old. It wont be able to do a lot of traffic, but it will run. FreeSWITCH works natively in windows, linux, osx, bsd, solaris, and others. It has even been ported to Windows CE by at least one person. It will run on the smallest of boxes (within reason) up to telcobridges.com gear.
When it comes to x86 type systems, if asterisk runs on it, FreeSWITCH will run on it with less cpu utilization at the same call volume.
November 14th, 2009 on 10:36 am
Is there somewhere i can get a tutorial or example on how to integrate this script into Freeswitch? I am gonna try freeswitch on my new server. I am trying to setup a couple extensions, sipgate, and Google voice for now.
November 14th, 2009 on 5:46 pm
this will allow to enable/disable phones:
###
# toggle phone
###
sub togglephone {
my ($phoneId, $enabled) = @_;
$cookiejar = HTTP::Cookies->new();
$rnr_se = auth($cookiejar);
if (!defined $rnr_se) {
return;
} else {
my ($url, $client, $request, $response, $postdata);
$client = LWP::UserAgent->new();
$client->agent(‘Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.11) Gecko/2009060308 Ubuntu/9.04 (jaunty) Firefox/3.0.11′);
$client->timeout(30);
$client->cookie_jar($cookiejar);
$url = ‘https://www.google.com/voice/settings/editDefaultForwarding/';
$postdata = “phoneId=$phoneId&enabled=$enabled&_rnr_se=$rnr_se”;
$request = HTTP::Request->new(POST => $url);
$request->content_type(‘application/x-www-form-urlencoded’);
$request->content($postdata);
$response = $client->request($request);
if ($response->is_success) {
print “Phone enabled/disabled\n”;
} else {
print “Could not enable/disable phone “.$response->status_line.”\n”;
}
}
return;
}
phoneId is an integer starting from 1
enabled is either 0 or 1
Best
VulK
November 14th, 2009 on 7:31 pm
Thanks I will merge this in soon. I plan on refactoring everything and making this a perl module so that it is easier for other people to use in their projects.
November 14th, 2009 on 7:35 pm
blue: afaik no there is not a tutorial. The way that I can easily see it working is to get a gizmo account (rumor is that google just bought them). Google will route via SIP through gizmo to you. If you see a X-googlevoice: true header then it came from google voice. I may be mistaken on the header itself, but it is something like that.
It is a bit klugy if you want to use this to place a call, you pick up your phone and dial, then your dialplan does a system call to execute the script and wait for the inbound googlevoice call, then it will do a uuid_bridge or something to bridge the two together. Alternatively you cna use a conference instead.
If you want to send a sms perhaps from a chat event you would need something that would see the chat event (event socket, lua or javascript etc) and then resend that via this script.
I have plans to make this a perl module which would make it far easier to make an event socket perl app that would directly send messages and such. I just have been lazy lately.
November 18th, 2009 on 3:26 pm
when i try to use the script i am getting
“Could not place the call 500 Internal Server Error” ?
has something changed?
Thanks
November 19th, 2009 on 1:11 am
it is still working for me. 500 is a google side error, this means that they either got malformed data from you, or they had problems of their own. Are you still experiencing problems? What country is the IP you are connecting to google from?
November 19th, 2009 on 1:41 pm
blue and trixster
re 500 Internal Server Error
google now wants a phoneType parameter, eg phoneType=2, posted to https://www.google.com/voice/call/connect/. Just add this to the $postdata string in subroutine placecall.
November 19th, 2009 on 1:46 pm
I will have to see if that breaks anything else. I do not have that and its working elsewhere, why I think that its a bit odd that its happening.
Thanks for the patch though!
November 19th, 2009 on 7:19 pm
trixster: it was still dying with the 500 error.
I added the phoneType parameter as Ronald said and it works now.
What are the values for phoneType? I just used =2 as in the previous post..
P.S.- I do thank you all for the help.
November 19th, 2009 on 8:03 pm
on the previous post i forgot to mention calls and IPs are US.
November 25th, 2009 on 8:10 am
THANK YOU Roland Walker! That phoneType=2 thing saved me a ton of time.
November 30th, 2009 on 8:36 am
I had to do the
$postdata = “outgoingNumber=$dst_number&forwardingNumber=$from_number&subscriberNumber=undefined&remember=0&_rnr_se=$rnr_se”. “&phoneType=2″;
modification to get it working again.
As long as I am posting something I might as well mention that I hacked in support for the Mac OS X keychain instead of using a saved password:
#
# OPTION 3
# Enable use keychain support
#
my $use_keychain = 1;
if ($use_keychain)
{
open (KEYCHAINITEM, “security 2>&1 find-generic-password -g -s ‘Google Services’|”);
while ()
{
/”acct”=”(.*)”/ and $username = $1;
/^password: “(.*)”$/ and $password = $1;
}
}
December 18th, 2009 on 2:26 am
Hi there,
Is there a way to use a proxy when posting to google voice website ?
If so, could you please point me the direction to achieve this ?
Thank you!
Tuga Cari
January 4th, 2010 on 7:14 pm
is this still in development? i can definitely utilize this script in my scripts! i wish there was a way to pull current inbox translations via an RSS feed.. oh well.
February 4th, 2010 on 2:58 am
john doe: my plan is to change this over to a perl module to make it easier to use. I am lazy though and have had other things consuming my time. As for pulling the inbox, I have given the url to get the JSON data, you just have to parse that (something I am open to accepting patches for). I parse some data like the contacts list but that is about it.
February 4th, 2010 on 3:00 am
tuga cari: I would have to add code that lets you use a proxy. I have been hesitant to do much with this until I change it over to a perl module making it easier to use in other programs. I have just been lazy lately.
February 4th, 2010 on 3:17 am
Geordie: thanks! I will work that in when I redo this as a perl module. until then the code is here for everyone else to get this working
yes I really am being lazy, even about moderating comments. sigh.
February 4th, 2010 on 3:21 am
I got the 500 error from a bad password/username. I am going to rework this, I think there is a bug that I fixed in other software that this came from (why I really wrote it, a silly bot on irc) but failed to fix it here because its just so easy to forget about this page.
I *think* that I failed to properly check for a valid login at one point. I plan on making sure that it all works when I convert it to a perl module, which I am thinking will be in a week or so. That should also make it a lot easier to extend it and to run it in a wider range of programs. It also means that the original program I wrote this for will be ported to use this instead. I may get a little froggy and write a php version suitable for a webpage, but I have not yet decided on that.