The script generates and emails an HTML-formatted report on meetings scheduled for a user. The script can be used for mailboxes in Exchange Online and Exchange on-premise.
To create a report on demand, create a custom command that runs the script on User objects. To schedule the reports, create a scheduled task that will run the script on a regular basis.
To use the script, download and install Microsoft Exchange Web Services Managed API on the computer where Adaxes service is running.
Parameters:
- $exchangeServer - Specifies the Fully Qualified Domain Name (FQDN) of the Exchange Server that will be used by the script (only for Exchange On-Premises). If the script is used for Exchange Online only, set the variable to $NULL.
- $exchangeWebServiceDllPath - Specifies the full path to the Microsoft Exchange Web Services dll module.
- $to - Specifies the e-mail address of the notification recipient.
- $subject - Specifies the email message subject.
- $reportHeader - Specifies the email message header.
- $htmlTable - Specifies the header for the table with the calendar meetings.
- $reportFooter - Specifies the email message footer.
PowerShell
$exchangeServer = "exchangeserver.domain.com" # TODO: modify me
$exchangeWebServiceDllPath = "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll" # TODO: modify me
# E-mail settings
$to = "recipient@domain.com" # TODO: modify me
$subject = "Meetings in the calendar of mailbox '%name%'" # TODO: modify me
$reportHeader = "<h2><b>Meetings in the calendar of mailbox '%name%'</b></h2><br/>" # TODO: modify me
$htmlTable = @"
<table border="1">
<tr>
<th>Subject</th>
<th>Organizer</th>
<th>Start</th>
<th>End</th>
<th>Duration</th>
<th>Created on</th>
<th>Body</th>
<th>Display to</th>
<th>Is submitted</th>
</tr>
"@ # TODO: modify me
$reportFooter = "<hr /><p><i>Please do not reply to this e-mail, it was sent to you for notification purposes only.</i></p>" # TODO: modify me
Import-Module $exchangeWebServiceDllPath
# Check whether the user has mailbox
if ($Context.TargetObject.RecipientType -ne "ADM_EXCHANGERECIPIENTTYPE_MAILBOXENABLED")
{
return
}
# Get primary SMTP Address
$mailboxParams = $Context.TargetObject.GetMailParameters()
$emailAddresses = $mailboxParams.EmailAddresses
$primarySMTPAddress = $NULL
for ($i = 0; $i -lt $emailAddresses.Count; $i++)
{
$emailAddress = $emailAddresses.GetAddress($i,[ref]"ADS_PROPERTY_NONE")
if ($emailAddress.IsPrimary -and $emailAddress.Prefix -eq "smtp")
{
$primarySMTPAddress = $emailAddress.Address
break
}
}
if ([System.String]::IsNullOrEmpty($primarySMTPAddress))
{
$Context.LogMessage("Cannot remove meetings scheduled by the user because the user's mailbox doesn't have a primary SMTP address.", "Warning")
return
}
if ($Context.TargetObject.RecipientLocation -eq "ADM_EXCHANGERECIPIENTLOCATION_OFFICE365")
{
# Connect to Exchange Online via the Exchange Web Services API
$exchangeWebService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
$exchangeWebService.Url = "https://outlook.office365.com/EWS/Exchange.asmx"
$token = $Context.CloudServices.GetAzureAuthAccessToken("https://outlook.office365.com/")
$OAuthCredentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($token)
$exchangeWebService.Credentials = $OAuthCredentials
$exchangeWebService.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $primarySMTPAddress)
}
elseif ($Context.TargetObject.RecipientLocation -eq "ADM_EXCHANGERECIPIENTLOCATION_ONPREMISE")
{
# Connect to Exchange on-premises via the Exchange Web Services API
$exchangeWebService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010)
$exchangeWebService.Url = "https://$exchangeServer/ews/exchange.asmx"
}
# Get the user's calendar
$calendarFolderId = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar, $primarySMTPAddress)
$calendarFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchangeWebService, $calendarFolderId)
$itemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(500)
$propertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet(
[Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties,
[Microsoft.Exchange.WebServices.Data.AppointmentSchema]::Organizer)
$propertySet.RequestedBodyType = [Microsoft.Exchange.WebServices.Data.BodyType]::Text
$records = New-Object "System.Text.StringBuilder"
$recordsCount = 0
do
{
$searchResult = $calendarFolder.FindItems($itemView)
foreach ($item in $searchResult.Items)
{
if (!($item.IsMeeting))
{
continue
}
try
{
$item.Load($propertySet)
}
catch
{
$Context.LogMessage("An error occurred when getting item properties. Item start date: $($item.Start). Error: " + $_.Exception.Message, "Warning")
continue
}
$recordsCount++
[void]$records.Append("<tr valign='top'>")
[void]$records.Append("<td>$($item.Subject)</td>")
[void]$records.Append("<td>$($item.Organizer.Address)</td>")
[void]$records.Append("<td>$($item.Start.ToLocalTime())</td>")
[void]$records.Append("<td>$($item.End.ToLocalTime())</td>")
[void]$records.Append("<td>$($item.Duration)</td>")
[void]$records.Append("<td>$($item.DateTimeCreated.ToLocalTime())</td>")
[void]$records.Append("<td>$($item.Body)</td>")
[void]$records.Append("<td>$($item.DisplayTo)</td>")
[void]$records.Append("<td>$($item.IsSubmitted)</td>")
[void]$records.Append("</tr>")
}
$itemView.Offset = $searchResult.NextPageOffset
}
while($searchResult.MoreAvailable -eq $True)
# Build report
$html = New-Object "System.Text.StringBuilder"
[void]$html.Append($reportHeader)
if ($records.Length -eq 0)
{
[void]$html.Append("<b>No meetings found.</b>")
}
else
{
[void]$html.Append($htmlTable)
[void]$html.Append($records.ToString())
[void]$html.Append("</table>")
[void]$html.Append("<br/><b>Number of meetings: $recordsCount</b>")
}
[void]$html.Append($reportFooter)
# Send report
$Context.SendMail($to, $subject, $NULL, $html.ToString())