In the past importing Gmail contacts was a bit of a hassle. One of the previous options was to use the Contacts gem found at RubyForge. However, now that the Google Contacts API has been released, it offers a more secure (and hopefully reliable) way to retrieve contacts. The Contacts API allows redirecting and authenticating users through Google, instead of forcing them enter their Gmail password into a third party application. Here is a quick tutorial to get up and running in ruby on rails with the Gmail Contacts API.
First, you need to register your domain with Google. This can be as easy as uploading a temporary file to your domain’s root directory to verify control of the domain. The steps for doing this are clearly outlined at Registration for Web-Based Applications.
Once you’ve verified control of the domain with google, start making your requests! Grabbing the contacts is essentially a three step process:
- Initiate the authentication with Gmail. Send your user over to enter their credentials, after which Google passes back an AuthSub token valid for one request.
- Send back the one-time AuthSub token and exchange it for a long-lived token valid for multiple requests.
-
Use this second token to make requests to the Gmail Contacts API and import user’s Gmail contacts.
More detailed steps on how Google Authentication process works can be found at Authentication for Web Applications
Now lets visit the three steps above in more detail, and implement importing gmail contacts using ruby on rails!
1. First redirect your users to authenticate with Gmail and request a one-time use AuthSub token.
# initiate authentication w/ gmail # # create url with url-encoded params to initiate connection with contacts api # # next - The URL of the page that Google should redirect the user to after authentication. # scope - Indicates that the application is requesting a token to access contacts feeds. # secure - Indicates whether the client is requesting a secure token. # session - Indicates whether the token returned can be exchanged for a multi-use (session) token. # next_param = "http%3A%2F%2Fwww.example.com%2F" scope_param = "http%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds%2F" secure_param = "0" session_param = "1" root_url = "https://www.google.com/accounts/AuthSubRequest" query_string = "?scope=#{scope_param}&session=#{session_param}&secure=#{secure_param}&next=#{next_param}" redirect_to root_url + query_string
2. Trade your single-use token for the all powerful AuthSub session token.
require 'net/http' require 'net/https' token = params[:token] # received the single-use authsub token, exchange for authsub session token http = Net::HTTP.new('www.google.com', 443) http.use_ssl = true path = '/accounts/AuthSubSessionToken' headers = {'Authorization' => "AuthSubtoken="#{token}""} resp, data = http.get(path, headers) if resp.code == "200" token = '' data.split.each do |str| if not (str =~ /Token=/).nil? token = str.gsub(/Token=/, '') end end redirect_to "http://www.example.com/?token=#{token}" else redirect_to "http://www.example.com/" end
Note: There’s probably a better way to grab the above token from the response, if anyone would like to suggest a refactoring here please feel free . . .
3. Finally, grab your buddies!
# GET http://www.google.com/m8/feeds/contacts/default/base require 'net/http' require 'rexml/document' http = Net::HTTP.new('www.google.com', 80) # by default Google returns 50? contacts at a time. Set max-results to very high number # in order to retrieve more contacts path = "/m8/feeds/contacts/default/base?max-results=10000" headers = {'Authorization' => "AuthSubtoken="#{authsub_token}""} resp, data = http.get(path, headers) # extract the name and email address from the response data xml = REXML::Document.new(data) contacts = [] xml.elements.each('//entry') do |entry| person = {} person['name'] = entry.elements['title'].text gd_email = entry.elements['gd:email'] person['email'] = gd_email.attributes['address'] if gd_email contacts << person end
Hopefully that should help get you started on the right track. The Google Contacts API allows retrieval of other information besides simply name and email address. I’d be interested in hearing what else is everyone using/doing with this API?
Other Posts That Might Interest You

