PowerShell

Office 365 – Report containing User Information and Mailbox Usage

Working with Office 365 is my bread and butter in the last few months. I'm a System Architect and I am dropped in multiple projects, both new and old, to fix certain aspect and get out before anyone sees me. One of the common tasks I get is to provide some data about users stored in Office 365. Following is a report that can give you answers to following questions:

User information (Display Name, User Principal Name, First Name, Last Name, Country, City, Department, and Usage Location)
Mailbox information (Primary Email Address, All Emaill Addresses, Mailbox Size, Mailbox Item Count, Mailbox Archive Size, Mailbox Archive Item Count and so on)
User License Information (which licenses user has assigned in their long name format)

While are probably some reports that cover this already I thought I need my own. It should be easy to read and understand what is happening. It has some little things that make this report unique. For example, it converts licenses to their long name format. I management doesn't know what DESKLESSPACK as license means (it's Office 365 (Plan F1))There are around 150 license translations added so it should cover most of your needs. The second feature is the ability to define Size Type and Size Precision. This allows you to sort your mailboxes based on the size you want to sort. You don't have to play with converting it yourself. And last excellent functionality is that it combines output from three different sources. Get-Mailbox, Get-MailboxStatistics, and Get-MsolUser.

Office 365 User Data Script

Below you can find the code for the report. I have a plan to gather more of those reports and bundle them up as part of PSWinDocumentation project. The goal would be that you install the module and can create full documentation for Active Directory, Office 365 but also use reports on demand. That means any updates to that report will go to PSWinDocumentation project later on.

Warning
Mailbox Logon Time and LogOff Time may not represent proper information. In Office 365 you should be using AuditLog for that. I have plans to update the code later on, but at the moment you're on your own with this one.
function Get-ReportO365Mailboxes {
    [CmdletBinding()]
    param(
        [string] $Prefix,
        [validateset("Bytes", "KB", "MB", "GB", "TB")][string]$SizeIn = 'MB',
        [alias('Precision')][int]$SizePrecision = 2,
        [switch] $ReturnAll,
        [switch] $SkipAvailability
    )
    $PropertiesMailbox = 'DisplayName', 'UserPrincipalName', 'PrimarySmtpAddress', 'EmailAddresses', 'HiddenFromAddressListsEnabled', 'Identity', 'ExchangeGuid', 'ArchiveGuid', 'ArchiveQuota', 'ArchiveStatus', 'WhenCreated', 'WhenChanged', 'Guid', 'MailboxGUID'
    $PropertiesAzure = 'FirstName', 'LastName', 'Country', 'City', 'Department', 'Office', 'UsageLocation', 'Licenses', 'WhenCreated', 'UserPrincipalName', 'ObjectID'
    $PropertiesMailboxStats = 'DisplayName', 'LastLogonTime', 'LastLogoffTime', 'TotalItemSize', 'ItemCount', 'TotalDeletedItemSize', 'DeletedItemCount', 'OwnerADGuid', 'MailboxGuid'
    $PropertiesMailboxStatsArchive = 'DisplayName', 'TotalItemSize', 'ItemCount', 'TotalDeletedItemSize', 'DeletedItemCount', 'OwnerADGuid', 'MailboxGuid'

    if ($SkipAvailability) {
        $Commands = Test-AvailabilityCommands -Commands "Get-$($Prefix)Mailbox", "Get-$($Prefix)MsolUser", "Get-$($Prefix)MailboxStatistics"
        if ($Commands -contains $false) {
            Write-Warning "Get-ReportO365Mailboxes - One of commands Get-$($Prefix)Mailbox, Get-$($Prefix)MsolUser, Get-$($Prefix)MailboxStatistics is not available. Make sure connectivity to Office 365 exists."
            return 
        }
    }

    $Object = [ordered] @{}
    Write-Verbose "Get-ReportO365Mailboxes - Getting all mailboxes"
    $Object.Mailboxes = & "Get-$($Prefix)Mailbox" -ResultSize Unlimited | Select-Object $PropertiesMailbox
    Write-Verbose "Get-ReportO365Mailboxes - Getting all Azure AD users"
    $Object.Azure = Get-MsolUser -All | Select-Object $PropertiesAzure
    $Object.MailboxStatistics = [System.Collections.Generic.List[object]]::new()
    $Object.MailboxStatisticsArchive = [System.Collections.Generic.List[object]]::new()
    foreach ($Mailbox in $Object.Mailboxes) {
        Write-Verbose "Get-ReportO365Mailboxes - Processing Mailbox Statistics for Mailbox $($Mailbox.UserPrincipalName)"
        ($Object.MailboxStatistics).Add( (& "Get-$($Prefix)MailboxStatistics" -Identity $Mailbox.Guid.Guid | Select-Object $PropertiesMailboxStats))
        if ($Mailbox.ArchiveStatus -eq "Active") {
            ($Object.MailboxStatisticsArchive).Add((& "Get-$($Prefix)MailboxStatistics" -Identity $Mailbox.Guid.Guid -Archive | Select-Object $PropertiesMailboxStatsArchive))
        }
    }

    Write-Verbose "Get-ReportO365Mailboxes - Preparing output data"
    $Object.Output = foreach ($Mailbox in $Object.Mailboxes) {
        $Azure = $Object.Azure | Where-Object { $_.UserPrincipalName -eq $Mailbox.UserPrincipalName }
        $MailboxStats = $Object.MailboxStatistics | Where-Object { $_.MailboxGuid.Guid -eq $Mailbox.ExchangeGuid.Guid }
        $MailboxStatsArchive = $Object.MailboxStatisticsArchive | Where-Object { $_.MailboxGuid.Guid -eq $Mailbox.ArchiveGuid.Guid }

        [PSCustomObject][ordered] @{
            DiplayName               = $Mailbox.DisplayName
            UserPrincipalName        = $Mailbox.UserPrincipalName
            FirstName                = $Azure.FirstName
            LastName                 = $Azure.LastName
            Country                  = $Azure.Country
            City                     = $Azure.City
            Department               = $Azure.Department
            Office                   = $Azure.Office
            UsageLocation            = $Azure.UsageLocation
            License                  = Convert-Office365License -License $Azure.Licenses.AccountSkuID
            UserCreated              = $Azure.WhenCreated

            PrimaryEmailAddress      = $Mailbox.PrimarySmtpAddress
            AllEmailAddresses        = Convert-ExchangeEmail -Emails $Mailbox.EmailAddresses -Separator ', ' -RemoveDuplicates -RemovePrefix -AddSeparator

            MailboxLogOn             = $MailboxStats.LastLogonTime
            MailboxLogOff            = $MailboxStats.LastLogoffTime

            MailboxSize              = Convert-ExchangeSize -Size $MailboxStats.TotalItemSize -To $SizeIn -Default '' -Precision $SizePrecision

            MailboxItemCount         = $MailboxStats.ItemCount

            MailboxDeletedSize       = Convert-ExchangeSize -Size $MailboxStats.TotalDeletedItemSize -To $SizeIn -Default '' -Precision $SizePrecision
            MailboxDeletedItemsCount = $MailboxStats.DeletedItemCount

            MailboxHidden            = $Mailbox.HiddenFromAddressListsEnabled
            MailboxCreated           = $Mailbox.WhenCreated # WhenCreatedUTC
            MailboxChanged           = $Mailbox.WhenChanged # WhenChangedUTC

            ArchiveStatus            = $Mailbox.ArchiveStatus
            ArchiveQuota             = Convert-ExchangeSize -Size $Mailbox.ArchiveQuota -To $SizeIn -Default '' -Display
            ArchiveSize              = Convert-ExchangeSize -Size $MailboxStatsArchive.TotalItemSize -To $SizeIn -Default '' -Precision $SizePrecision
            ArchiveItemCount         = Convert-ExchangeItems -Count $MailboxStatsArchive.ItemCount -Default ''

            ArchiveDeletedSize       = Convert-ExchangeSize -Size $MailboxStatsArchive.TotalDeletedItemSize -To $SizeIn -Default '' -Precision $SizePrecision
            ArchiveDeletedItemsCount = Convert-ExchangeItems -Count $MailboxStatsArchive.DeletedItemCount -Default ''
            # Adding GUID so it's possible to match other data
            Guid                     = $Mailbox.Guid.Guid
            ObjectID                 = $Mailbox.ExternalDirectoryObjectId
        }
    }
    if ($ReturnAll) {
        return $Object
    } else {
        return $Object.Output
    }
}

You can use it to output to PowerShell Console, GridView, CSV or Microsoft Excel directly.

$Report = Get-ReportO365Mailboxes 
# To Gridview
$Report | Out-GridView

# To Excel (you need PSWriteExcel)
$Report | ConvertTo-Excel -FilePath "$env:USERPROFILE\Desktop\MyReport.xlsx" -ExcelWorkSheetName 'Export of Mailboxes' -AutoFilter -AutoFit -FreezeTopRow

# To Console
$Report | Format-Table Mailbox*, Archive*
$Report | Format-Table -AutoSize *
Prerequisite

This report uses PSSharedGoods PowerShell Module. Some of the functions that it uses such as Convert-ExchangeSize, Convert-ExchangeEmail, Convert-Office365License are part of that module. It's required for you to have that module. If you don't want to do that all those functions are shared on GitHub and you're free to take it apart and extract those functions for your use. You can also scroll below to see how they look like now. But if you want to keep it up to date I would suggest sticking with that PSSharedGoods module that I try to maintain for my own Clients.

Install-Module PSSharedGoods -Force

Also before you can use this script you need to be connected to Office 365 – especially to Connect-MsolService and Exchange Online. If you're using my module, you could use something like the code below to connect. It's a simple True/False based on the selection of services and making sure your data is correct. Of course, it requires you to have all pre-requisites installed. So you need all those Office 365 modules that Microsoft provides, or you will get errors. I'm slowly working on an optimized version of this Connectivity Pack where I'll bundle this up to one command, probably with the installation of required modules from Microsoft but haven't had time to dive into it since it works for me entirely.

Clear-Host
Import-Module PSSharedGoods -Force

$Configuration = @{
    Options    = @{
        LogsPath = 'C:\Support\Logs\Automated.log'
    }
    Office365  = [ordered] @{
        Credentials        = [ordered] @{
            Username                  = 'przemyslaw.klys@evotec.pl'
            Password                  = 'C:\Support\Important\Password-O365-Evotec.txt'
            PasswordAsSecure          = $true
            PasswordFromFile          = $true
            MultiFactorAuthentication = $false
        }
        Azure              = [ordered] @{
            Use         = $true
            SessionName = 'O365 Azure MSOL' # MSOL
        }
        AzureAD            = [ordered] @{
            Use         = $true
            SessionName = 'O365 Azure AD' # Azure
            Prefix      = ''
        }
        ExchangeOnline     = [ordered] @{
            Use            = $true
            Authentication = 'Basic'
            ConnectionURI  = 'https://outlook.office365.com/powershell-liveid/'
            Prefix         = 'O365'
            SessionName    = 'O365 Exchange'
        }
        SecurityCompliance = [ordered] @{
            Use            = $false
            Authentication = 'Basic'
            ConnectionURI  = 'https://ps.compliance.protection.outlook.com/PowerShell-LiveId'
            Prefix         = 'O365'
            SessionName    = 'O365 Security And Compliance'
        }
        SharePointOnline   = [ordered] @{
            Use           = $false
            ConnectionURI = 'https://evotecpoland-admin.sharepoint.com'
        }
        SkypeOnline        = [ordered] @{
            Use         = $false
            SessionName = 'O365 Skype'
        }
        Teams              = [ordered] @{
            Use         = $false
            Prefix      = ''
            SessionName = 'O365 Teams'
        }
    }
    OnPremises = @{
        Credentials = [ordered] @{
            Username         = 'przemyslaw.klys@evotec.pl'
            Password         = 'C:\Support\Important\Password-O365-Evotec.txt'
            PasswordAsSecure = $true
            PasswordFromFile = $true
        }
        Exchange    = [ordered] @{
            Use            = $false
            Authentication = 'Kerberos'
            ConnectionURI  = 'http://PLKATO365Exch.evotec.pl/PowerShell'
            Prefix         = ''
            SessionName    = 'Exchange'
        }
    }
}

$Connected = [System.Collections.Generic.List[object]]::new()

$BundleCredentials = $Configuration.Office365.Credentials
$BundleCredentialsOnPremises = $Configuration.OnPremises.Credentials

if ($Configuration.Office365.Azure.Use) {
    $Connected.Add((Connect-WinAzure @BundleCredentials -Output -SessionName $Configuration.Office365.Azure.SessionName -Verbose))
}
if ($Configuration.Office365.AzureAD.Use) {
    $Connected.Add((Connect-WinAzureAD @BundleCredentials -Output -SessionName $Configuration.Office365.AzureAD.SessionName -Verbose))
}
if ($Configuration.Office365.ExchangeOnline.Use) {
    $Connected.Add((Connect-WinExchange @BundleCredentials -Output -SessionName $Configuration.Office365.ExchangeOnline.SessionName -ConnectionURI $Configuration.Office365.ExchangeOnline.ConnectionURI -Authentication $Configuration.Office365.ExchangeOnline.Authentication -Verbose))
}
if ($Configuration.Office365.SecurityCompliance.Use) {
    $Connected.Add((Connect-WinSecurityCompliance @BundleCredentials -Output -SessionName $Configuration.Office365.SecurityCompliance.SessionName -ConnectionURI $Configuration.Office365.SecurityCompliance.ConnectionURI -Authentication $Configuration.Office365.SecurityCompliance.Authentication -Verbose))
}
if ($Configuration.Office365.SkypeOnline.Use) {
    $Connected.Add((Connect-WinSkype @BundleCredentials -Output -SessionName $Configuration.Office365.SkypeOnline.SessionName -Verbose))
}
if ($Configuration.Office365.SharePointOnline.Use) {
    $Connected.Add((Connect-WinSharePoint @BundleCredentials -Output -SessionName $Configuration.Office365.SharePointOnline.SessionName -ConnectionURI $Configuration.Office365.SharePointOnline.ConnectionURI -Verbose))
}
if ($Configuration.Office365.MicrosoftTeams.Use) {
    $Connected.Add((Connect-WinTeams @BundleCredentials -Output -SessionName $Configuration.Office365.Teams.SessionName -Verbose))
}
if ($Configuration.OnPremises.Exchange.Use) {
    $Connected.Add((Connect-WinExchange @BundleCredentialsOnPremises -Output -SessionName $Configuration.OnPremises.Exchange.SessionName -ConnectionURI $Configuration.OnPremises.Exchange.ConnectionURI -Authentication $Configuration.OnPremises.Exchange.Authentication -Verbose))
}

if ($Connected.Status -contains $false) {
    foreach ($C in $Connected | Where-Object { $_.Status -eq $false }) {
        Write-Color -Text 'Connecting to tenant failed for ', $C.Output, ' with error ', $Connected.Extended -Color White, Red, White, Red -LogFile $Configuration.Options.LogsPath
    }
    return
}

If you're wondering how you can create that Secure Password thing I've actually prepared little module called PSMyPassword that helps me do it for my internal needs.

Install-Module PSMyPassword -Force
Protect-MyPassword -UserName "przemyslaw.klys@domain.pl" -Output File -FilePath 'C:\YourPaath.txt'

It should ask you for a password and generate that file for you. If you prefer to do it yourself here's the code I'm using in that module. Keep in mind that I've bigger plans for that module so you may remember that name, just in case 🙂

function Protect-MyPassword {
    param (
        [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $false)][string] $UserName,
        [Parameter(Position = 1, Mandatory = $true, ValueFromPipeline = $false)][string] $Password,
        [Parameter(Position = 2, Mandatory = $true, ValueFromPipeline = $false)][alias('FilePath')][string] $Path,
        [validateset("File", 'Screen')][string] $Output = 'Screen',
        [string] $AsUserName,
        [string] $AsPassword
    )
    $SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString
    if ($Output -eq 'File') {
        if ($Path -ne '') {
            $SecurePassword | Out-File -FilePath $Path

            $FullPath = Resolve-Path $Path
            if ($FullPath) {
                Write-Color -Text 'Protect-MyPassword', ' - ', 'secure file created in path ', $FullPath -Color Yellow, White, White, Yellow
            } else {
                Write-Color -Text 'Protect-MyPassword', ' - ', "can't find file at ", $FullPath -Color Yellow, White, White, Yellow
            }
        } else {
            Write-Color -Text 'Protect-MyPassword - File Path ', $Path, " is empty. Terminating." -Color White, Red, White
        }
    } elseif ($Output -eq 'Screen') {
        return $SecurePassword
    }
    return
}
Convert-Office365License

In case you would like to use Convert-Office365License command in your own modules here's an example.

Convert-Office365License -License 'VISIOCLIENT','PROJECTONLINE_PLAN_1','test'
Convert-Office365License -License "Office 365 (Plan A3) for Faculty","Office 365 (Enterprise Preview)", 'test' -ToSku

It can convert licenses both ways from SKU to FullName and vice versa. It can also take multiple licenses at once. If it doesn't know how to translate it, it leaves it intact. Feel free to let me know if it fails to do a conversion and we can add it to the list. You can also make a PR on GitHub.

function Convert-Office365License {
    <#
    .SYNOPSIS
    This function helps converting Office 365 licenses from/to their SKU equivalent
    
    .DESCRIPTION
        This function helps converting Office 365 licenses from/to their SKU equivalent
    
    .PARAMETER License
    License SKU or License Name. Takes multiple values.
    
    .PARAMETER ToSku
    Converts license name to SKU

    .PARAMETER Separator
    
    .PARAMETER ReturnArray
  
    .EXAMPLE
    Convert-Office365License -License 'VISIOCLIENT','PROJECTONLINE_PLAN_1','test','tenant:VISIOCLIENT'

    .EXAMPLE
    Convert-Office365License -License "Office 365 (Plan A3) for Faculty","Office 365 (Enterprise Preview)", 'test' -ToSku
    #>
  
    [CmdletBinding()]
    param(
        [string[]] $License,
        [alias('SKU')][switch] $ToSku,
        [string] $Separator = ', ',
        [switch] $ReturnArray
    )
    if (-not $ToSku) {
        $ConvertedLicenses = foreach ($L in $License) {
            # Remove tenant from SKU
            if ($L -match ':') {
                $Split = $L -split ':'
                $L = $Split[-1]
            }
            
            $Conversion = $Script:O365SKU[$L]
            if ($null -eq $Conversion) {
                $L
            } else {
                $Conversion
            }
        }
    } else {
        $ConvertedLicenses = foreach ($L in $License) {
            $Conversion = $Script:O365SKU.GetEnumerator() | Where-Object {$_.Value -eq $L }
            if ($null -eq $Conversion) {
                $L
            } else {
                $Conversion.Name
            }
        }
    }
    if ($ReturnArray) {
        return $ConvertedLicenses
    } else {
        return $ConvertedLicenses -join ', '
    }
}

This script utilizes the following data table.

$Script:O365SKU = @{
    "O365_BUSINESS_ESSENTIALS"           = "Office 365 Business Essentials"
    "O365_BUSINESS_PREMIUM"              = "Office 365 Business Premium"
    "DESKLESSPACK"                       = "Office 365 (Plan F1)"
    "DESKLESSWOFFPACK"                   = "Office 365 (Plan F2)"
    "LITEPACK"                           = "Office 365 (Plan P1)"
    "EXCHANGESTANDARD"                   = "Office 365 Exchange Online Only"
    "STANDARDPACK"                       = "Enterprise Plan E1"
    "STANDARDWOFFPACK"                   = "Office 365 (Plan E2)"
    "ENTERPRISEPACK"                     = "Enterprise Plan E3"
    "ENTERPRISEPACKLRG"                  = "Enterprise Plan E3"
    "ENTERPRISEWITHSCAL"                 = "Enterprise Plan E4"
    "STANDARDPACK_STUDENT"               = "Office 365 (Plan A1) for Students"
    "STANDARDWOFFPACKPACK_STUDENT"       = "Office 365 (Plan A2) for Students"
    "ENTERPRISEPACK_STUDENT"             = "Office 365 (Plan A3) for Students"
    "ENTERPRISEWITHSCAL_STUDENT"         = "Office 365 (Plan A4) for Students"
    "STANDARDPACK_FACULTY"               = "Office 365 (Plan A1) for Faculty"
    "STANDARDWOFFPACKPACK_FACULTY"       = "Office 365 (Plan A2) for Faculty"
    "ENTERPRISEPACK_FACULTY"             = "Office 365 (Plan A3) for Faculty"
    "ENTERPRISEWITHSCAL_FACULTY"         = "Office 365 (Plan A4) for Faculty"
    "ENTERPRISEPACK_B_PILOT"             = "Office 365 (Enterprise Preview)"
    "STANDARD_B_PILOT"                   = "Office 365 (Small Business Preview)"
    "VISIOCLIENT"                        = "Visio Pro Online"
    "POWER_BI_ADDON"                     = "Office 365 Power BI Addon"
    "POWER_BI_INDIVIDUAL_USE"            = "Power BI Individual User"
    "POWER_BI_STANDALONE"                = "Power BI Stand Alone"
    "POWER_BI_STANDARD"                  = "Power-BI Standard"
    "PROJECTESSENTIALS"                  = "Project Lite"
    "PROJECTCLIENT"                      = "Project Professional"
    "PROJECTONLINE_PLAN_1"               = "Project Online"
    "PROJECTONLINE_PLAN_2"               = "Project Online and PRO"
    "ProjectPremium"                     = "Project Online Premium"
    "ECAL_SERVICES"                      = "ECAL"
    "EMS"                                = "Enterprise Mobility Suite"
    "RIGHTSMANAGEMENT_ADHOC"             = "Windows Azure Rights Management"
    "MCOMEETADV"                         = "PSTN conferencing"
    "SHAREPOINTSTORAGE"                  = "SharePoint storage"
    "PLANNERSTANDALONE"                  = "Planner Standalone"
    "CRMIUR"                             = "CMRIUR"
    "BI_AZURE_P1"                        = "Power BI Reporting and Analytics"
    "INTUNE_A"                           = "Windows Intune Plan A"
    "PROJECTWORKMANAGEMENT"              = "Office 365 Planner Preview"
    "ATP_ENTERPRISE"                     = "Exchange Online Advanced Threat Protection"
    "EQUIVIO_ANALYTICS"                  = "Office 365 Advanced eDiscovery"
    "AAD_BASIC"                          = "Azure Active Directory Basic"
    "RMS_S_ENTERPRISE"                   = "Azure Active Directory Rights Management"
    "AAD_PREMIUM"                        = "Azure Active Directory Premium"
    "MFA_PREMIUM"                        = "Azure Multi-Factor Authentication"
    "STANDARDPACK_GOV"                   = "Microsoft Office 365 (Plan G1) for Government"
    "STANDARDWOFFPACK_GOV"               = "Microsoft Office 365 (Plan G2) for Government"
    "ENTERPRISEPACK_GOV"                 = "Microsoft Office 365 (Plan G3) for Government"
    "ENTERPRISEWITHSCAL_GOV"             = "Microsoft Office 365 (Plan G4) for Government"
    "DESKLESSPACK_GOV"                   = "Microsoft Office 365 (Plan F1) for Government"
    "ESKLESSWOFFPACK_GOV"                = "Microsoft Office 365 (Plan F2) for Government"
    "EXCHANGESTANDARD_GOV"               = "Microsoft Office 365 Exchange Online (Plan 1) only for Government"
    "EXCHANGEENTERPRISE_GOV"             = "Microsoft Office 365 Exchange Online (Plan 2) only for Government"
    "SHAREPOINTDESKLESS_GOV"             = "SharePoint Online Kiosk"
    "EXCHANGE_S_DESKLESS_GOV"            = "Exchange Kiosk"
    "RMS_S_ENTERPRISE_GOV"               = "Windows Azure Active Directory Rights Management"
    "OFFICESUBSCRIPTION_GOV"             = "Office ProPlus"
    "MCOSTANDARD_GOV"                    = "Lync Plan 2G"
    "SHAREPOINTWAC_GOV"                  = "Office Online for Government"
    "SHAREPOINTENTERPRISE_GOV"           = "SharePoint Plan 2G"
    "EXCHANGE_S_ENTERPRISE_GOV"          = "Exchange Plan 2G"
    "EXCHANGE_S_ARCHIVE_ADDON_GOV"       = "Exchange Online Archiving"
    "EXCHANGE_S_DESKLESS"                = "Exchange Online Kiosk"
    "SHAREPOINTDESKLESS"                 = "SharePoint Online Kiosk"
    "SHAREPOINTWAC"                      = "Office Online"
    "YAMMER_ENTERPRISE"                  = "Yammer for the Starship Enterprise"
    "EXCHANGE_L_STANDARD"                = "Exchange Online (Plan 1)"
    "MCOLITE"                            = "Lync Online (Plan 1)"
    "SHAREPOINTLITE"                     = "SharePoint Online (Plan 1)"
    "OFFICE_PRO_PLUS_SUBSCRIPTION_SMBIZ" = "Office ProPlus"
    "EXCHANGE_S_STANDARD_MIDMARKET"      = "Exchange Online (Plan 1)"
    "MCOSTANDARD_MIDMARKET"              = "Lync Online (Plan 1)"
    "SHAREPOINTENTERPRISE_MIDMARKET"     = "SharePoint Online (Plan 1)"
    "OFFICESUBSCRIPTION"                 = "Office ProPlus"
    "YAMMER_MIDSIZE"                     = "Yammer"
    "DYN365_ENTERPRISE_PLAN1"            = "Dynamics 365 Customer Engagement Plan Enterprise Edition"
    "ENTERPRISEPREMIUM_NOPSTNCONF"       = "Enterprise E5 (without Audio Conferencing)"
    "ENTERPRISEPREMIUM"                  = "Enterprise E5 (with Audio Conferencing)"
    "MCOSTANDARD"                        = "Skype for Business Online Standalone Plan 2"
    "PROJECT_MADEIRA_PREVIEW_IW_SKU"     = "Dynamics 365 for Financials for IWs"
    "STANDARDWOFFPACK_IW_STUDENT"        = "Office 365 Education for Students"
    "STANDARDWOFFPACK_IW_FACULTY"        = "Office 365 Education for Faculty"
    "EOP_ENTERPRISE_FACULTY"             = "Exchange Online Protection for Faculty"
    "EXCHANGESTANDARD_STUDENT"           = "Exchange Online (Plan 1) for Students"
    "OFFICESUBSCRIPTION_STUDENT"         = "Office ProPlus Student Benefit"
    "STANDARDWOFFPACK_FACULTY"           = "Office 365 Education E1 for Faculty"
    "STANDARDWOFFPACK_STUDENT"           = "Microsoft Office 365 (Plan A2) for Students"
    "DYN365_FINANCIALS_BUSINESS_SKU"     = "Dynamics 365 for Financials Business Edition"
    "DYN365_FINANCIALS_TEAM_MEMBERS_SKU" = "Dynamics 365 for Team Members Business Edition"
    "FLOW_FREE"                          = "Microsoft Flow Free"
    "POWER_BI_PRO"                       = "Power BI Pro"
    "O365_BUSINESS"                      = "Office 365 Business"
    "DYN365_ENTERPRISE_SALES"            = "Dynamics Office 365 Enterprise Sales"
    "RIGHTSMANAGEMENT"                   = "Rights Management"
    "PROJECTPROFESSIONAL"                = "Project Professional"
    "VISIOONLINE_PLAN1"                  = "Visio Online Plan 1"
    "EXCHANGEENTERPRISE"                 = "Exchange Online Plan 2"
    "DYN365_ENTERPRISE_P1_IW"            = "Dynamics 365 P1 Trial for Information Workers"
    "DYN365_ENTERPRISE_TEAM_MEMBERS"     = "Dynamics 365 For Team Members Enterprise Edition"
    "CRMSTANDARD"                        = "Microsoft Dynamics CRM Online Professional"
    "EXCHANGEARCHIVE_ADDON"              = "Exchange Online Archiving For Exchange Online"
    "EXCHANGEDESKLESS"                   = "Exchange Online Kiosk"
    "SPZA_IW"                            = "App Connect"
    "WINDOWS_STORE"                      = "Windows Store for Business"
    "MCOEV"                              = "Microsoft Phone System"
    "VIDEO_INTEROP"                      = "Polycom Skype Meeting Video Interop for Skype for Business"
    "SPE_E5"                             = "Microsoft 365 E5"
    "SPE_E3"                             = "Microsoft 365 E3"
    "ATA"                                = "Advanced Threat Analytics"
    "MCOPSTN2"                           = "Domestic and International Calling Plan"
    "FLOW_P1"                            = "Microsoft Flow Plan 1"
    "FLOW_P2"                            = "Microsoft Flow Plan 2"
    "POWERAPPS_VIRAL"                    = "Microsoft PowerApps Plan 2"
    "MIDSIZEPACK"                        = "Office 365 Midsize Business"
    "AAD_PREMIUM_P2"                     = "Azure Active Directory Premium P2"
    "RIGHTSMANAGEMENT_STANDARD_FACULTY"  = "Information Rights Management for Faculty"
    "PROJECTONLINE_PLAN_1_FACULTY"       = "Project Online for Faculty Plan 1"
    "PROJECTONLINE_PLAN_2_FACULTY"       = "Project Online for Faculty Plan 2"
    "PROJECTONLINE_PLAN_1_STUDENT"       = "Project Online for Students Plan 1"
    "PROJECTONLINE_PLAN_2_STUDENT"       = "Project Online for Students Plan 2"
    "TEAMS1"                             = "Microsoft Teams"
    "RIGHTSMANAGEMENT_STANDARD_STUDENT"  = "Information Rights Management for Students"
    "EXCHANGEENTERPRISE_FACULTY"         = "Exchange Online Plan 2 for Faculty"
    "SHAREPOINTSTANDARD"                 = "SharePoint Online Plan 1"
    "CRMPLAN2"                           = "Dynamics CRM Online Plan 2"
    "CRMSTORAGE"                         = "Microsoft Dynamics CRM Online Additional Storage"
    "EMSPREMIUM"                         = "Enterprise Mobility + Security E5"
    "POWER_BI_INDIVIDUAL_USER"           = "Power BI for Office 365 Individual"
    "DESKLESSPACK_YAMMER"                = "Office 365 Enterprise F1 with Yammer"
    "MICROSOFT_BUSINESS_CENTER"          = "Microsoft Business Center"
    "STREAM"                             = "Microsoft Stream"
    "OFFICESUBSCRIPTION_FACULTY"         = "Office 365 ProPlus for Faculty"
    "WACSHAREPOINTSTD"                   = "Office Online STD"
    "POWERAPPS_INDIVIDUAL_USER"          = "Microsoft PowerApps and Logic flows"
    "IT_ACADEMY_AD"                      = "Microsoft Imagine Academy"
    "SHAREPOINTENTERPRISE"               = "SharePoint Online (Plan 2)"
    "MCOPSTN1"                           = "Skype for Business PSTN Domestic Calling"
    "MEE_FACULTY"                        = "Minecraft Education Edition Faculty"
    "LITEPACK_P2"                        = "Office 365 Small Business Premium"
    "EXCHANGE_S_ENTERPRISE"              = "Exchange Online Plan 2 S"
    "INTUNE_A_VL"                        = "Intune (Volume License)"
    "ENTERPRISEPACKWITHOUTPROPLUS"       = "Office 365 Enterprise E3 without ProPlus Add-on"
    "ATP_ENTERPRISE_FACULTY"             = "Exchange Online Advanced Threat Protection"
    "EXCHANGE_S_STANDARD"                = "Exchange Online (Plan 2)"
    "MEE_STUDENT"                        = "Minecraft Education Edition Student"
    "EQUIVIO_ANALYTICS_FACULTY"          = "Office 365 Advanced Compliance for faculty"
}
Convert-ExchangeSize

Here's how Convert-ExchangeSize can be used. What it actually does is use the bytes size from variable and converts it to KB, MB, GB, TB.

Convert-ExchangeSize -To MB -Size '49 GB (52,613,349,376 bytes)'
Convert-ExchangeSize -To GB -Size '49 GB (52,613,349,376 bytes)'

Source code can be found below or in module

function Convert-ExchangeSize {
    [cmdletbinding()]
    param(
        [validateset("Bytes", "KB", "MB", "GB", "TB")][string]$To = 'MB',
        [string]$Size,
        [int]$Precision = 4,
        [switch]$Display,
        [string]$Default = 'N/A'
    )
    if ([string]::IsNullOrWhiteSpace($Size)) {
        return $Default
    }
    $Pattern = [Regex]::new('(?<=\()([0-9]*[,.].*[0-9])')  # (?<=\()([0-9]*.*[0-9]) works too
    $Value = ($Size | Select-String $Pattern -AllMatches).Matches.Value
    Write-Verbose "Convert-ExchangeSize - Value Before: $Value"

    if ($null -ne $Value) {
        $Value = $Value.Replace(',', '').Replace('.', '')
    }

    switch ($To) {
        "Bytes" {return $value}
        "KB" {$Value = $Value / 1KB}
        "MB" {$Value = $Value / 1MB}
        "GB" {$Value = $Value / 1GB}
        "TB" {$Value = $Value / 1TB}

    }
    Write-Verbose "Convert-ExchangeSize - Value After: $Value"
    if ($Display) {
        return "$([Math]::Round($value,$Precision,[MidPointRounding]::AwayFromZero)) $To"
    } else {
        return [Math]::Round($value, $Precision, [MidPointRounding]::AwayFromZero)
    }

}
Convert-ExchangeEmail

This little function can convert standard output from Exchange Email into a readable string. Don't know about you but my management doesn't want all those SMTP, SIP and SPO prefixes in email address list when I send them the report. No magic here, just a plain conversion.

    $Emails = @()
    $Emails += 'SIP:test@email.com'
    $Emails += 'SMTP:elo@maiu.com'
    $Emails += 'sip:elo@maiu.com'
    $Emails += 'Spo:dfte@sdsd.com'
    $Emails += 'SPO:myothertest@sco.com'

    Convert-ExchangeEmail -Emails $Emails -RemovePrefix -RemoveDuplicates -AddSeparator

Here's the source code for it

function Convert-ExchangeEmail {
    <#
    .SYNOPSIS
    Function that helps converting Exchange email address list into readable, exportable format.
    
    .DESCRIPTION
        Function that helps converting Exchange email address list into readable, exportable format.
    
    .PARAMETER Emails
    List of emails as available in Exchange or Exchange Online, otherwise known as proxy addresses list
    
    .PARAMETER Separator
    
    .PARAMETER RemoveDuplicates
    
    .PARAMETER RemovePrefix
    
    .PARAMETER AddSeparator
    
    .EXAMPLE
    
    $Emails = @()
    $Emails += 'SIP:test@email.com'
    $Emails += 'SMTP:elo@maiu.com'
    $Emails += 'sip:elo@maiu.com'
    $Emails += 'Spo:dfte@sdsd.com'
    $Emails += 'SPO:myothertest@sco.com'

    Convert-ExchangeEmail -Emails $Emails -RemovePrefix -RemoveDuplicates -AddSeparator
    
    .NOTES
    General notes
    #>
    
    [CmdletBinding()]
    param(
        [string[]] $Emails,
        [string] $Separator = ', ',
        [switch] $RemoveDuplicates,
        [switch] $RemovePrefix,
        [switch] $AddSeparator
    )

    if ($RemovePrefix) {
        #$Emails = $Emails.Replace('SMTP:', '').Replace('SIP:', '').Replace('smtp:', '').Replace('sip:', '').Replace('spo:','')
        $Emails = $Emails -replace 'smtp:', '' -replace 'sip:', '' -replace 'spo:', ''
    }
    if ($RemoveDuplicates) {
        $Emails = $Emails | Sort-Object -Unique
    }
    if ($AddSeparator) {
        $Emails = $Emails -join $Separator
    }
    return $Emails
}

This post was last modified on January 29, 2019 19:01

Przemyslaw Klys

System Architect with over 14 years of experience in the IT field. Skilled, among others, in Active Directory, Microsoft Exchange and Office 365. Profoundly interested in PowerShell. Software geek.

Share
Published by
Przemyslaw Klys

Recent Posts

Upgrade Azure Active Directory Connect fails with unexpected error

Today, I made the decision to upgrade my test environment and update the version of…

6 days ago

Mastering Active Directory Hygiene: Automating Stale Computer Cleanup with CleanupMonster

Have you ever looked at your Active Directory and wondered, "Why do I still have…

4 months ago

Active Directory Replication Summary to your Email or Microsoft Teams

Active Directory replication is a critical process that ensures the consistent and up-to-date state of…

8 months ago

Syncing Global Address List (GAL) to personal contacts and between Office 365 tenants with PowerShell

Hey there! Today, I wanted to introduce you to one of the small but excellent…

1 year ago

Active Directory Health Check using Microsoft Entra Connect Health Service

Active Directory (AD) is crucial in managing identities and resources within an organization. Ensuring its…

1 year ago

Seamless HTML Report Creation: Harness the Power of Markdown with PSWriteHTML PowerShell Module

In today's digital age, the ability to create compelling and informative HTML reports and documents…

1 year ago