Using the Google Apps Profile API

Zurück zur Übersicht

As Google Apps reseller we develop applications to automate certain tasks in conjunction with Google Apps. For examples you can take a look at our Google Marketplace page. One of our products there is the Sync Shared Contacts tool which synchonizes LDAP/Active Directory entries to Domain Shared Contacts on the Google Servers. But contacts who have a user account for your Apps domain are not shown. Instead the user’s profile is shown. Since profiles and contacts are two different things we needed to add the synchronization for profiles as well. This is possible since Google released the Profile API for Apps Premier, Education and Partner Edition.

Since the Profile API is fairly new there are no profile classes for C# present yet. You can however use the Contacts API classes for profiles with a little bit of work. Here is how to do it:

To do anything with Google Apps API you have to get authenticated. The following example shows how to do this.

// "cp" is required for profiles
FeedService = new Service("cp", "COMPANY-PRODUCT-VERSION");
// if you don't set the ProtocolMajor to 3 nothing will work as expected
FeedService.ProtocolMajor = 3;
// Set your admin credentials
FeedService.setUserCredentials("admin@yourdomain.com", "password");
// get an Auth token for the future
string AuthToken = FeedService.QueryClientLoginToken();

The next step would be to retrieve some profile information. Lets get all profiles for starters. Receive the AtomFeed and then parse it into a ContactsFeed. Then remove unnecessary xml nodes.

string uriString = "https://www.google.com/m8/feeds/profiles/domain/yourdomain.com/full";
// Create a query
FeedQuery query = new FeedQuery(uriString);
// Query the service
AtomFeed profFeed = FeedService.Query(query);
// Write AtomFeed to MemoryStream
Stream memstream = new MemoryStream();
profFeed.SaveToXml(memstream);
memstream.Position = 0;
// create new ContacsFeed
ContactsFeed ProfilesFeed = new ContactsFeed(new Uri(uriString), FeedService);
// Parse the AtomFeed into the ContactsFeed
ProfilesFeed.Parse(memstream, AlternativeFormat.Atom);
// Clean Up
memstream.Close();
// We now have profiles as contacts. Remove unnecessary nodes from Feed
foreach (ContactEntry ae in ProfilesFeed.Entries)
{
ae.Categories.Remove(new AtomCategory("http://schemas.google.com/contact/2008#contact"));
}

We now have a lot of profiles to work on.
If you intend to set new email/postal addresses or phone numbers you should not forget to set a relationship. If you don’t you will get an error when your’re attempting to update the profile. Have a look at the following example. It shows how to add a primary Email address to the first profile in our list of profiles.

ContactEntry profile = ProfilesFeed.Entries[0];
newEmail = new EMail();
newEmail.Primary = true;
newEmail.Address = "account@yourdomain.com";
newEmail.Rel = EmailRel.work;
profile.Emails.Add(newEmail);

You can also add an postal address. You can use object attributes like Street, Postcode, etc. You should however also fill the FormattedAddress Attribute (and the relationship of course).

StructuredPostalAddress pb = new StructuredPostalAddress();
pb.Primary = true;
pb.Rel = ContactsRelationships.IsWork;
pb.Street = "Street 101">
pb.Postcode = "PO123";
pb.City = "City";
pb.Country = "US";
// You have to set the Formatted Address for Profiles!
pb.FormattedAddress = "Street 101, PO123 City, State";
profile.PostalAddresses.Add(pb);

Now that the profile is modified you can upload the changes to the Google servers. Use the following code snippet to do so.

profile.Update();

Although not covered in this artice I’d like to add that you can update multiple profiles at a time. The feature is called batch processing. Take a look at the API Documentation for more info.

Oh before I forget, these were the Google libraries that I used:

using Google.GData.Client;
using Google.Contacts;
using Google.GData.Contacts;
using Google.GData.Extensions;
using Google.GData.GoogleBase;

This article is based on the Google Data API Version 1.6.0.0.