Sunday, August 26, 2007

Automating Outlook with Ruby: Address Books

We recently discussed working with Outlook Contacts. On a related note, a reader asked how to access the Outlook Address Books. So let's dive right in...

We start by using the win32ole library to create a new instance (or connect to a currently running instance) of the Outlook application object:

require 'win32ole'
outlook ='Outlook.Application')

Next we'll get the MAPI namespace:

mapi = outlook.GetNameSpace('MAPI')

The MAPI object's Session.AddressLists method, when called without parameters, returns a collection of the various Address Books available to Outlook, such as "Contacts", "Personal Address Book", and "Global Address List". The following code iterates over this collection and prints the name of each available Address Book:

mapi.Session.AddressLists.each do |list|
puts list.Name

To work with a particular Address Book, call the MAPI object's Session.AddressLists method and pass it the name of the Address Book:

address_list = mapi.Session.AddressLists('Global Address List')

This returns a single AddressList object. Call this object's AddressEntries method to obtain a list of AddressEntry objects:

address_entries = address_list.AddressEntries

Upon executing the above line of code, an Outlook security dialog will prompt the user to allow access to Address Book entries. The user must click a checkbox to allow access and select a time limit between 1 and 10 minutes.

Once access to the Address Book entries has been granted, you can iterate over the AddressEntries collection and get the Name and Address for each entry, or only for entries that meet certain criteria:

address_entries.each do |address|
if address.Name =~ /Machiavelli/
name = address.Name
email_address = address.Address

To search for an Address, you could call the AddressEntries collection's Item method. This accepts an integer as a (1-based) index:

address_entry = address_entries.Item(27)

...but also accepts a text string:

address_entry = address_entries.Item("sinatra, f")

This seems to return only the first AddressEntry object that meets the text string criteria. If no AddressEntry meets the text criteria, it seems to return the closest item following. So don't assume that the object returned meets your search criteria -- check the Name and/or Address properties to be certain.

There you have it. As always, feel free to post a comment here or send me email with questions, comments, or suggestions.

Thanks for stopping by!

Digg my article


Emmanuel said...

How about deleting mail / sending it to another folder?

I would like to script my inbox to filter out all the annoying SPAM that i get. I could analyze the mail header (subject, email address from the sender and maybe content) to determine if i have to move the mail to the spam folder or keep it on incoming.

Can this be done?


Dave said...

Very interesting. I have been looking at Ruby for a couple weeks but I had not considered using it with Microsoft Office programs.

I need a utility to go through all my in box folders and mark all the messages read.

A nice task for Ruby.

David Mullet said...

Emmanuel & Dave:

I've just posted a new article about managing your Inbox messages here.

I hope that helps you get a rolling start.

bodhi said...

Thanks for excellent articles. One question: Once I have the address_entry, can I get the status of the person?
Basically I want to know if there is a way to get if the resource is busy/free (from its calender)

Anonymous said...

Is it possible to access the alias similar to "Name"?

address_entries.each do |address|
if address.Alias =~ /someNiceAlias/
alias = address.Alias