PowerShell: Remove meetings that may cause problem with ActiveSync Devices


It's again time to talk about ActiveSync.

It seems rather frequent that users, most often VIP, ends up missing a meeting because one or more did not synchronize (or rather the handset did not handle the data correctly).

Mainly, this comes down to few common user error:

  1. The meeting is a recurring meeting with no end date (hence it has got a myriad of exceptions - an exception being a discrepancy to the series)
  2. The meeting has got the iCalUID which is duplicate of another one (is the PA using copy/paste when creating meetings?)

This really are the most common scenarios hence why I thought to write up a couple of sample scripts that can report (and delete, if desired) these meetings that are potential offenders.

 

If you need to deep dive into ActiveSync troubleshooting I would suggest the following resources.

  1. Exchange ActiveSync Mailbox Logging
  2. Under The Hood: Exchange ActiveSync Mailbox Log Analysis – Part 1
  3. Under The Hood: Exchange ActiveSync Mailbox Log Analysis – Part 2
  4. A script to troubleshoot issues with Exchange ActiveSync

Now, these are given as goodies and should be used as a start point for your investigation.

Anyway, let's go back to the original scenario, you want to know if a given mailbox has got recurring meetings with no end dates or meetings with the same iCalUID. Or perhaps you found out, while following the above links, that the issue that VIP user has experienced was due to one of the 2 common causes we're trying to fix here.

 

What is it doing then?

There isn't just a script in this article, there are actually 2. I wanted to keep them separate as I feel this better demonstrates how to fetch via EWS the different properties and how to operate in order to identify either duplicates or recurring meetings without end dates. At the end, this gives you the option to run either one of the 2 samples, should you wish to investigate a single type of problem.

 

Both the scripts leverages the Dictionary class as well as the List class as these offer a very efficient way to manipulate multiple items and offers a built capabilities to quickly retrieves Keys/Values or generic entries.

 

Overall, both the examples leverages the following work stream:

  1. Locate the EWS Managed API location (overridden if -EWSManagedApiPath "<location>" is specified)
  2. Connect to the target mailbox via EWS (can leverage Owner Logon, Delegate Access or Impersonation)
    1. If no EWS URL is specified, the script would auto-locate the EWS endpoint via AutoDiscover (-AllowInsecureRedirection might be necessary)
    2. If no EWS Schema Version is specified, this would be auto-located (again, -AllowInsecureRedirection might be necessary), in case of failure it would default to Exchange2013_SP1
  3. Fetch all the items present in the mailbox Calendar and evaluate the condition (recurring meeting with no end date in one case, duplicate iCalUid/GoID in the other sample)
  4. List (or delete, if -ConfirmDeletion is specified) the items that match the criteria

 

Should you wish to modify the sample, all the code below "# Common Functions" is pretty much standard in all my sample scripts, the actual code that demonstrates the functionality is all below the comment "# Specific Functions".

 

How to run it?

This is rather easy. Both the scripts come with examples and a detailed parameter definition. If you have any doubt I'd suggest starting with the following.

Get-Help .\Remove-RecurringMeetingNoEndDate.ps1 -Detailed
Get-Help .\Remove-DuplicateMeetingsById.ps1 -Detailed

Please note that the "Mailbox" parameter expects an email address, this can be the PrimarySmtpAddress, the UserPrincipalName or the WindowsEmailAddress.

Do not try using an alias or a mailbox GUID as these would not work.

 

Some examples? Here you go.

I will interchangeably use the 2 scripts in the examples as they expect the same parameters and the workflow is exactly the same. Feel free to follow the examples with any of the 2.

 

In this first example, the administrator wants to list the duplicates meetings in a given user mailbox. These must not be deleted.

The user is test@contoso.com and the mailbox is hosted in Office 365. The administrator has assigned himself Full Access permission on the user's mailbox.

$AdminCred = Get-Credential
.\Remove-RecurringMeetingNoEndDate.ps1 -Mailbox "Test@Contoso.com" -Credentials $AdminCred -EwsUrl "https://outlook.office365.com/EWS/Exchange.asmx" -EwsVersion "Exchange2013_SP1" -LogFile .\LogFile.txt

 

With the following example, the administrator wants to delete the recurring meetings with no end date from the user mailbox.

At this time, it's not specified which endpoint to contact nor what version fo the EWs schema it supports; these will be auto-located via AutoDiscover. Please note that this operation might take approximately 20 seconds per hop (in case of hybrid deployment this translates to 20 sec for the on-prem look-up plus other 20 seconds for the redirection).

Here Application Impersonation is leveraged so there is no need for FullAccess permission; this should be the preferred way when multiple mailboxes need to be processed.

$AdminCred = Get-Credential
.\Remove-RecurringMeetingNoEndDate.ps1 -Mailbox "Test@Contoso.com" -Credentials $AdminCred -Impersonate -AllowInsecureRedirection -LogFile .\LogFile.txt -ConfirmDeletion

 

Now we're looking to delete the duplicate meetings (by iCalUid and/or GoID) from a list of mailboxes. Here Application Impersonation will be used and both the EWS Schema Version as well as the EWS endpoint will be auto discovered.

Due to the reliance on AutoDiscover, this solution allows you to seamlessly target mailboxes on-premise as well as mailboxes in cloud (should you be running a hybrid deployment). The only constraint here is that the administrative account provided, which does not require a mailbox, must be assigned Application Impersonation rights on all the forests targeted; this implies the account is granted such a RBAC in Exchange on-premise as well as in Exchange Online, if these the mailboxes to be processed are hosted between the 2.

The only downside is that in such a scenario the AutoDiscover process can take some time, sue to the script checking for the SCP first and then moving to the DNS lookup and the DNS redirection.

$AdminCred = Get-Credential
$Mailboxes = "User1@contoso.com","User2@contoso.onmicrosoft.com","MigratedUser@contoso.com"
ForEach ($Mailbox in $Mailboxes) {.\Remove-RecurringMeetingNoEndDate.ps1 -Mailbox $Mailbox -Credentials $AdminCred -Impersonate -AllowInsecureRedirection -LogFile .\LogFile.txt -ConfirmDeletion}

 

Lastly, the more complete example.

This takes in account that you wish to process all the mailboxes in the organization (or a subset of it). The EWS Url as well as the Schema version are specified since we want to achieve greater performances and void any delay coming from the AutoDiscover process. Again, here Application Impersoantion is used as we're going to process potentially a large number of mailboxes and assigning Full Access permission to each target mailbox would be unpractical.

In this example it is also demonstrated the connection to Exchange Online in order to retrieve the full list of the User Mailboxes to be processed.

 

$AdminCred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $AdminCred -Authentication Basic -AllowRedirection
Import-PSSession $Session
$Mailboxes = Get-Mailbox -RecipientTypeDetails "UserMailbox" -ResultSize Unlimited
ForEach ($Mailbox in $Mailboxes) {
   .\Remove-RecurringMeetingNoEndDate.ps1 -Mailbox $Mailbox.PrimarySmtpAddress -Credentials $AdminCred -EwsUrl "https://outlook.office365.com/ews/exchange.asmx" -EwsVersion "Exchange2013_SP1" -Impersonate -LogFile .\LogFile.txt -ConfirmDeletion
   .\Remove-DuplicateMeetingsById.ps1 -Mailbox $Mailbox.PrimarySmtpAddress -Credentials $AdminCred -EwsUrl "https://outlook.office365.com/ews/exchange.asmx" -EwsVersion "Exchange2013_SP1" -Impersonate -LogFile .\LogFile.txt -ConfirmDeletion
}

 

The sample scripts.

Here you can download Remove-RecurringMeetingNoEndDate and Remove-DuplicateMeetingsById.

 

Notes.

Despite the sample scripts have been tested while using the Exchange2007_SP1 schema, for retro-compatibility, an Exchange Server 2013, 2016 or Exchange Online have been used as target. It's strongly suggested to test thoroughly the sample prior to run it against live users' mailboxes.

The script requires -Mailbox and -Credentials to run, at present. Should you wish to make these optional just change "Mandatory=$True" to "Mandatory=$False" and remove "[ValidateNotNullOrEmpty()]" form these 2 parameters definition. The logic for having these parameters optional is already in-place so this change would not require any new code to be added.

 

Comments (0)

Skip to main content