Read Outlook Events via Python

Norfeldt picture Norfeldt · Jan 31, 2014 · Viewed 26.6k times · Source

Outlook has some things to desire - like showing multiple month view

So I decided to give it a try by pulling out the event data via python (and then figure a way to display it nicely). Google is giving me pore results, but stackoverflow has been very helpful previously in regards to using win32com and outlook.

My goals are the following

  • read a shared calendar
  • read the events information like start, end, subject, creater etc

I haven't got far, but this is what I got together (with inspiration from this site)

import win32com.client, datetime
from dateutil.relativedelta import relativedelta

Outlook = win32com.client.Dispatch("Outlook.Application")
ns = Outlook.GetNamespace("MAPI")

appointments = namespace.GetDefaultFolder(9).Items 
# TODO: Need to figure out howto get the shared calendar instead Default [9] 
# (I have placed the shared folder into a separate folder - don't know if it matters)
# I would just like the user to select which calendar to execute on
appointments.Sort("[Start]")
appointments.IncludeRecurrences = "True"
begin = date.today().strftime("%m%d%Y")
end = (date.today() + relativedelta( months = 3 )).strftime("%m%d%Y")
appointments = appointments.Restrict("[Start] >= '" +begin+ "' AND [END] >= '" +end+ "'")

From here I need help with looping through the events and read them. Any help is highly appreciated.

Answer

Andreas Fester picture Andreas Fester · Feb 3, 2014

From here I need help with looping through the events and read them.

Basically, all you have to do is to follow the COM API documentation from Microsoft. For example, the Restrict() method returns AppointmentItem objects which are documented at AppointmentItem Object for Outlook 2010. So, starting with a folder, you can get and list the appointments as follows:

# Get the AppointmentItem objects
# http://msdn.microsoft.com/en-us/library/office/aa210899(v=office.11).aspx
appointments = someFolder.Items

# Restrict to items in the next 30 days (using Python 3.3 - might be slightly different for 2.7)
begin = datetime.date.today()
end = begin + datetime.timedelta(days = 30);
restriction = "[Start] >= '" + begin.strftime("%m/%d/%Y") + "' AND [End] <= '" +end.strftime("%m/%d/%Y") + "'"
restrictedItems = appointments.Restrict(restriction)

# Iterate through restricted AppointmentItems and print them
for appointmentItem in restrictedItems:
    print("{0} Start: {1}, End: {2}, Organizer: {3}".format(
          appointmentItem.Subject, appointmentItem.Start, 
          appointmentItem.End, appointmentItem.Organizer))

Note that I had to use a slightly different time format for the restriction expression ("%m/%d/%Y" instead of "%m%d%Y"). The proper solution would be to use Outlook's Format function as documented at http://msdn.microsoft.com/en-us/library/office/ff869597(v=office.14).aspx, section Date. Note also that I was using Python 3.3, so you might have to use different functions to create the dates. In any case, for testing purposes, you can use a hard coded expression like "[Start] >= '02/03/2014' AND [End] <= '03/05/2014'"

To get a shared calendar, the following code should work - This is the usual sequence found in the API documentation, however I was not able to actually get it working, but this could be due to a different backend server (not using an Exchange server):

recipient = namespace.createRecipient("User Name")
resolved = recipient.Resolve()
sharedCalendar = namespace.GetSharedDefaultFolder(recipient, 9)

To show all available folders as a tree, you can use something like

def folderTree(folders, indent = 0):
    prefix = ' ' * (indent*2)
    i = 0
    for folder in folders:
        print("{0}{1}. {2} ({3})".format(prefix, i, folder.Name, folder.DefaultItemType))
        folderTree(folder.Folders, indent + 1)
        i = i + 1

...
folderTree(namespace.Folders)

To look up a folder by its path (e.g. to find the calendar folder "[email protected]" below the "Internet Calendars" folder), you can use something like

def findFolder(folders, searchPath, level = 0):
    for folder in folders:
        if folder.Name == searchPath[level]:
            if level < len(searchPath)-1:
                # Search sub folder
                folder = findFolder(folder.folders, searchPath, level+1)
            return folder
    return None

...
sharedCalendar = findFolder(namespace.Folders, ["Internet Calendars", "[email protected]"])

See also: