M365 Migration | Exchange Inventory v2
So, in post M365 Migration | Exchange Inventory, an Exchange Online inventory was described. Every part that needed to be inventoried was written down and explained. After creating that post I started to improve the script. Running it could take about 24h. To improve the inventory speed, I started to see what could go better and faster.
Identities
Getting all the information of the identities in a tenant can take some time. What if we only request the data that we would like to have?
Mailboxes
# getting all the requested information
[array]$mailboxes = Get-Mailbox -ResultSize Unlimited | Select Migrate,DisplayName,RecipientTypeDetails,isMailboxEnabled,usageLocation,PrimarySMTPAddress,itemCount,DeletedItemsCount,TotalItemSize,legacyExchangeDN,emailaddresses,userprincipalname,retentionpolicy,ForwardingAddress,ForwardingSMTPAddress,UseDatabaseQuotaDefaults,IssueWarningQuota,RulesQuota,ExchangeGUID,ArchiveQuota,ArchiveWarningQuota,ArchiveGuid,ProhibitSendQuota,ProhibitSendReceiveQuota,RecoverableItemsQuota,RecoverableItemsWarningQuota,CalendarLoggingQuota,HiddenFromAddressListsEnabled,FullAccess,SendAs
# rewrite the arrays in the array
$Mailboxes | Foreach-Object -Parallel {
$PSItem.EmailAddresses = $PSItem.EmailAddresses -join ","
}
# add mailbox permissions and statistics
ForEach ($Mailbox in $Mailboxes) {
Write-Progress -Activity "Processing user $($Mailbox.primarysmtpaddress)" -PercentComplete (($Count / $Mailboxes.count) * 100)
Start-Sleep -Milliseconds 200
$permissions = Get-EXOMailboxPermission -Identity $Mailbox.PrimarySMTPAddress | ? { ($_.IsInherited -eq $False) -and -not ($_.User -Like "NT AUTHORITY*") }
$fullAccess = $permissions | Where-Object { $permissions.AccessRights -eq "FullAccess" }
$permissions = Get-RecipientPermission -Identity $Mailbox.PrimarySMTPAddress | ? { ($_.IsInherited -eq $False) -and -not ($_.Trustee -Like "NT AUTHORITY*") }
$SendAs = $permissions | Where-Object { $permissions.AccessRights -eq "SendAs" }
$Stats = Get-EXOMailboxStatistics $Mailbox.primarysmtpaddress
$Mailbox.FullAccess = $($fullAccess.User) -join (",")
$Mailbox.SendAs = $($sendas.Trustee) -join (",")
$Mailbox.itemcount = $Stats.ItemCount
$Mailbox.DeletedItemsCount = $stats.DeletedItemCount
$mailbox.TotalItemSize= $Stats.TotalItemSize
}
Mailusers
# getting all the requested information
[array]$Mailusers = Get-MailUser -ResultSize Unlimited | Select Migrate,DisplayName,RecipientTypeDetails,isMailboxEnabled,usageLocation,PrimarySMTPAddress,itemCount,DeletedItemsCount,TotalItemSize,legacyExchangeDN,emailaddresses,userprincipalname,retentionpolicy,ForwardingAddress,ForwardingSMTPAddress,UseDatabaseQuotaDefaults,IssueWarningQuota,RulesQuota,ExchangeGUID,ArchiveQuota,ArchiveWarningQuota,ArchiveGuid,ProhibitSendQuota,ProhibitSendReceiveQuota,RecoverableItemsQuota,RecoverableItemsWarningQuota,CalendarLoggingQuota,HiddenFromAddressListsEnabled,FullAccess,SendAs
# rewrite the arrays in the array
$Mailusers | Foreach-Object -Parallel {
$PSItem.EmailAddresses = $PSItem.EmailAddresses -join ","
}
Mailcontacts
# getting all the requested information
[array]$MailContacts = Get-Contact -ResultSize Unlimited | Select Migrate,DisplayName,RecipientTypeDetails,WindowsEmailAddress,ForwardingAddress,HiddenfromAddressListsEnabled
Combine the identities
$Identities = $Mailboxes + $Mailusers + $MailContacts
# sorting the objects
$Identities = $Identities | Sort-Object -Property "DisplayName"
Groups
Instead of doing for each group creating an PSCustomObject, I created an array with the information that was requested up front in the command.
When the array already is filled, you don’t need to create an PSCustomObject. Because some fields are still arrays in the array, we wanted to split them up like for example all the emailaddresses and members.
Unified Groups
# getting all the unified groups with the fields we want
[array]$UnifiedGroups = Get-Unifiedgroup -Resultsize Unlimited | Select AccessType, Displayname,Description,PrimarySMTPAddress,grouptype,EmailAddresses,RecipientType,RecipientTypeDetails,GroupMemberCount,GroupExternalMemberCount,AllowAddGuests,HiddenFromExchangeClientsEnabled,ManagedBy,AuditLogAgeLimit,ModeratedBy,ModerationEnabled,SendModerationNotifications,BypassModerationFromSendersOrMembers,SharePointSiteUrl,Language,SubscriptionEnabled,WelcomeMessageEnabled,ConnectorsEnabled,IsMembershipDynamic,ResourceBehaviorOptions
# rewriting the arrays in the array
$UnifiedGroups | ForEach-Object -Parallel {
$PSItem.emailaddresses = $PSItem.emailaddresses -join ","
$PSItem.ManagedBy = $PSItem.ManagedBy -join ","
$PSItem.BypassModerationFromSendersOrMembers = $PSItem.BypassModerationFromSendersOrMembers -join ","
$PSItem.ResourceBehaviorOptions = $PSItem.ResourceBehaviorOptions -join ","
}
# adding members to the array
ForEach ($Group in $UnifiedGroups){
$members = $null
$members = Get-UnifiedGroupLinks -Linktype Members -identity $Group.PrimarySMTPAddress -Resultsize Unlimited
$UnifiedGroups | Add-Member -Membertype NoteProperty -Name Group -Value "Unified" -Force
$UnifiedGroups | Add-Member -Membertype NoteProperty -Name Members -Value $($Members.PrimarySMTPAddress -join ",") -Force
}
Distribution Groups
# getting all the distributionlists
[array]$distributionGroups = Get-DistributionGroup -Resultsize Unlimited | Select AccessType, Displayname,Description,PrimarySMTPAddress,grouptype,EmailAddresses,RecipientType,RecipientTypeDetails,GroupMemberCount,GroupExternalMemberCount,AllowAddGuests,HiddenFromExchangeClientsEnabled,ManagedBy,AuditLogAgeLimit,ModeratedBy,ModerationEnabled,SendModerationNotifications,BypassModerationFromSendersOrMembers,SharePointSiteUrl,Language,SubscriptionEnabled,WelcomeMessageEnabled,ConnectorsEnabled,IsMembershipDynamic,ResourceBehaviorOptions
# rewriting the arrays in the array
$distributionGroups | ForEach-Object -Parallel {
$PSItem.emailaddresses = $PSItem.emailaddresses -join ","
$PSItem.ManagedBy = $PSItem.ManagedBy -join ","
$PSItem.BypassModerationFromSendersOrMembers = $PSItem.BypassModerationFromSendersOrMembers -join ","
$PSItem.ResourceBehaviorOptions = $PSItem.ResourceBehaviorOptions -join ","
}
# adding the members to the array
ForEach ($Group in $distributionGroups){
$members = $null
$members = Get-DistributionGroupMember -Identity $Group.DisplayName -Resultsize Unlimited
$distributionGroups| Add-Member -Membertype NoteProperty -Name Group -Value "Distribution" -Force
$distributionGroups| Add-Member -Membertype NoteProperty -Name Members -Value $($Members.PrimarySMTPAddress -join ",") -Force
}
Combine the groups
$Groups = $Unifiedgroups + $Distributiongroups
# sorting the groups
$Groups = $Groups | Sort-Object -Property "DisplayName"