Search code examples
pythonoutlookms-officepywin32win32com

Get Outlook Group Calendars using Pywin32 (win32com.client)


I'm trying to figure out how I can access the calendars for different Outlook groups that I am apart of. I'm using win32com and Python 3.9 for this task, and would prefer to avoid going the RESTful/auth token route as that would be a fair bit of overhead for what is supposed to be a simple script inserting a few calendar appointments.

I'm able to get my own appointments using the following code:

import win32com.client

application = win32com.client.Dispatch('Outlook.Application')
namespace = application.GetNamespace('MAPI')

cal = namespace.GetDefaultFolder(9)
    
for item in cal.Items:
    print(item.Subject)

Returning the subject line of every appointment in my personal calendar.

I'm also able to get the same information using GetSharedDefaultFolder:

application = win32com.client.Dispatch('Outlook.Application')
namespace = application.GetNamespace('MAPI')

recipient = namespace.createRecipient("{my_email}")
resolved = recipient.Resolve()

sharedCalendar = namespace.GetSharedDefaultFolder(recipient, 9)

for item in sharedCalendar.Items:
    print(item.Subject)

I read that you want to pass the email/user of the person who created the desired calendar as the recipient, but I have had no luck with this.

In attempting to use the creator's email, I get the following error:

pywintypes.com_error: (-2147352567, 'Exception occurred.', (4096, 'Microsoft Outlook', 'The operation failed because of a registry or installation problem. Restart Outlook and try again. If the problem persists, reinstall.', None, 0, -2147221219), None)

And if I attempt to use their (lastName, firstName), I get the following:

pywintypes.com_error: (-2009857777, 'OLE error 0x8834010f', None, None)

Note that I'm referring to GROUP calendars, not Shared Calendars. I'm not sure if there's actually a difference between the two, but they appear as different sections on Outlook for me.

Some references I've been referring to (for others who find this page and are having this issue):
Read Outlook Events via Python
https://learn.microsoft.com/en-us/office/vba/api/outlook.namespace.getdefaultfolder (and related pages)
Problem with read Outlook shared calendar via python
https://learn.microsoft.com/en-us/answers/questions/607061/how-to-create-new-events-share-calendar-with-pytho.html


Solution

  • The NameSpace.GetSharedDefaultFolder method is used in a delegation scenario, where one user has delegated access to another user for one or more of their default folders (for example, their shared Calendar folder). So, you need to make sure the user as delegated access to you.

    If the calendar is visible in Outlook's navigation pane you can access it using the NavigationGroups object. You can traverse the group and folder hierarchy of a module in the Navigation Pane by using the NavigationGroups and NavigationFolders collections. The NavigationGroups collection of the NavigationModule object contains each navigation group displayed in a navigation module, while the NavigationFolders collection of the NavigationGroup object contains each navigation folder displayed in a navigation group. By using these collections in combination, you can enumerate each navigation folder for a navigation module displayed in the Navigation Pane. Here is the sample VBA code where you can get the idea of the required OOM properties method to get the required calendar:

    Dim WithEvents objPane As NavigationPane 
     
    Private Sub EnumerateActiveCalendarFolders() 
     Dim objModule As CalendarModule 
     Dim objGroup As NavigationGroup 
     Dim objFolder As NavigationFolder 
     Dim intCounter As Integer 
     
     On Error GoTo ErrRoutine 
     
     ' Get the NavigationPane object for the 
     ' currently displayed Explorer object. 
     Set objPane = Application.ActiveExplorer.NavigationPane 
     
     ' Get the CalendarModule object, if one exists, 
     ' for the current Navigation Pane. 
     Set objModule = objPane.Modules.GetNavigationModule(olModuleCalendar) 
     
     ' Iterate through each NavigationGroup contained 
     ' by the CalendarModule. 
     For Each objGroup In objModule.NavigationGroups 
     ' Iterate through each NavigationFolder contained 
     ' by the NavigationGroup. 
     For Each objFolder In objGroup.NavigationFolders 
     ' Check if the folder is selected. 
     If objFolder.IsSelected Then 
     intCounter = intCounter + 1 
     End If 
     Next 
     Next 
     
     ' Display the results. 
     MsgBox "There are " & intCounter & " selected calendars in the Calendar module." 
     
    EndRoutine: 
     On Error GoTo 0 
     Set objFolder = Nothing 
     Set objGroup = Nothing 
     Set objModule = Nothing 
     Set objPane = Nothing 
     intCounter = 0 
     Exit Sub 
     
    ErrRoutine: 
     MsgBox Err.Number & " - " & Err.Description, _ 
     vbOKOnly Or vbCritical, _ 
     "EnumerateActiveCalendarFolders" 
    End Sub
    

    The Outlook object model is common for all kind of programming languages, so it will not take a lot of efforts to recognize the sequence of properties and methods required to get the job done.