How to Read User Calendar Events Using Powershell and the Graph API

Calendar API access using PowerShell

Many organizations find it helpful to implement some kind of automation around user calendars.

The purpose could be tracking productivity, updating notification boards, seeing trends, etc.

With Microsoft Graph PowerShell, it’s pretty easy to access user calendars – if you know how to do it 🙂

Here’s a step-by-step guide:

Scripting Office 365 Calendars: Step-by-Step Guide

To enable programmatic access to all calendars in your organization, you need to implement the following:

  1. Generate a certificate to be used for OAuth2 authentication
  2. Set up a client application
  3. Assign API permissions to the application
  4. Set up a certificate identity on the application

1. Generate a Certificate to Be Used for Oauth2 Authentication

With PowerShell, you can quickly generate a self-signed certificate which works just fine for application authentication.

You’ll need two files from the certificate:

  • A .pfx file – includes the private key and is stored securely in the personal certificate store of your scheduling account on the scheduling server.
  • A .cer file – includes only the public key and is uploaded to the Azure App to allow you to authenticate using the corresponding (secret) private key.

Generate a new certificate and export the .pfx and .cer files using the following code:

# Create certificate with expiry of 5 years
$mycert = New-SelfSignedCertificate -DnsName "easy365manager.com" -CertStoreLocation "cert:\CurrentUser\My" -NotAfter (Get-Date).AddYears(5) -KeySpec KeyExchange
# Export certificate to .pfx file
$mycert | Export-PfxCertificate -FilePath C:\tmp\ExoAutomateCert.pfx -Password $(ConvertTo-SecureString -String "$omeP@ssw0rd" -AsPlainText -Force)
# Export certificate to .cer file
$mycert | Export-Certificate -FilePath C:\tmp\ExoAutomateCert.cer

The certificate is created in the personal certificate store of the user running the code.

If you plan to automate scripts using the logged-in account on the logged-in system, you won’t need the .pfx file (except for backup).

To use the certificate on another system/user account, you must log in interactively and import the certificate from the .pfx file.

The .cer file will be used to set up authentication on the Azure App in a later step.

2. Set Up a Client Application

You must log in to the Azure Portal to set up a new Azure Application. Then, select Azure Active Directory, click on App registrations, or follow this direct link.

From there, you can create a new App registration by clicking on New registration:

Azure App Registration for Exchange Online PowerShell Automation

Complete the application registration:

Calendar API access using PowerShell

The new Azure Application has now been created:

Notice the Application (client) ID. This is what we will use as the -AppId parameter when connecting to Exchange Online with PowerShell.

3. Assign API Permissions to the Application

We’ll be using the Graph API to access user calendars. This is much easier to use than older methods like Exchange Web Services (EWS).

Select API permissions, click on Add a permission, and select Microsoft Graph:

Select Application permissions:

Then scroll down to find Calendars permissions. Select Calendars.Read if you’re only going to review/export information:

We now have the permissions needed to access calendar information. If you also want your script to extract user information, you can add the following permissions:

Click on Add permissions to commit the new API permissions.

Then grant Admin Consent to the new permissions:

Calendar API access using PowerShell

The status of the permissions will change to Granted, and the new client application is now set up.

We only need to grant access to use it.

4. Set Up a Certificate Identity on the Application

To enable authentication using the certificate generated in step 1, we need to perform the following steps:

Click on Certificates & secrets, click on Certificates, click on Upload certificate, browse to the .cer file from step 1, add a description and click on Add:

You’ll now see the certificate in the list, including the thumbprint that we’ll be using as a parameter in our script:

Read Calendar Information Using Microsoft Graph PowerShell

We’re ready to rock’n’roll!

Use the Microsoft Graph PowerShell module to access the user calendars.

Connect to your new client application with the certificate using the following command:

PS C:\> Connect-MgGraph -TenantId "8a35f394-855d-4d13-9f6f-86d8eb24dc6b" -ClientId "23b3f624-502d-42fb-83ac-ea9f6aff9e5b" -CertificateThumbprint "08451D7079F093EBB2A2CB0266C885ECA098DD9E"
Welcome To Microsoft Graph!

To extract calendar information, use the Get-MgUserCalendarView CmdLet.

The following example lists all calendar entries for today for the user Hans C. Ørsted (only one entry is shown):

PS C:\> $StartDate = Get-Date -Date 00:00:00
PS C:\> $EndDate = Get-Date -Date 23:59:59
PS C:\> Get-MgUserCalendarView -UserId hans.c.orsted@azure.skrubbeltrang.com -CalendarId "Calendar" -StartDateTime $StartDate -EndDateTime $EndDate | fl


AllowNewTimeProposals         : True
Attachments                   :
Attendees                     : {Microsoft.Graph.PowerShell.Models.MicrosoftGraphAttendee, Microsoft.Graph.PowerShell.Models.MicrosoftGraphAttendee, Microsoft.Graph.PowerShell.Models.MicrosoftGraphAttendee}
Body                          : Microsoft.Graph.PowerShell.Models.MicrosoftGraphItemBody
BodyPreview                   : Do some more testing on electro magnetism.
Calendar                      : Microsoft.Graph.PowerShell.Models.MicrosoftGraphCalendar
Categories                    : {}
ChangeKey                     : xa95c+RziUeacUESMPKGkwAAGGtkxw==
CreatedDateTime               : 11/8/2022 7:19:51 AM
End                           : Microsoft.Graph.PowerShell.Models.MicrosoftGraphDateTimeZone
Extensions                    :
HasAttachments                : False
HideAttendees                 : False
ICalUId                       : 040000008200E00074C5B7101A82E00800000000000135B14AF3D801000000000000000010000000D7E511407918FD4F9318BD4EEDFB3229
Id                            : AAMkAGY5MjM3MjVmLTcxMzQtNDEwNC1iNDQwLTU1NjNhOGRmYzM5ZABGAAAAAAAHk64FGa4vQJkMsperiKxZBwDFr3lz5HOJR5pxQRIw8oaTAAAAAAENAADFr3lz5HOJR5pxQRIw8oaTAAAYa3q5AAA=
Importance                    : normal
Instances                     :
IsAllDay                      : False
IsCancelled                   : False
IsDraft                       : False
IsOnlineMeeting               : False
IsOrganizer                   : True
IsReminderOn                  : True
LastModifiedDateTime          : 11/8/2022 7:21:52 AM
Location                      : Microsoft.Graph.PowerShell.Models.MicrosoftGraphLocation
Locations                     : {Science room 23}
MultiValueExtendedProperties  :
OnlineMeeting                 : Microsoft.Graph.PowerShell.Models.MicrosoftGraphOnlineMeetingInfo
OnlineMeetingProvider         : unknown
OnlineMeetingUrl              :
Organizer                     : Microsoft.Graph.PowerShell.Models.MicrosoftGraphRecipient
OriginalEndTimeZone           : Romance Standard Time
OriginalStart                 :
OriginalStartTimeZone         : Romance Standard Time
Recurrence                    : Microsoft.Graph.PowerShell.Models.MicrosoftGraphPatternedRecurrence
ReminderMinutesBeforeStart    : 15
ResponseRequested             : True
ResponseStatus                : Microsoft.Graph.PowerShell.Models.MicrosoftGraphResponseStatus
Sensitivity                   : normal
SeriesMasterId                :
ShowAs                        : busy
SingleValueExtendedProperties :
Start                         : Microsoft.Graph.PowerShell.Models.MicrosoftGraphDateTimeZone
Subject                       : Meeting with assistant
TransactionId                 :
Type                          : singleInstance
WebLink                       : https://outlook.office365.com/owa/?itemid=AAMkAGY5MjM3MjVmLTcxMzQtNDEwNC1iNDQwLTU1NjNhOGRmYzM5ZABGAAAAAAAHk64FGa4vQJkMsperiKxZBwDFr3lz5HOJR5pxQRIw8oaTAAAAAAENAADFr3lz5HOJR5pxQRIw8oaTAAAYa3q5AAA%3D&exvsurl=1&path=/calendar/item
AdditionalProperties          : {[@odata.etag, W/"xa95c+RziUeacUESMPKGkwAAGGtkxw=="]}

Besides a lot of technical information, you’ll see useful properties in the above output:

  • Start
  • End
  • Subject
  • BodyPreview
  • Attendees
  • Location

and more.

Have fun creating applications and scripts with calendar integration!