by

Discovering the TimeZone being utilized in a Mailbox utilizing EWS

Discovering the TimeZone being utilized in a Mailbox utilizing EWS In the event you ever have the necessity to create plenty of occasions in person mailbox’s from a central software or Script the place the goal Mailboxes span throughout totally different time zones then discovering every goal Mailbox’s timezone is a crucial factor. On this submit I’ll define a couple of totally different strategies of getting the TimeZone utilizing EWS.

In case you have entry to the Trade Administration Shell cmdlet’s to seek out the customers configured timezone you should utilize both the Get-MailboxCalendarConfiguration or Get-MailboxRegionalConfiguration cmdlets which present you the timezone settings of a Mailbox from the WorkHours configuration of that mailbox. The article within the Mailbox that the data is learn from/saved in is the IPM.Configuration.WorkHours FAI (Folder Assoicated Gadgets) object within the Calendar Folder of the Mailbox. So if you wish to entry the TimeZone setting in Mailbox simply utilizing EWS you want to Bind to this UserConfiguration object (FAI object) after which parse the TimeZone Settings out of the WorkHours configuration XML doc(which is documented in https://msdn.microsoft.com/en-us/library/ee157798(v=exchg.80).aspx) eg in Powershell one thing like the next ought to work okay

operate GetWorkHoursTimeZone
{
param(
[Parameter(Place=0, Obligatory=$true)] [String]$MailboxName,
[Parameter(Place=1, Obligatory=$true)] [Microsoft.Exchange.WebServices.Data.ExchangeService]$service
)
Start
{
# Bind to the Calendar Folder
$folderid= new-object Microsoft.Trade.WebServices.Information.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar,$MailboxName)
$Calendar = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$sfFolderSearchFilter = new-object Microsoft.Trade.WebServices.Information.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass, "IPM.Configuration.WorkHours")
#Outline ItemView to retrive simply 1000 Gadgets
$ivItemView = New-Object Microsoft.Trade.WebServices.Information.ItemView(1)
$ivItemView.Traversal = [Microsoft.Exchange.WebServices.Data.ItemTraversal]::Related
$fiItems = $service.FindItems($Calendar.Id,$sfFolderSearchFilter,$ivItemView)
if($fiItems.Gadgets.Depend -eq 1)
{
$UsrConfig = [Microsoft.Exchange.WebServices.Data.UserConfiguration]::Bind($service, "WorkHours", $Calendar.Id, [Microsoft.Exchange.WebServices.Data.UserConfigurationProperties]::All)
[XML]$WorkHoursXMLString = [System.Text.Encoding]::UTF8.GetString($UsrConfig.XmlData)
$returnVal = $WorkHoursXMLString.Root.WorkHoursVersion1.TimeZone.Identify
write-host ("Parsed TimeZone : " + $returnVal)
Write-Output $returnVal
}
else
{
write-host ("No Workhours Object in Mailbox")
Write-Output $null
}
}
}

 The opposite place in an Trade Malbox the place TimeZone info is held is within the OWA Configuration. That is set when a person logs onto to OWA the primary time after which selects the timezone, the configuration is then saved in one other FAI (in a Roaming Dictionary)with an ItemClass of IPM.Configuration.OWA.UserOptions within the NON_IPM root of the mailbox. Eg the next can be utilized to entry this setting utilizing EWS

operate GetOWATimeZone{
param(
[Parameter(Place=0, Obligatory=$true)] [String]$MailboxName,
[Parameter(Place=1, Obligatory=$true)] [Microsoft.Exchange.WebServices.Data.ExchangeService]$service
)
Start
{
# Bind to the RootFolder Folder
$folderid= new-object Microsoft.Trade.WebServices.Information.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Root,$MailboxName)
$RootFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$sfFolderSearchFilter = new-object Microsoft.Trade.WebServices.Information.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass, "IPM.Configuration.OWA.UserOptions")
#Outline ItemView to retrive simply 1000 Gadgets
$ivItemView = New-Object Microsoft.Trade.WebServices.Information.ItemView(1)
$ivItemView.Traversal = [Microsoft.Exchange.WebServices.Data.ItemTraversal]::Related
$fiItems = $service.FindItems($RootFolder.Id,$sfFolderSearchFilter,$ivItemView)
if($fiItems.Gadgets.Depend -eq 1)
{
$UsrConfig = [Microsoft.Exchange.WebServices.Data.UserConfiguration]::Bind($service, "OWA.UserOptions", $RootFolder.Id, [Microsoft.Exchange.WebServices.Data.UserConfigurationProperties]::All)
if($UsrConfig.Dictionary.ContainsKey("timezone"))
{
$returnVal = $UsrConfig.Dictionary["timezone"]
write-host ("OWA TimeZone : " + $returnVal)
Write-Output $returnVal
}
else
{
write-host ("TimeZone not set")
Write-Output $null
}


}
else
{
write-host ("No Workhours OWAConfig for Mailbox")
Write-Output $null
}
}
}

In the event you tried each of those places and nonetheless cannot discover the TimeZone (or your get a conflicting outcome) the final methodology you could possibly strive is to enumerate the final X variety of appointments that the place created by the person within the calendar (both a gathering they organized or a non assembly) after which enumerate the timezone used on these objects. The next is a pattern of utilizing the Calendar Appointments to work out the timezone of the person (It ought to return probably the most generally used timezone base on the final 150 Calendar objects).

operate GetTimeZoneFromCalendarEvents{
param(
[Parameter(Place=0, Obligatory=$true)] [String]$MailboxName,
[Parameter(Place=1, Obligatory=$true)] [Microsoft.Exchange.WebServices.Data.ExchangeService]$service
)
Start
{
$folderid= new-object Microsoft.Trade.WebServices.Information.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar,$MailboxName)
$Calendar = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$tzList = [TimeZoneInfo]::GetSystemTimeZones()
$AppointmentStateFlags = New-Object Microsoft.Trade.WebServices.Information.ExtendedPropertyDefinition([Microsoft.Exchange.WebServices.Data.DefaultExtendedPropertySet]::Appointment,0x8217,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);
$ResponseStatus = New-Object Microsoft.Trade.WebServices.Information.ExtendedPropertyDefinition([Microsoft.Exchange.WebServices.Data.DefaultExtendedPropertySet]::Appointment,0x8218,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);
$ivItemView = New-Object Microsoft.Trade.WebServices.Information.ItemView(150)
$psPropset= new-object Microsoft.Trade.WebServices.Information.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$psPropset.Add($AppointmentStateFlags)
$psPropset.Add($ResponseStatus)
$ivItemView.PropertySet = $psPropset
$fiItems = $service.FindItems($Calendar.Id,$ivItemView)
$tzCount = @{}
if($fiItems.Gadgets.Depend -gt 0){
foreach($Merchandise in $fiItems.Gadgets){
$AppointmentStateFlagsVal = $null
[Void]$Merchandise.TryGetProperty($AppointmentStateFlags,[ref]$AppointmentStateFlagsVal)
$ResponseStatusVal = $null
[Void]$Merchandise.TryGetProperty($ResponseStatus,[ref]$ResponseStatusVal)
if($ResponseStatusVal -eq "Organizer" -bor $AppointmentStateFlagsVal -eq 0)
{
if($tzCount.ContainsKey($Merchandise.TimeZone))
{
$tzCount[$Merchandise.TimeZone]++
}
else
{
$tzCount.Add($Merchandise.TimeZone,1)
}
}
}
}
$returnVal = $null
if($tzCount.Depend -gt 0){
$fav = ""
$tzCount.GetEnumerator() | kind -Property Worth -Descending | foreach-object {
if($fav -eq "")
{
$fav = $_.Key
}
}
foreach($tz in $tzList)
{
if($tz.DisplayName -eq $fav)
{
$returnVal = $tz.Id
}
}
}
Write-Host ("TimeZone From Calendar Appointments : " + $returnVal)
Write-Output $returnVal
}
}

I’ve included all of those capabilities in a module that I’ve posted on GitHub right here