Find recurring meetings that have ended with Microsoft Graph

Calendar with date circled

When I joined the Microsoft Graph team I set up recurring 1:1 meetings with each of my teammates and a number of people from other teams within our group. As luck would have it those meetings defaulted to have an end date ~1 year from when the series was created.

As you might guess, I forgot to extend some of those meetings and then after they reached their end date I had to go through my calendar to find which ones were impacted and extend them.

<Update 2023-02-02>I confirmed with the PM for this endpoint that the Recurrence property does not support filtering at this time. As such you will need to filter client-side through your own means.</Update>

The below query is intended to find all recurring meetings on your Exchange Online calendar. It is not a complete solution as I haven’t figured out the exact syntax for recurrence property with an end date in the past. Hopefully someone finds this useful and if you have enhancements to help with filtering please feel free to share in the comments.

Click here to try this out in Graph Explorer

Ex. query$filter=type eq 'seriesMaster'&$select=id,subject,recurrence

Note that type = ‘seriesMaster’ will only find the series and not individual meeting instances which may have exceptions from the original recurrence pattern.

-Frog Out

Tips on Email Signatures

In this post I’ll share tips and questions to ask yourself when creating an email signature. The instructions will be specific to Outlook, but the concepts apply to any email program.


This week a peer of mine asked me:

“Do you have any tips or advice for creating an email signature? I interact with external customers quite a bit and would like to appear more professional over email.”

For those of you who are not familiar with email signatures, you can create a templatized signature at the bottom of your emails to include text, images, your electronic business card, a logo, and more. You can set up Outlook (or your favorite email client of choice) so that signatures are automatically added to all outgoing messages (replies and / or new messages) or add it to emails manually on a case-by-case basis.

Questions to ask yourself

Before you create your signature, take some time to think about who is the audience that will be reading your email signature. What things might they want to know about you, the work you do, how to find you (calendar, blog, etc.), etc.? The following are a series of items you may want to consider:

  • LinkedIn profile link
  • GitHub profile link
  • personal / work blog link
  • links to documentation or projects you work on
  • link to schedule a meeting with you (could be your work calendar availability or a scheduling service)
  • email address for sharing feedback (ex. manager, group alias, etc.)
  • upcoming OOF (you need to update regularly)
  • time zone / working hours
  • inspirational quote
  • …and more

An additional thought is to look at signatures that you can seen from other people and ask them if it is ok to borrow / copy / adapt it. I’ve done this many times in the past and my current signature was adapted from a colleague at Microsoft.


The following is my current signature as an example:

Brian T. Jackett
Sr. Program Manager | Microsoft Graph CPx
Blog: | Microsoft Teams (Chat) | Calendar availability (EST/EDT)
If you have any feedback about my work, please share with me or my manager, <redacted>.

How to add your email signature to Outlook

  • Copy your email signature
  • Open a new email message in Outlook
  • On the Message menu, select Signatures, then New, and type in a nickname for this signature
  • Paste in your new signature
  • Select OK to save and exit the email signature editor

Detailed instructions:​


Hopefully this post gives you some inspiration on what you would like to include. If you have suggestions or would like to share your own signature(s) please post in the comments.

-Frog Out

Outlook Calendar Tips for Remote Teams

As mentioned in my last blog post A New Role with Microsoft Graph Team, I mentioned I am joining the Microsoft Graph team. One of the nice aspects of our team is that we are diverse and globally dispersed. With the different time zones that our team all reside in I thought it would be helpful to review a few of my calendar settings in Outlook desktop and Outlook on the Web to help with scheduling meetings or calls.

<Update 2020-11-05>Update screenshots for meeting duration to include new option for end early or start late. Thanks to my teammate Glenn Block for the suggestion.</Update>

Working / Meeting Hours

Set your working / meeting days and hours so that teammates will know when you are generally available for scheduled meetings or calls. Personally, I wake up early most days and hence my start of the day is likely earlier than some others.

Outlook desktop: File -> Options -> Calendar -> Work time

Outlook calendar settings for working hours

Outlook on the Web: Settings -> Calendar -> View -> Meeting hours

Outlook on the Web calendar settings for meeting hours

Time Zones

Since my team is all over the world, it is important to be aware of time zones for scheduling meetings. In Outlook desktop it is possible to set your primary time zone and display 2 additional time zones. In the following screenshot I have set Eastern Time (US & Canada) as my primary time zone with additional time zones for Pacific Time (US & Canada) and East Africa Time (Nairobi). I have purposely kept the labels short so that they fit easily in the display on calendar views.

Outlook desktop: File -> Options -> Calendar -> Time zones

I have only been able to add a single time zone in Outlook on the Web. If someone knows a way to add multiple please let me know in the comments or contact me.

Outlook on the Web: Settings -> Calendar -> Language and time

End Meetings Early / Start Meetings Late

Whether you are hosting a meeting in-person or online there are many reasons you may want to end your meeting early or start your meeting late including:

  • Allow attendees time to walk to their next meeting room
  • Encourage attendees to wrap up their meeting without overlapping the following time block
  • Give attendees time for a mental break / chance to use the restroom in between meetings
  • …and more

Outlook desktop: File -> Options -> Calendar -> Calendar options

Outlook on the Web: Settings -> Calendar -> Events and invitations -> Shorten duration for all events

Share Free / Busy Times

In addition to setting your working / meeting hours, you can also come to show your free / busy times (and more) with other people.

Outlook desktop: File -> Options -> Calendar -> Calendar options -> Free/Busy Options

By default you may see that all users in your organization are able to see your free / busy times. You can adjust permission levels to show more details or add / remove additional people to have access to view your calendar.

Outlook on the Web: Settings -> Calendar -> Shared calendars

Publish Calendar

Aside from showing your free / busy times to people internal to your organization, sometimes you may want to publish your calendar to people external to your organization. Currently I have found this easiest to do through Outlook on the Web.

Outlook on the Web: Settings -> Calendar Shared calendars -> Publish a calendar

After you publish your desired calendar you can provide people with either an HTML (render in browser) or ICS (universal calendar file format) link.


In this post I walked through a number of calendar settings and preferences on my Outlook desktop and Outlook on the Web client. I hope this helps you to think of the diverse and global audience that you may be working with currently or in the future. If you have any additional tips you recommend please share them in the comments.

-Frog Out

Get Exchange Online Mailbox Size in GB

   As mentioned in my previous post I was recently working with a customer to get started with Exchange Online PowerShell commandlets.  In this post I wanted to follow up and show one example of a difference in output from commandlets in Exchange 2010 on-premises vs. Exchange Online.



   The customer was interested in getting the size of mailboxes in GB.  For Exchange on-premises this is fairly easy.  A fellow PFE Gary Siepser wrote an article explaining how to accomplish this (click here).  Note that Gary’s script will not work when remoting from a local machine that doesn’t have the Exchange object model installed.  A similar type of scenario exists if you are executing PowerShell against Exchange Online.  The data type for TotalItemSize  being returned (ByteQuantifiedSize) exists in the Exchange namespace.  If the PowerShell session doesn’t have access to that namespace (or hasn’t loaded it) PowerShell works with an approximation of that data type.

   The customer found a sample script on this TechNet article that they attempted to use (minor edits by me to fit on page and remove references to deleted item size.)


Get-Mailbox -ResultSize Unlimited |
   Get-MailboxStatistics |
   Select DisplayName,StorageLimitStatus, `
   @{name="TotalItemSize (MB)"; expression={[math]::Round( `
   ($_.TotalItemSize.Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}}, `
   ItemCount |
   Sort "TotalItemSize (MB)" -Descending |
   Export-CSV "C:My DocumentsAll Mailboxes.csv" -NoTypeInformation


  The script is targeted to Exchange 2010 but fails for Exchange Online.  In Exchange Online when referencing the TotalItemSize property though it does not have a Split method which ultimately causes the script to fail.



   A simple solution would be to add a call to the ToString method off of the TotalItemSize property (in bold on line 5 below).


Get-Mailbox -ResultSize Unlimited |
   Get-MailboxStatistics |
   Select DisplayName,StorageLimitStatus, `
   @{name="TotalItemSize (MB)"; expression={[math]::Round( `
   ($_.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}}, `
   ItemCount |
   Sort "TotalItemSize (MB)" -Descending |
   Export-CSV "C:My DocumentsAll Mailboxes.csv" -NoTypeInformation


   This fixes the script to run but the numerous string replacements and splits are an eye sore to me.  I attempted to simplify the string manipulation with a regular expression (more info on regular expressions in PowerShell click here).  The result is a workable script that does one nice feature of adding a new member to the mailbox statistics called TotalItemSizeInBytes.  With this member you can then convert into any byte level (KB, MB, GB, etc.) that suits your needs.  You can download the full version of this script below (includes commands to connect to Exchange Online session).

$UserMailboxStats = Get-Mailbox -RecipientTypeDetails UserMailbox `
   -ResultSize Unlimited |
$UserMailboxStats |
   Add-Member -MemberType ScriptProperty -Name TotalItemSizeInBytes `
   -Value {$this.TotalItemSize -replace "(.*()|,| [a-z]*)", ""}
$UserMailboxStats |
   Select-Object DisplayName,@{Name="TotalItemSize (GB)"; `



   Moving from on-premises to the cloud with PowerShell (and PowerShell remoting in general) can sometimes present some new challenges due to what you have access to.  This means that you must always test your code / scripts.  I still believe that not having to physically RDP to a server is a huge gain over some of the small hurdles you may encounter during the transition.  Scripting is the future of administration and makes you more valuable.  Hopefully this script and the concepts presented help you be a better admin / developer.


      -Frog Out




The Get-MailboxStatistics Cmdlet, the TotalitemSize Property, and that pesky little “b”


View Mailbox Sizes and Mailbox Quotas Using Windows PowerShell


Regular Expressions with Windows PowerShell


“I don’t always test my code…” image


The One Thing: Brian Jackett and SharePoint 2010

Links for Getting Started with PowerShell for Office 365 and Exchange Online

   This past week I worked with some customers who were getting started with using PowerShell against Exchange Online as part of their new Office 365 solution.  As you may know Exchange is not my primary focus area but since these customers’ needs centered around PowerShell I thought this would be a good opportunity to learn more.  What soon became apparent to me was a few things:

  • The output / objects returned from Exchange Online vs. on-premises commandlets sometimes differ (mainly due to Exchange Online output needing to be serialized across the wire)
  • Some of the community scripts posted on TechNet Script Center or PoSH Code Repository that work for on-premises won’t work against Exchange Online due to the above
  • I went to multiple resources to get an introduction of using the Exchange Online commandlets


   In light of the last item I would like to share some resources I gathered for getting started with the Exchange Online commandlets.  I will address the first two items in a follow up post that shows one sample script that I helped a customer fix.



Using PowerShell with Office365


Administering Microsoft Office 365 using WIndows PowerShell


Reference to Available PowerShell Cmdlets in Exchange Online


Windows PowerShell cmdlets for Office 365


Role Based Access Control in Exchange Online


Exchange Online and RBAC



   Office 365 is being integrated into more and more customers’ environments.  While your PowerShell skills can still be used to manage certain portions of Office 365 (Exchange Online as of the time of this writing) there are a few differences in how data is passed back and forth.  Hopefully the links above will get you started on scripting against  cloud based services.


      -Frog Out