How AppleScript Saved My Address Book

From the time I got my iPhone — over a year and a half ago — I have been trying to force myself to use Apples own native products, like Mail, Address Book, iCal, etc… It was my thinking that this would make life easier, integrating into the whole Mac-iPhone way of life.

The thing is, I haven’t used any of these products since the days of OS X 10.2. For a time I was using ThunderMail (way back in the day) and eventually the whole Google Suite of apps like Gmail and Google Calendar. So a little over 1.5 years back, I started looking into the migration from these web services to the desktop apps that OS X provides.

With apps like [BusySync][a_091223104130] (and ultimately [BusyCal][a_091223104201] which I now use over iCal and in conjunction with Google Calendar), getting my calendar off the web but still having “anywhere” access was easy enough. And I did, for the first time ever, succumb to the .mac/mobileme world so my information is fully mobile and accessible to me in any form I choose. I am all about redundancy when it comes to data.

Since Mail and Gmail now do IMAP — and do it fairly well — getting local with my mail has not been difficult by any stretch, but I have to admit, I just don’t like the way Mail does things. I never have and that’s why I stopped using it so many years ago. I can get used to it though, and I am trying… on and off.

But my real reason why, after the better part of two years, I haven’t managed to fully integrate into the Macisphere way of doing things is none of the above… It has been moving contacts that has been the biggest catch.

I stopped using the Apple suite of apps around 2002-2003, so it goes without saying that the contacts acquired since then is quite extensive. Gmail’s way of collecting those contacts is sort of a drag-net approach — someone sends you an email and Gmail does it’s best to add that person to your contacts list… at all cost, with little regard for their name or whether it’s a duplicate. After this many years Gmail has collected what it thinks are 10,000 unique contacts… uhhh… yeah. And there is no way to manage those contacts in any practical manner.

So with a slew of free tools, exports, imports and lots of crying I was able to cram those 10,000 contacts into Address Book… which promptly rendered Address Book utterly useless. Fortunately Address Book comes with a handy command to look for duplicates (Card > Look for Duplicates…) and then merges them and their relevant data together. Great. After running for the better bit of 5 hours, Address Book was able to cut that down to a smidge over 4,500 contacts. While this made the app a little more useful on my Mac (though still really slow), Contacts on my iPhone was still, more or less useless.

And this is the way I’ve left it for the last 18 months. Defeated, deflated and frustrated.

Enter AppleScript. Why I hadn’t thought of this earlier, I have no idea, but just a few days ago, while writing an AppleScript to send out all my Christmas E-Cards (which invariably makes use of Mail and Address Book) I thought I had better do something about Address Book once and for all.

I knew going into this that Address Book was full of duplicate information, but it was different enough that Address Book wasn’t able to tell. For instance, if a contact has a first name of “John” and a last name of “Reynolds”, Address Book can’t draw the similarity from another contact with a dubious first name of “John Reynolds” and no last name. Nor can it conclude that the contact with the first name “Reynolds” and last name “John” is likely the same as the first contact.

In addition to this mass confusion, in Address Book’s attempt to manage duplicate contacts, it merged nameless email addresses into thousands of other nameless email addresses creating countless, nameless contacts, each with dozens, if not hundreds of emails… sound confusing?

It was time for some bug guns… big scripting, non-discriminating guns.

**Before I go any farther, let me start by saying DO NOT TRY THIS AT HOME! YOU WILL CAUSE IRREVERSIBLE CHANGES TO YOUR CONTACTS IN ADDRESS BOOK! Unless you are certain you have this information backed up or stored elsewhere, or unless you are just as desperate as me and don’t care anymore, do not use these scripts!!!**

## Delete Nameless Entries ##

So first things first. I want to get rid of all the nameless, kludged together contacts that resulted from Address Book compiling nameless, and therefor what it deemed to be duplicate, contacts. This is what I came up with:

tell application "Address Book"
		set thePeople to every person whose first name is missing value and last name is missing value
		repeat with i from 1 to count of thePeople
			set thePerson to (item i of thePeople)
			delete thePerson
		end repeat
	end tell

[[get the up-to-date code snippet here][a_091223123541]]

AppleScript will tell Address Book to find all the contacts with no first or last name and delete them with no questions asked. If this scares you, DON’T USE IT. This cut down my contact list from 4,500+ to to about 2,300+. Good… better… but not great.

## Cleanup @ Entries ##

One thing I can’t stand is a contact with no proper name. You are nothing to me if all I have is your email address. It especially bothers me when a contact uses all or bits of their email address as the first and/or last name, like…

first name: john
middle name: @doe.
last name: com


first name:

So this next script looks for such contacts and indiscriminately wipes them out. If there is any question about whether the person really does have a proper first or last name, it will pause and ask… but for the most part it will just hack and slash with reckless abandon.

tell application "Address Book"
		set thePeople to (every person whose first name contains "@" or last name contains "@" or middle name contains "@")
		repeat with i from 1 to count of thePeople
			set thePerson to (item i of thePeople)
			set firstName to (first name of (item i of thePeople) as string)
			set lastName to (last name of (item i of thePeople) as string)
			set middleName to (middle name of (item i of thePeople) as string)
			set theirEmails to (value of email of (item i of thePeople) as string)
			set urlList to {"com", "net", "ca", "org", "uk", "us", "fr", "it", "edu", ".com", ".net", ".ca", ".org", ".uk", ".us", ".fr", ".it", ".edu"}

			if first name of (item i of thePeople) is missing value or last name of (item i of thePeople) is missing value then
				delete thePerson
			else if firstName contains "@" and lastName contains "@" then
				delete thePerson
			else if urlList contains lastName then
				delete thePerson
				display dialog "first name: " & firstName & return & "middle name: " & middleName & return & "last name: " & lastName & return & return & theirEmails buttons {"Cancel", "KEEP", "DELETE"} default button "DELETE" giving up after 30
				copy result as list to {the buttonReturned, the gaveUp}
				if gaveUp is true then error number -128
				if buttonReturned is "Canceled" then error number -128
				if buttonReturned is "DELETE" then delete thePerson
			end if
		end repeat
	end tell

[[get the up-to-date code snippet here][a_091223140548]]

## Detect Name Switch ##

The next step was to sort out how many contacts were actually duplicates, only with their first and last names reversed. It’s understandable that Address Book would think such entries were unique, but you’d think the error was common enough that it would have such provisions built in and at least ask you to review what it suspects might be duplicates. Since Address Book does nothing of the sort, I had to write an AppleScript that does.

The script is too long and complex show it all here, but basically what happens is AppleScript tells address book to look for contacts whose first and last names match those contacts whose last and first names are the same. It then prompts me with the comparative information and asks me to decide if they are in fact the same. If yes, then it asks me which one, if any, that I want to delete.

This process cut another several hundred more contacts from my list.

[[get the up-to-date code snippet here][a_091223131712]]

## Split First Name ##

Something else I found regularly when going through my contacts is entires where both the first and last name would be in the first name field and the last name field entry left empty. This would also produce a lot of undetectable duplicates as the comparison of `first name: John Doe` to `first name: John, last name: doe` would obviously yield two unique contacts.

This script will search for contacts whose first names contain a space and whose last name is not present. Going on the assumption that the first and last name are both contained in the first name (hence the space), the script takes the first word and the last word and uses them for a proper first and last name. Again, it does so rather blindly, so this contact `first name: Royal Bank of Canada` will become `first name: Royal, last Name: Canada`. I need not say this again… proceed with caution.

tell application "Address Book"
		set first name to first word in first name
		set last name to last word in first name
		set the thePeople to (every person whose (last name is missing value and first name contains " "))
		repeat with i from 1 to count of thePeople
			set theirName to (first name of (item i of thePeople))
			set firstName to (first word of theirName)
			set lastName to (last word of theirName)
			set properties of (item i of thePeople) to {first name:firstName, last name:lastName}

			set newFirstName to (first name of (item i of thePeople))
			set newLastName to (last name of (item i of thePeople))
		end repeat
	end tell

This process, when combined with another duplicate search from the Address Book card menu, managed to chop out another 500 contacts.

[[get the up-to-date code snippet here][a_091223143806]]

## And the Winner Is? ##

After beating Address Book over the head with these scripts various times and after running Address Books own duplicate check after each script run I was able to cut my number of contacts from Gmail’s initial 10,000, down to 4,500+ until finally I managed to walk away from the whole fight with a clean, organized Address Book containing 1,308 cards! Ahhh… victory!

So does this make me a happy user of the Apple office apps? It’s certainly got me closer. Now that I have an Address Book that is usable, I’m now using Mail on both the desktop and iPhone and am making a real effort to get used to them both.

[a_091223104130]: “BusyCal – Share Calendars on a LAN and sync with Google Calendar”
[a_091223104201]: “BusyCal – Share Calendars on a LAN and sync with Google Calendar”
[a_091223123541]: “Code Collector – View Snippet”
[a_091223131712]: “Code Collector – View Snippet”
[a_091223140548]: “Code Collector – View Snippet”
[a_091223143806]: “Code Collector – View Snippet”