Reputation: 43
I'm getting some unexpected values returned from Exchange calendar items I'm iterating over in Python 2.6 via Outlook using COM. Outlook 2010 32-bit is being used on Windows 7.
The 6 items that were found and logged by the script can't be seen in Outlook when viewing the calendar. There are only 2 items in Outlook that should be seen by the script for 11/17/2014 after 2pm. The script was run at 2pm.
The shared or public folders have events that are in what are used as schedules for conference rooms. I don't know how the items are being created or how they're shared so I'm not sure what object types they are.
That's why the script I'm pasting below I wrote in a generic way and lacks any filtering using .Restrict(). I'm simply trying to "see" everything possible.
After the script code is the log output. Sorry for the verbose output and the long script, but I wanted to include all the different bits I've looked at in case it helps. I've looked at some other posts here on SO and elsewhere and have put together what's shown below. Some of the links are referenced below. Maybe it'll help others.
The end result I'm trying to achieve is to simply pull all the calendar items/events for the current day for "Room 1" through "Room 4".
The script:
import sys
import datetime
import logging
import win32com.client
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
log_formatter = logging.Formatter("%(asctime)s [%(levelname)-5.5s] %(message)s")
log_consolehandler = logging.StreamHandler()
log_consolehandler.setFormatter(log_formatter)
log.addHandler(log_consolehandler)
logfname = datetime.datetime.now().strftime('%Y%m%d-%H%M%S')
log_filehandler = logging.FileHandler('cal-%s.txt' % logfname, mode='a', encoding='utf-8')
log_filehandler.setFormatter(log_formatter)
log.addHandler(log_filehandler)
def convert_pytime_to_datetime(pytime):
# arg is type PyTime, str is "09/10/13 16:00:00"
return datetime.datetime.strptime(str(pytime), '%m/%d/%y %H:%M:%S')
def print_folders(folders, indent=0):
prefix = ' ' * (indent*2)
i = 0
for folder in folders:
log.info("{0}{1}. {2} ({3})".format(prefix, i, folder.Name, folder.DefaultItemType))
print_folders(folder.Folders, indent + 1)
i += 1
def find_folder(folders, search_path, level=0):
"""
Outlook = win32com.client.Dispatch("Outlook.Application")
mapi = Outlook.GetNamespace("MAPI")
cal = find_folder(mapi.Folders, ['[email protected]', 'calendar'])
cal = find_folder(namespace.Folders, ["Internet Calendars", "[email protected]"])
"""
for folder in folders:
name = folder.Name
if name.lower() == search_path[level].lower():
if level < len(search_path)-1:
# search sub folder
folder = find_folder(folder.folders, search_path, level+1)
return folder
return None
Outlook = win32com.client.Dispatch("Outlook.Application")
mapi = Outlook.GetNamespace("MAPI")
print_folders(mapi.Folders)
# filter/restrict items to date range
flt_delta = datetime.timedelta(days=30)
flt_start = datetime.datetime.now()
flt_end = flt_start + flt_delta
# don't use .Restrict() for now until we know we can "see" items properly
#restriction = '[Start] >= "' + flt_start.strftime('%m/%d/%Y') + '" AND [End] <= "' + flt_end.strftime('%m/%d/%Y') + '"'
#restrictedItems = appointments.Restrict(restriction)
# iterate through restricted AppointmentItems
#for appointmentItem in restrictedItems:
#target_folder = ['[email protected]', 'calendar']
target_folder = ['Public Folders - [email protected]', 'All Public Folders', 'Conference Room Schedule', 'Room 1']
cal = find_folder(mapi.Folders, target_folder)
if cal is None:
log.error('folder not found: %s' % target_folder)
sys.exit()
items = cal.Items
# include recurring items
items.IncludeRecurrences = True
log.debug('items.IncludeRecurrences == %s' % items.IncludeRecurrences)
log.debug('date/time range is from "%s" to "%s" (%s)' % (flt_start, flt_end, flt_delta))
found_items = []
# for now iterate over all items and manually filter since .Restrict() is not working
for item in items:
item_msgcls = item.MessageClass
log.debug('found item "%s"' % item_msgcls)
# make sure item is an appointment
#if item_msgcls.lower() != 'ipm.appointment':
# log.debug('skipping non-appointment item "%s"' % item_msgcls)
# continue
# manually filter item
# "Start" is type PyTime
if not hasattr(item, 'Start'):
log.debug('skipping item "%s" which has no "Start" attribute (can\'t check start time)' % item_msgcls)
continue
item_start = convert_pytime_to_datetime(item.Start)
if item_start < flt_start or item_start > flt_end:
log.debug('skipping item "%s" with start date/time out of range: %s' % (item_msgcls, item_start))
continue
found_item = dict(item=item, item_start=item_start)
found_items.append(found_item)
log.debug('item "%s" has start date/time in range: %s' % (item_msgcls, item_start))
log.debug('"%s" from "%s" to "%s"' % (item.Subject, item.Start, item.End))
if not found_items:
log.debug('no items found in date/time range')
sys.exit()
log.debug('%d item(s) found in date/time range' % len(found_items))
# sort items by start time
found_items = sorted(found_items, key=lambda k: k['item_start'])
for item in found_items:
item_start = item['item_start']
item = item['item']
log.debug('"%s" from "%s" to "%s"' % (item.Subject, item.Start, item.End))
Log output:
2014-11-17 14:00:56,181 [INFO ] 0. Public Folders - [email protected] (6)
2014-11-17 14:00:56,226 [INFO ] 0. Favorites (6)
2014-11-17 14:00:56,263 [INFO ] 1. All Public Folders (6)
2014-11-17 14:00:56,322 [INFO ] 0. Sales Calendar (1)
2014-11-17 14:00:56,375 [INFO ] 1. Conference Room Schedule (6)
2014-11-17 14:00:56,434 [INFO ] 0. Room 1 (1)
2014-11-17 14:00:56,476 [INFO ] 1. Room 2 (1)
2014-11-17 14:00:56,535 [INFO ] 2. Room 3 (1)
2014-11-17 14:00:56,588 [INFO ] 3. Room 4 (1)
2014-11-17 14:00:56,644 [INFO ] 2. ... (2)
2014-11-17 14:00:56,697 [INFO ] 0. ... (2)
2014-11-17 14:00:56,752 [INFO ] 1. ... (2)
2014-11-17 14:00:58,388 [INFO ] 1. [email protected] (0)
2014-11-17 14:00:58,421 [INFO ] 0. Deleted Items (0)
2014-11-17 14:00:58,454 [INFO ] 1. Inbox (0)
2014-11-17 14:00:58,489 [INFO ] 2. Outbox (0)
2014-11-17 14:00:58,523 [INFO ] 3. Sent Items (0)
2014-11-17 14:00:58,558 [INFO ] 4. Calendar (1)
2014-11-17 14:00:58,592 [INFO ] 5. Contacts (2)
2014-11-17 14:00:58,664 [INFO ] 6. ... (0)
...
2014-11-17 14:00:59,296 [DEBUG] items.IncludeRecurrences == True
2014-11-17 14:00:59,315 [DEBUG] date/time range is from "2014-11-17 14:00:59.122000" to "2014-12-17 14:00:59.122000" (30 days, 0:00:00)
...
2014-11-17 14:00:59,358 [DEBUG] found item "IPM.Appointment"
2014-11-17 14:00:59,387 [DEBUG] skipping item "IPM.Appointment" with start date/time out of range: 2014-09-19 11:00:00
...
2014-11-17 14:01:30,595 [DEBUG] found item "IPM.Appointment"
2014-11-17 14:01:30,624 [DEBUG] skipping item "IPM.Appointment" with start date/time out of range: 2012-01-25 10:30:00
...
2014-11-17 14:01:38,961 [DEBUG] found item "IPM.Schedule.Meeting.Canceled"
2014-11-17 14:01:38,982 [DEBUG] skipping item "IPM.Schedule.Meeting.Canceled" which has no "Start" attribute (can't check start time)
...
2014-11-17 14:01:39,056 [DEBUG] found item "IPM.Schedule.Meeting.Request"
2014-11-17 14:01:39,079 [DEBUG] skipping item "IPM.Schedule.Meeting.Request" which has no "Start" attribute (can't check start time)
...
2014-11-17 14:01:50,782 [DEBUG] found item "IPM.Appointment"
2014-11-17 14:01:50,862 [DEBUG] item "IPM.Appointment" has start date/time in range: 2014-11-17 14:30:00
2014-11-17 14:01:50,888 [DEBUG] "ABC - meeting with Len Jones & John Li" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
...
2014-11-17 14:01:53,326 [DEBUG] found item "IPM.Appointment"
2014-11-17 14:01:53,375 [DEBUG] item "IPM.Appointment" has start date/time in range: 2014-11-17 14:30:00
2014-11-17 14:01:53,408 [DEBUG] "Don - Interview" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
2014-11-17 14:01:53,440 [DEBUG] found item "IPM.Appointment"
2014-11-17 14:01:53,487 [DEBUG] item "IPM.Appointment" has start date/time in range: 2014-11-17 14:30:00
2014-11-17 14:01:53,523 [DEBUG] "Don - Interview" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
...
2014-11-17 14:01:53,681 [DEBUG] found item "IPM.Appointment"
2014-11-17 14:01:53,732 [DEBUG] item "IPM.Appointment" has start date/time in range: 2014-11-17 14:30:00
2014-11-17 14:01:53,762 [DEBUG] "Weekly Conference Call" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
...
2014-11-17 14:01:58,049 [DEBUG] found item "IPM.Appointment"
2014-11-17 14:01:58,111 [DEBUG] item "IPM.Appointment" has start date/time in range: 2014-11-17 14:30:00
2014-11-17 14:01:58,151 [DEBUG] "Ben Connors - GHS" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
...
2014-11-17 14:01:58,326 [DEBUG] found item "IPM.Appointment"
2014-11-17 14:01:58,380 [DEBUG] item "IPM.Appointment" has start date/time in range: 2014-11-17 14:30:00
2014-11-17 14:01:58,414 [DEBUG] "Joe Dietz" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
...
2014-11-17 14:02:00,302 [DEBUG] 6 item(s) found in date/time range
2014-11-17 14:02:00,329 [DEBUG] "ABC - meeting with Len Jones & John Li" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
2014-11-17 14:02:00,365 [DEBUG] "Don - Interview" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
2014-11-17 14:02:00,403 [DEBUG] "Don - Interview" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
2014-11-17 14:02:00,434 [DEBUG] "Weekly Conference Call" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
2014-11-17 14:02:00,474 [DEBUG] "Ben Connors - GHS" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
2014-11-17 14:02:00,510 [DEBUG] "Joe Dietz" from "11/17/14 14:30:00" to "11/17/14 14:30:00"
Upvotes: 0
Views: 3008
Reputation: 43
The key to getting this to work for me was to use the namespace.createRecipient("User Name")
API to reference the shared calendar. Use the username of the user that shared the calendar.
I found the code in the SO answer https://stackoverflow.com/a/21532251/3476174.
recipient = namespace.createRecipient("User Name")
resolved = recipient.Resolve()
sharedCalendar = namespace.GetSharedDefaultFolder(recipient, 9)
I was then able to iterate over sharedCalendar.Items
as expected. I also used sharedCalendar.Items.Restrict()
to filter the events successfully which is shown in the link above.
Upvotes: 2