Tuesday, August 28, 2007

Automating Outlook with Ruby: Inbox & Messages

In response to my series on Automating Outlook with Ruby, several readers have asked about accessing the Inbox and managing messages.

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 = WIN32OLE.new('Outlook.Application')

Next we'll get the MAPI namespace:

mapi = outlook.GetNameSpace('MAPI')

To get a reference to the Inbox folder, call the MAPI object's GetDefaultFolder method, passing it the integer 6, which represents the Inbox folder:

inbox = mapi.GetDefaultFolder(6)

To get the Personal Folders object, call the MAPI object's Folders.Item method, passing it the name of the folder.

personal_folders = mapi.Folders.Item('Personal Folders')

To reference a subfolder, call the parent folder object's Folders.Item method, passing it the name of the folder.

baseball_folder = personal_folders.Folders.Item('Baseball')

You can get a count of a folder's unread items by calling the UnreadItemCount method:

puts "#{inbox.UnreadItemCount} unread messages"

A folder object's Items method returns a collection of message objects, which you can iterate over:

inbox.Items.each do |message|
# Your code here...
end

You can also pass the Items method a (1-based) index to retrieve a single message:

first_message = inbox.Items(1)

Once your code tries to access methods and properties of a Message object, 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.

Message objects have dozens of methods/properties, including:

SenderEmailAddress
SenderName
To
Cc
Subject
Body

To see a complete list, you could call the ole_methods method, as explained here. So to view a sorted list of the Message object's methods and properties, we could do this:

methods = []
inbox.Items(1).ole_methods.each do |method|
methods << method.to_s
end
puts methods.uniq.sort

To delete a message, call its Delete method:

message.Delete

To move a message to another folder, call its Move method, passing it the folder object:

baseball_folder = personal_folders.Folders.Item('Baseball')
message.Move(baseball_folder)

So, if we wanted to check our Inbox and move all messages that contain 'Cardinals' in the subject line to our 'Baseball' folder, we could do something like this:

inbox.Items.Count.downto(1) do |i|
message = inbox.Items(i)
if message.Subject =~ /cardinals/i
message.Move(baseball_folder)
end
end

As reader Ana points out, we should use the Count and downto methods to ensure that our inbox.Items index stays in sync, even as we move messages out of the Inbox. Otherwise, we run the risk of a message being skipped when the message above it is moved or deleted.

That concludes our program for today. Feel free to post a comment here or send me email with questions, comments, or suggestions.

Digg my article

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 = WIN32OLE.new('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
end

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
end
end

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

Wednesday, August 22, 2007

Windows Developer Power Tools

While taking a brief respite from tutorialism and browsing the stacks at Barnes & Noble recently, I stumbled across Windows Developer Power Tools, an O'Reilly book by James Avery and Jim Holmes that covers over 170 free tools for Windows developers.

I've only scratched the surface thus far, but have already begun using several of the tools mentioned in the book, including SQLite Administrator, SharpDevelop, and Snippet Compiler. Some tools are .NET-specific, but many more are not.

The companion web site is here.

If you work with SQLite, my personal favorite database, you'll probably find SQLite Administrator quite helpful. It provides a GUI front end that allows you to create, design, and manage SQLite database files. Check out the website for full details and screenshots.

Digg my article

Wednesday, August 15, 2007

Automating Outlook with Ruby: Contacts

We've looked at sending email, working with calendar appointments, and creating and managing tasks with Outlook. Next we'll take a look at how to create new contacts and read contacts data from Outlook.

You know by now how this starts out: we'll use the win32ole library to create a new instance (or connect to a currently running instance) of the Outlook application object:


require 'win32ole'
outlook = WIN32OLE.new('Outlook.Application')

Next we'll get the MAPI namespace:

mapi = outlook.GetNameSpace('MAPI')

Creating a New Contact

To create a new contact, call the Outlook Application object's CreateItem method, passing it the number 2, which represents a Contact Item. This returns a new Contact object:

contact = outlook.CreateItem(2)

Then set values for various properties of the new Contact object:

contact.FullName = 'Stan Musial'
contact.CompanyName = 'St. Louis Cardinals'
contact.JobTitle = 'Hitter'
contact.BusinessTelephoneNumber = '(314)555-1234'
contact.Email1Address = 'stan_the_man@stlcardinals.com'

What properties are available to set? Dozens. To see a list, you could call contact.ole_methods, Google for it (Outlook Contact Properties), or use an OLE object browser.

When you've completed setting property values, call the Contact object's Save method:

contact.Save

Getting Existing Contacts Data

To obtain a collection of Contacts, call the MAPI object's GetDefaultFolder method, passing it the integer 10, which represents the Contacts folder. Then call the Items method on this object:

contacts = mapi.GetDefaultFolder(10).Items

You can now iterate over this collection of Contact objects, calling the methods/properties to get the data you need:

contacts.each do |contact|
puts contact.FullName
puts contact.Email1Address
puts contact.BusinessTelephoneNumber
end

For further information, check out these Microsoft TechNet articles:

Creating a New Contact in Microsoft Outlook
Exporting Contact Information

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