Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Brett Terpstra's voicesms.rb command: send sms messages from the command line via google voice. Original here: http://brettterpstra.com/sms-from-the-command-line-with-google-voice/

View voicesms.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
#!/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 = '' # Set to Google Voice account email for default account
PASSWORD = '' # 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 = 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

2014
Getting an error:
versions/2.1.0/lib/ruby/2.1.0/net/http/response.rb:119:in error!': 403 "Forbidden" (Net::HTTPServerException)
from voicesms.y.rb:65:in
postit'
from voicesms.y.rb:85:in `'

I added three lines above this, so 85 is

res = postit('https://www.google.com/accounts/ClientLogin',data)

Presumably Google has made it more difficult/impossible to do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.