Have you ever been troubleshooting Exchange Online (EXO) and MSOnline (Azure) objects and wished there was a way to aggregate all the data together into a single object that you could manipulate either via script or pipeline, output via FT, manipulate or otherwise report on?
The following script will accept either UPN or ObjectID, locate the object in MSOnline, then find the associated Exchange online object, either User, MailUser or UserMailbox, and create a new object with a combination of all the object attributes from both Azure and EXO.
Be sure to read the help and examples provided in the function.
<#
.SYNOPSIS
This command will accept either ObjectID or UserPrincipalName, locate the MSOLUser account and combine with the EXO user.
.DESCRIPTION
This command will accept either ObjectID or UserPrincipalName, locate the MSOLUser account and combine with the Exchange Online object, either UserMailbox, MailUser or User to create a new single object with all the attrbutes from both MSOL and EXO.
All MSONLINE attributes will be prefixed with MSOL.
All Exchange Online UserMailBox attributes will be prefixed with EXOMBX.
All Exchange Online MailUser attributes will be prefixed with EXOMUSR.
All Exchange Online User attributes will be prefixed with EXOUSR.
If the object is not a particular type (e.g. Exchange Online Mail User) those attributes won't be included since they would all be null.
Additionally, the boolean values IsEXOMailBox, IsEXOuser and IsEXOMailUser are added to every output object so they can be used for evaluation purposes.
Lastly, if the MSOL user validation status is ERROR, two additional values, MSOLValidationStatusService and MSOLValidationStatusErrorMessage
are added to the object properties with error details.
IMPORTANT :
*** This cmdlet assumes you have the MSONLINE powershell module loaded and have connected to Azure.
*** This cmdlet assumes you have the Exchange Online PSSNAPIN loaded with the PREFIX EXO switch set and have connected to Exchange Online.
.PARAMETER UPN
User Principal Name to be used to search MSONLINE
.PARAMETER ObjectID
Object ID value to be used to search MSONLINE
.EXAMPLE
Get-O365User.ps1 userUPN@tenant.onmicrosoft.com
Passes the value userUPN@tenant.onmicrosoft.com to the script to locate the MSONLINE user
.EXAMPLE
Get-O365User.ps1 -UserPrincipalName userUPN@tenant.onmicrosoft.com
Passes the value userUPN@tenant.onmicrosoft.com to the script to locate the MSONLINE user
.EXAMPLE
Get-O365User.ps1 -ObjectID cd94fe89-4b2e-4bc9-888a-3fc650c96816
Passes the ObjectID value to the script to locate the MSONLINE user
.EXAMPLE
Get-MSOLUser -Userprincipalname XXXXXX@tenant.onmicrosoft.com | Get-O365User
Passes the UserPrincipalName value from the Get-MSOLUser command down the pipeline to the Get-O365User command.
.EXAMPLE
$date = [datetime] "4/1/2014 12:00:00"
Get-MSOLUser -all | where {$_.lastdirsynctime -lt $date} | Get-O365User | Select *Userprin*, *Externalemail*
Finds any MSOLUser who hasn't been dirsynced since April 1, 2014 at noon, passes that list of users down the pipeline
to the Get-O365User command and returns the UserprincipalName and ExternalEmailAddress (if exists) for each user
.INPUTS
UserPrincipalName
ObjectID
.OUTPUTS
Aggregated PSObject
.NOTES
NAME: Get-O365User.ps1
AUTHOR: Darryl Kegg
DATE: 20 April, 2014
EMAIL: dkegg@microsoft.com
REQUIREMENTS:
-Connection to Exchange online with -PREFIX EXO
-Connection to MSONLINE
VERSION HISTORY:
1.0 20 April, 2014
Initial Version
#>
Function Get-O365User
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $false,ValueFromPipeline=$true,ValueFromPipeLineByPropertyName=$true)]
[string]$UserPrincipalName,
[Parameter(Mandatory = $False,ValueFromPipeline=$true,ValueFromPipeLineByPropertyName=$true)]
[string]$ObjectID
)
BEGIN {}
PROCESS{
if ($UserPrincipalName)
{
$msoluser = $( try {Get-MsolUser -UserPrincipalName $UserPrincipalName -ErrorAction SilentlyContinue} catch {$null})
}
if ($ObjectID)
{
$msoluser = $( try {Get-MsolUser -ObjectID $ObjectID -ErrorAction SilentlyContinue} catch {$null})
}
if (!($msoluser)) {write-host -fore Red "MSOLUser provided does not exist";break}
$MSOLUSERproperties = $msoluser | get-member
$objTemplateObject = New-Object psobject
# set variables to null
$exomailbox = $null
$exomailuser = $null
# Get EXOUSER and then branch based on USERMAILBOX versus USER versus MAILUSER
$exouser = get-exouser ($msoluser.userprincipalname) -erroraction silentlycontinue
if (!($exouser))
{
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailBox" -Value $false
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailuser" -Value $false
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOuser" -Value $false
}
if ($exouser -and $exouser.recipienttype -eq "UserMailbox")
{
$exomailbox = get-exomailbox $exouser.userprincipalname
$exouser = $null
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailBox" -Value $true
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailuser" -Value $false
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOuser" -Value $true
}
if ($exouser -and $exouser.recipienttype -eq "MailUser")
{
$exomailuser = get-exomailuser $exouser.userprincipalname
$exouser = $null
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailBox" -Value $false
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailuser" -Value $true
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOuser" -Value $true
}
if ($exouser -and $exouser.RecipientType -eq "User")
{
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailBox" -Value $false
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOMailuser" -Value $false
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "IsEXOuser" -Value $true
}
# create the properties for MSOLUSER
foreach ($property in $MSOLUSERproperties)
{
if ($property.membertype -eq "Property")
{
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "MSOL$($property.Name)" -Value $Null
}
}
# Add 2 properties if the object has a validation status of ERROR
if ($msoluser.validationstatus -eq "Error")
{
# add members here if its in validation status error
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "MSOLValidationStatusService" -Value $Null
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "MSOLValidationStatusErrorMessage" -Value $Null
}
# Create the properties for UserMailBox if exists
if ($exoMailbox)
{
$EXOMAILBOXproperties = $exomailbox | get-member
foreach ($property in $EXOMAILBOXproperties)
{
if ($property.membertype -eq "Property")
{
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "EXOMBX$($property.Name)" -Value $Null
}
}
}
if ($exomailuser)
{
$exomailuser = get-exomailuser ($msoluser.UserPrincipalName) -erroraction silentlycontinue
$EXOMAILUSERproperties = $exomailuser | Get-Member
foreach ($property in $EXOMAILUSERproperties)
{
if ($property.membertype -eq "Property")
{
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "EXOMUSR$($property.Name)" -Value $Null
}
}
}
if ($exouser)
{
$EXOUSERproperties = $exouser | Get-Member
foreach ($property in $EXOUSERproperties)
{
if ($property.membertype -eq "Property")
{
$objTemplateObject | Add-Member -MemberType NoteProperty -Name "EXOUSR$($property.Name)" -Value $Null
}
}
}
# Done deciding what properties to add to the new Object, now lets populate those values
$objTemp = $objTemplateObject | Select-Object *
# populate the MSOLUSER values
foreach ($property in $MSOLUSERproperties)
{
if ($property.membertype -eq "Property")
{
$PropName = "MSOL$($property.name)"
$objTemp.$propname = $msoluser.($property.Name)
}
}
if ($msoluser.ValidationStatus -eq "Error")
{
$objTemp.MSOLValidationStatusService = $msoluser.Errors.ErrorDetail.Name.split("/")[0]
$objTemp.MSOLValidationStatusErrorMessage = $msoluser.Errors.ErrorDetail.ObjectErrors.ErrorRecord.ErrorDescription
}
# populate the EXOMAILBOX values
If ($exomailbox)
{
foreach ($property in $EXOMAILBOXproperties)
{
if ($property.membertype -eq "Property")
{
$PropName = "EXOMBX$($property.name)"
$objTemp.$propname = $exomailbox.($property.Name)
}
}
}
# populate the MAILUSER values
If ($exomailuser)
{
foreach ($property in $EXOMAILUSERproperties)
{
if ($property.membertype -eq "Property")
{
$PropName = "EXOMUSR$($property.name)"
$objTemp.$propname = $exomailuser.($property.Name)
}
}
}
# populate the EXOUSER values
If ($exouser)
{
foreach ($property in $EXOUSERproperties)
{
if ($property.membertype -eq "Property")
{
$PropName = "EXOUSR$($property.name)"
$objTemp.$propname = $exouser.($property.Name)
}
}
}
$objtemp
}
}#PROCESS