Filling Mac Address Book Pictures with Gravatars

[This information in this post is out of date. Please see Gravatar, AppleScript, and the OS X Address Book Revisited for more current information.]

This is a multi-part tutorial series on using Gravatar from AppleScript to update your Mac Address Book pictures automatically. These pictures then sync to your iPhone for Gravatar goodness on the go.

I’ve had some AppleScripts to work with Gravatars and Address Book hanging around in rough form for quite a while. But I was recently prompted to clean them up and write these tutorials when Matt Mullenweg posted about Gravatar on his blog saying that “we need a better way to get Gravatars into your Apple address book / iPhone.” I hope that the documentation and tools from this project will be used for other creative Gravatar integration projects.

We’re about to put all of what we learned in part 1, part 2, and part 3 together to make our working script. Be sure to check out the previous parts for the details of how it all works.

Here is the process the script will be doing:

  1. Get a list of only the selected contacts from Address Book. This way we can control which contacts get their pictures updated if we don’t want them all.
  2. Ask the user if we should overwrite any existing pictures or skip those contacts.
  3. Step through each of those contacts and get all of the e-mail addresses associated with each.
  4. Step through each e-mail address and download its Gravatar to a temporary file. If there is more than one address with a Gravatar we’ll keep it simple and just let it set each one in turn and we’ll end up with last one found. This could be improved in the future to favor a particular one if needed.
  5. Update the Address Book picture, delete the temporary file, then repeat the process with the next contact.

Here’s the script:

-- Set selected Address Book contact pictures from Gravatar.
-- Released under GPL.
-- by Doug Smith,

-- Grab the selected records and see how many there are.
tell application "Address Book"
	set selected_contacts to selection
	set count_selected to number of items in selected_contacts
	-- Bail out if there are no records selected. Otherwise ask about how to deal 
	-- with contacts having existing pictures.
	if count_selected < 1 then
		tell me to display dialog "You must first select some Address Book contacts." buttons {"Cancel"} default button 1 cancel button 1
		if count_selected = 1 then
			set plural to ""
			set plural to "s"
		end if
		tell me to set user_result to display dialog "We're about to try updating " & count_selected & " selected Address Book contact picture" & plural & " from Gravatar. Would you like to overwrite existing pictures or skip those contacts?" buttons {"Cancel", "Overwrite Existing", "Skip Existing"} cancel button 1 default button 1 with icon caution
		set overwrite to (button returned of user_result contains "Overwrite")
	end if
	-- Step through each contact and find Gravatars.
	with timeout of 600 seconds
		repeat with one_contact in selected_contacts
			if not ((image of one_contact exists) and not overwrite) then
				-- Step through the contact's e-mail addresses.
				set all_emails to emails of one_contact
				repeat with one_email_record in all_emails
					set one_email_address to value of one_email_record
					set grav_file to (my get_gravatar(my trim_email(one_email_address)))
					-- If we have a Gravatar image add it to the contact.
					if grav_file is not "" then
						set image of one_contact to my get_pict_data(grav_file)
					end if
				end repeat
			end if
		end repeat
	end timeout
	tell me to display dialog "Done. You may need to select a different record to force Address Book to refresh the screen before changes show." buttons {"Okay"} default button 1
end tell

-- Trim junk off the end of the e-mail address field. Assume space separated.
on trim_email(email_address)
	set AppleScript's text item delimiters to " "
	return item 1 of email_address
end trim_email

-- Look up a Gravatar from an e-mail address and save to a file.
on get_gravatar(email_address)
	-- Calculate an MD5 for the e-mail address.
	set md5_email to do shell script "md5 -q -s `echo " & email_address & " | tr '[:upper:]' '[:lower:]'`"
	-- Construct the Gravatar URL. Max Address Book picture size stored is 218 pixels.
	set grav_url to quoted form of ("" & md5_email & "?s=218&d=" & "%22%22" as text)
	-- Make a file name in which to temporarily save the Gravatar.
	set grav_file to (path to temporary items) & "gravatar" & md5_email & ".jpg" as text
	set grav_POSIX_file to quoted form of POSIX path of grav_file
	-- Download the Gravatar image to the temporary file with a timeout of 10 seconds.
	do shell script "curl " & grav_url & " -m 10 -o " & grav_POSIX_file
	tell application "System Events"
		if exists file grav_file then
			return grav_file
			return ""
		end if
	end tell
end get_gravatar

-- Read the picture data into a variable in TIFF format then delete the file.
on get_pict_data(grav_file)
	tell application "System Events"
		set file_ref to open for access grav_file
		set pict_data to read file_ref as "TIFF"
		close access file_ref
		delete file grav_file
		return pict_data
	end tell
end get_pict_data

There you have it. I have some ideas to take it further but I’ll let everyone test what we have and offer feedback before continuing. I’ll also make an easier to use application download for everyone once we’ve done enough testing to work out the kinks.

18 thoughts on “Filling Mac Address Book Pictures with Gravatars”

    1. I love your plugin. In fact, it’s what originally got me thinking about doing this project. I just wanted a way to update more than just one record at a time.

  1. i also thought about a mass-updating feature, but it just didn’t fit in my 20-minutes development time 🙂

    by the way, what percentage of your contacts do have a gravatar? i’m a bit frustrating that … not many people are using it, especially in business.

    1. Less than 10% of my contacts have a Gravatar, and many of those are my immediate family that I encouraged to get one.

      Now that I figured out how to programatically tell when Gravatar doesn’t have an image instead of getting a default image back (see my previous post in this series), I was thinking about checking other services as a fallback. I know I could pick up quite a few images for my contacts from Twitter and Facebook.

      Wouldn’t it be cool if Gravatar did that fallback for us? They could check a few other popular services and cache the result.

  2. though it sounds cool i wouldn’t appreciate gravatar checking other sources, as it simple nature is one of the fascinating things about it, at least from my point of view.
    i’m afraid the main problem indeed isn’t the existence of contact pictures somewhere but rather the ability to find these kind of things, so a good ( yet challenging ) solution would be a single service that just aggregates contact data, including a contact image, and provides this data. Privacy is the problem here i guess. But definitely a topic worth thinking about..

  3. I have to change:

    set grav_file to (my get_gravatar(my trim_email(one_email_address)))


    set grav_file to (my get_gravatar(one_email_address))

    in order for this to work.

  4. Thanks for the reports, Joost and Nick.

    The reason I included the trim_email is that I ran across people who stored notes after the actual e-mail address in Address Book. If you put text in parenthesis after the address, Address Book and Mail will strip it off when composing a message.

    Without the trim_email, any addresses with notes will calculate out to a wrong MD5 and will not be able to find the correct gravatar.

    I’d like to see if I can track down the problem and fix it so it will work in all cases. Were you getting any kind of error message before you made that change?

  5. Do you now of any script or Address Book plugin that would look for pictures in Google Images or Bing Images, and would propose to select one of the images coming back to replace the Address Book picture? (a little bit like those Apps that do it for Itunes)? Thx. As Google is indeed indexing Facebook images, it would be a very convenient way to do it.

    1. I’m not aware of anything that does that. That’s an interesting idea, though. I hadn’t realized Google was indexing those images. I was looking into expanding my script to also grab Twitter and Facebook images. I’ll have to consider what Google has too. Got any links for details about what they’re doing?

  6. Let me see if I can explain this easily…

    I have a large list (200-300) that I imported into address book. Worked great, I have all the information I need. The ‘note’ field contains the name of a JPG (A2299.JPG). I have all the JPG files. Is it possible to write a script that will combine the information in order to assign the picture to the correct contact? I realize it can be done manually, but I was hoping to automate. Thanks!

  7. There’s at least one iPhone app that will sync images from gravatar on the phone rather than on your desktop… called zync. If there isn’t a gravatar image you can choose from a variety of place-holder sets.

    1. Thanks for mentioning the iPhone app. I’ve tried a couple such apps, and unfortunately, don’t really like any all that well so far. I started working on one of my own back when the iPhone first came out. But my iPhone programming skills need to increase a bit more to make it a reality. 🙂

Leave a Reply