Select Page

Hi All, 

I got my inspiration from Paul Cunningham, when I stumbled across his awesome script a few years ago to query my exchange environment and to output it to my email once a week and produce a table with a  list all the devices that are connected and how many days they were not synced. This obviously helped me keep my exchange clean and to get rid of those devices that didn’t check in.

It was only a few months ago I decided to do a cut over migration to Office 365! Because the price for it is ridiculous and it makes having an on premise exchange not worth the time and effort to maintain.
So using Pauls, script almost became redundant because I couldn’t easily query exchange anymore, and I know that the script had to be adapted! (im not a powershell expert) so I left it for a few months and re-visited Paul’s Blogagain.

While browsing through I saw a few people mention about adapting it to work with 365 and I even saw Paul linked people to another blog to reference how to change it and adapt it. It was infact this BLOG

This blog was a very well written (better than mine) and he explained how the script works, what commands to adapt and look out for, because they can change from different exchange versions etc. Very, very interesting! Worth a read! Unfortunately there was no download or clear cut instructions of actually how to do it.

So this took me roughly an hour and half to play around with and get right, but it works like a treat! I hope it benefits some of you.

The SCRIPT
<#
.SYNOPSIS
Get-EASDeviceReport.ps1 – Exchange Server ActiveSync device report

.DESCRIPTION
Produces a report of ActiveSync device associations in the organization.

.OUTPUTS
Results are output to screen, as well as optional log file, HTML report, and HTML email

.PARAMETER SendEmail
Sends the HTML report via email using the SMTP configuration within the script.

.EXAMPLE
.Get-EASDeviceReport.ps1
Produces a CSV file containing stats for all ActiveSync devices.

.EXAMPLE
.Get-EASDeviceReport.ps1 -SendEmail -MailFrom:exchangeserver@exchangeserverpro.net -MailTo:paul@exchangeserverpro.com -MailServer:smtp.exchangeserverpro.net
Sends an email report with CSV file attached for all ActiveSync devices.

.EXAMPLE
.Get-EASDeviceReport.ps1 -Age 30
Limits the report to devices that have not attempted synced in more than 30 days.

.NOTES
Written by: Paul Cunningham

Find me on:

* My Blog:   http://paulcunningham.me
* Twitter:   https://twitter.com/paulcunningham
* LinkedIn:  http://au.linkedin.com/in/cunninghamp/
* Github:    https://github.com/cunninghamp

For more Exchange Server tips, tricks and news
check out Exchange Server Pro.

* Website:   http://exchangeserverpro.com
* Twitter:   http://twitter.com/exchservpro

License:

The MIT License (MIT)

Copyright (c) 2015 Paul Cunningham

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Change Log:
V1.00, 25/11/2013 – Initial version
V1.01, 11/02/2014 – Added parameters for emailing the report and specifying an “age” to report on
V1.02, 17/02/2014 – Fixed missing $mydir variable and added UTF8 encoding to Export-CSV and Send-MailMessage
V1.03, 19/02/2016 – Added OrganizationalUnit to report, plus minor fixes
#>

#requires -version 2

[CmdletBinding()]
param (

       [Parameter( Mandatory=$false)]
       [switch]$SendEmail,

       [Parameter( Mandatory=$false)]
       [string]$MailFrom,

       [Parameter( Mandatory=$false)]
       [string]$MailTo,

       [Parameter( Mandatory=$false)]
       [string]$MailServer,

    [Parameter( Mandatory=$false)]
    [int]$Age = 0

       )

#……………………………..
# Variables
#……………………………..

$now = Get-Date                                                                          #Used for timestamps
$date = $now.ToShortDateString()                                    #Short date format for email message subject

$report = @()

$stats = @(“DeviceID”,
            “DeviceAccessState”,
            “DeviceAccessStateReason”,
            “DeviceModel”
            “DeviceType”,
            “DeviceFriendlyName”,
            “DeviceOS”,
            “LastSyncAttemptTime”,
            “LastSuccessSync”
          )

$reportemailsubject = “Exchange ActiveSync Device Report – $date”
$myDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$reportfile = “$myDirExchangeActiveSyncDeviceReport.csv”

#……………………………..
# Email Settings
#……………………………..

$smtpsettings = @{
       To =  $MailTo
       From = $MailFrom
    Subject = $reportemailsubject
       SmtpServer = $MailServer
       }

#……………………………..
# Initialize
#……………………………..

$AdminName = “Logon username for Office 365”
$Pass = Get-Content “C:SupportActiveSynccred.txt” | ConvertTo-SecureString
$Cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $AdminName, $Pass

Import-Module MSOnline
Connect-MsolService -Credential $cred
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection
Import-PSSession $Session

#……………………………..
# Script
#……………………………..

Write-Host “Fetching list of mailboxes with EAS device partnerships”

$MailboxesWithEASDevices = @(Get-CASMailbox -Resultsize Unlimited | Where {$_.ActiveSyncEnabled})

Write-Host “$($MailboxesWithEASDevices.count) mailboxes with EAS device partnerships”

Foreach ($Mailbox in $MailboxesWithEASDevices)
{

    $EASDeviceStats = @(Get-MobileDeviceStatistics -Mailbox $Mailbox.Identity -WarningAction SilentlyContinue)

    Write-Host “$($Mailbox.Identity) has $($EASDeviceStats.Count) device(s)”

    $MailboxInfo = Get-Mailbox $Mailbox.Identity | Select DisplayName,PrimarySMTPAddress,OrganizationalUnit

    Foreach ($EASDevice in $EASDeviceStats)
    {
        Write-Host -ForegroundColor Green “Processing $($EASDevice.DeviceID)”

        $lastsyncattempt = ($EASDevice.LastSyncAttemptTime)

        if ($lastsyncattempt -eq $null)
        {
            $syncAge = “Never”
        }
        else
        {
            $syncAge = ($now – $lastsyncattempt).Days
        }

        #Add to report if last sync attempt greater than Age specified
        if ($syncAge -ge $Age -or $syncAge -eq “Never”)
        {
            Write-Host -ForegroundColor Yellow “$($EASDevice.DeviceID) sync age of $syncAge days is greater than $age, adding to report”

            $reportObj = New-Object PSObject
            $reportObj | Add-Member NoteProperty -Name “Display Name” -Value $MailboxInfo.DisplayName
            $reportObj | Add-Member NoteProperty -Name “Organizational Unit” -Value $MailboxInfo.OrganizationalUnit
            $reportObj | Add-Member NoteProperty -Name “Email Address” -Value $MailboxInfo.PrimarySMTPAddress
            $reportObj | Add-Member NoteProperty -Name “Sync Age (Days)” -Value $syncAge

            Foreach ($stat in $stats)
            {
                $reportObj | Add-Member NoteProperty -Name $stat -Value $EASDevice.$stat
            }

            $report += $reportObj
        }
    }
}

Write-Host -ForegroundColor White “Saving report to $reportfile”
$report | Export-Csv -NoTypeInformation $reportfile -Encoding UTF8

if ($SendEmail)
{

    $reporthtml = $report | ConvertTo-Html -Fragment

       $htmlhead=”

                

Report of Exchange ActiveSync device associations with greater than $age days since last sync attempt as of $date. CSV version of report attached to this email.

       $htmltail = “”    

       $htmlreport = $htmlhead + $reporthtml + $htmltail

       Send-MailMessage @smtpsettings -Body $htmlreport -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF8) -Attachments $reportfile
}

STEPS

  1. The script above is all writen by Paul Cunningham! (legend!) the main bit I changed was the section under “Initialize”

This logs into 365 and runs Pauls script unattended, and can run as a windows schedular service

  1. You first need to produce an encrypted text file containing a password for a 365 account.
  2. Run this command in powershell “Read-Host -Prompt “Enter Password” -AsSecureString | ConvertFrom-SecureString | Out-File “FILE PATH” now enter your password (change the output where you want it, this was mine)
  3. Now copy and paste this into the Initialize section of the script.

$AdminName = “username for 365 email address”
$Pass = Get-Content “FILE PATH” | ConvertTo-SecureString
$Cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $AdminName, $Pass

Import-Module MSOnline
Connect-MsolService -Credential $cred
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection
Import-PSSession $Session  

That’s it your good to go! Run this script and put it into a windows scheduler with all the switches explained by Paul.

Thanks! And enjoy!

CLICK TO DOWNLOAD

Note

  • Other modifications I changed to adapt the script was what Tony said in his blog. “Get-ActiveSyncDeviceStatistics” to “Get-MobileDeviceStatistics”
  • I also found changing this section helped with getting everyones devices, for some reason when it was “HasActiveSyncDevicePartnershp” it was only picking up some mailboxes. Maybe someone can shed some light? But i change it to the below, working it out from “Script” and working out what it was  was doing.                     From: “Where {$_.HasActiveSyncDevicePartnership})” To: “Where {$_.ActiveSyncEnabled})” 
  • Make sure you run the script with power script execution set to unrestricted