Export-MailboxFASAPermissions.ps1

<#PSScriptInfo
 
.VERSION 1.9.1
 
.GUID 1391bc32-575f-4ec5-8e73-a3ba548203b6
 
.AUTHOR SammyKrosoft
 
.COMPANYNAME SammykroSoft
 
#>


<#
.SYNOPSIS
    Export Exchange Mailbox Send As, Full Access, and Send On Behalf permissions
    in a CSV file in order to later import them in another environment using the
    output CSV file.
 
.DESCRIPTION
    This script requires the Exchange tools to run.
 
    It exports the following Exchange Mailbox permissions in a CSV file
    - Send As
    - Full Access
    - Send On Behalf To
    in order to be able to import them later in another environment using
    the output CSV file.
 
    The Output CSV file will contain the following information for each mailbox permissions
    information exported:
     
    Display Name, Primary SMTP Address, Full Access permissions, Send As permissions, Send On Behalf permissions
 
    The permissions can have one or more entries, which will be separated by semicolons (";")
 
    To import back the permissions if needed , you can use the associated Import-MailboxFASAPermissions.ps1
    script.
 
    Since the Send As and Full Access permissions can be granted to non-mailbox or
    non-mail enabled users, these are stored in the CSV in the form of DOMAIN\Alias.
 
    On the other hand, the Send On Behalf permission can be granted only to mailbox-enabled users,
    mail-enabled users and/or mail-enabled security groups only. For some reason, it is stored in
    the form of DOMAIN\OU1\Sub-OU1\...\Name - then, the script is designed to convert these - actually
    the script resolve these using Get-Mailbox -Identity DOMAIN\OU\...\Name to get and store the
    PrimarySMTPAddress of these users so that we have two advantages:
        > Not only we are sure that each SMTP address represents a unique user
        > Also it will be way easier for the IMPORT script to import these permissions back, wherever OU the
        target user will be located !
     
    This is because the IMPORT script uses Set-Mailbox with the -SendOnBehalfTo, where we can
    specify an SMTP address, which will be converted to the corresponding DOMAIN\OU\Name of the
    corresponding user in the target environment.
     
    In other words, the SMTP address will be the KEY to match the SendOnBehalfTo permission to the
    right users and mailboxes on the target environments.
 
.PARAMETER OutputFile
    Sets the file to which we want to store the results.
    By default, the script will generate a CSV report with the name of the script,
    with the date and time appended to it.
 
.PARAMETER SharedMailboxes
    This indicates the script to export the SharedMailboxes only
     
    When combined with the -ResourceMailboxes, the script will export
    the Shared Mailboxes, and the Room and Equipment Mailboxes as well !
 
    To export ALL mailboxes, just don't specify neither the SharedMailboxes
    nor the ResourceMailboxes parameter.
 
.PARAMETER ResourceMailboxes
    This indicates the script to export the ResourceMailboxes only which
    consist of the Room and the Equipment Mailboxes.
 
    When combined with the -SharedMailboxes, the script will export the
    Shared Mailboxes, the Room and the Equipment mailboxes as well !
 
    To export ALL mailboxes, just don't specify neither the SharedMailboxes
    nor the ResourceMailboxes parameter.
 
.PARAMETER DistrutionGroupsOnly
    This will make the script export Distribution Groups and Dynamic Distribution Groups
    Send On Behalf Rights exports - this will not export Mailbox rights.
 
    NOTE: Distribution Groups have only SendOnBehalf and Send As permissions
    -> these have NOT "Full Access" rights : because these are not mailboxes
 
.PARAMETER CheckVersion
    This parameter just dumps the script version.
 
.INPUTS
    The script will scan all the mailboxes, but database by database to avoid to use
    all the RAM of the machine from which it's executed.
 
.OUTPUTS
    A CSV file with either a name that you specify with the OutputFile parameter, or if not,
    the name of the script, containing the users Display Names, primary SMTP addresses,
    and the list of Send-As, Full Access and SendOnBehalfTo for each of these mailboxes.
     
    If the Send-As, Full Access and SendOnBehalfTo are multi-values, they are stored in the columns
    as semi-colon separated values, like Value1;value2;value3;...
     
    => when processing each permissions set, just use something like $ImportedCSV.SendAsPermissions -split ";"
    or $ImportedCSV.SendAsPermissions.Split(";") ...
 
.EXAMPLE
.\Export-MailboxFASAPermissions.ps1
    Will run the script and export the mailbox Display Names, primary SMTP Addresses, and all the
    Send As, Full Access and Send On Behalf To permissions on a CSV file.
 
.EXAMPLE
.\Export-MailboxFASAPermissions.ps1 -OutputFile C:\temp\EnvironmentPermissions.csv
    Will run the script and export permissions for all mailboxes, in the file specified on the
    OutputFile parameter : C:\temp\EnvironmentPermissions.csv
 
.EXAMPLE
.\Export-MailboxFASA.ps1 -SharedMailboxes
    Will run the script and export the Shared Mailboxes permissions as well as the Room and
    Equipment Mailboxes permissions, and store the result on the default CSV file named after
    the script, appended with the date and time of the execution, on the script directory
 
.EXAMPLE
.\Export-MailboxFASA.ps1 -ResourceMailboxes c:\temp\ResourceMailboxPermissions.csv
    Will run the script and export only the Room and Equipment Mailboxes permissions, and store
    the results in a CSV file c:\temp\ResourceMailboxPermissions.csv
 
.EXAMPLE
.\Export-MailboxFASA.ps1 -DistributionGroupsOnly
    Will run the script and export only the Distribugion Group permissions (Send As, GrantSendOnBehalfTo) in
    the default Output file format (Script_Name_Date_time.csv). This includes the Dynamic Distribution
    Groups.
 
.EXAMPLE
.\Export-MailboxFASA.ps1 -DistributionGroupsOnly -IncludeDynamic $false
    Will run the script to export permissions of Distribution Groups, excluding the Dynamic Distribugion
    Groups.
 
 
.NOTES
    This script can be use alone to export a permissions map, but the output is designed so that it
    can be used with the Import-MailboxFASAPermissions.ps1 script to migrate permissions to another
    environment such as a LAB or a brand new one with the same users (Inter-Forest migration for example
    or move from an On-Prem to an outsourced environment such as Office 365)
 
    Some simple facts about the permissions exported on this script:
 
    "Sens As" permissions
        . Stored in the form of "DOMAIN\Alias"
        . Is set with Add-ADPermission
        . https://docs.microsoft.com/en-us/powershell/module/exchange/active-directory/Add-ADPermission?view=exchange-ps
 
    "Full Access" Permissions
        . Stored in the form of "DOMAIN\Alias" as well
        . Is set with Add-MailboxPermission
        . https://docs.microsoft.com/en-us/powershell/module/exchange/mailboxes/Add-MailboxPermission?view=exchange-ps
 
    "Send On Behalf Of" permissions
        . Stored in the form of "Domain.com/OU_Name/Sub_OU/Name"
        . Is set with Set-Mailbox
        . https://docs.microsoft.com/en-us/powershell/module/exchange/mailboxes/Set-Mailbox?view=exchange-ps
        . -GrantSendOnBehalfTo parameter accepts one or more values from the below :
                Display name
                Alias
                Distinguished name (DN)
                Canonical DN
                <domain name>\<account name>
                Email address
                GUID
                LegacyExchangeDN
                SamAccountName
                User ID or user principal name (UPN)
 
.LINK
    https://technet.microsoft.com/en-ca/library/jj919240(v=exchg.150).aspx
 
.LINK
    https://docs.microsoft.com/en-us/powershell/module/exchange/active-directory/add-adpermission?view=exchange-ps
 
.LINK
    https://technet.microsoft.com/en-us/library/jj919240(v=exchg.150).aspx
 
.LINK
    https://github.com/SammyKrosoft
#>

[CmdLetBinding(DefaultParameterSetName = "NormalRun")]
Param(
    [Parameter(Mandatory = $false, Position = 0, ParameterSetName = "NormalRun")][switch]$SharedMailboxes,
    [Parameter(Mandatory = $false, Position = 1, ParameterSetName = "NormalRun")][switch]$ResourceMailboxes,
    [Parameter(Mandatory = $false, Position = 2, ParameterSetName = "DLOnly")][Switch]$DistributionGroupsOnly,
    [Parameter(Mandatory = $false, Position = 3, ParameterSetName = "DLOnly")][boolean]$IncludeDynamic=$true,
    [Parameter(Mandatory = $false, Position = 4, ParameterSetName = "NormalRun")][Parameter(ParameterSetName = "DLOnly")][string]$OutputFile,
    [Parameter(Mandatory = $false, ParameterSetName = "MailboxList")][string[]]$MailboxList,
    [Parameter(Mandatory = $false, Position = 6, ParameterSetName = "CheckOnly")][switch]$CheckVersion
)

<# ------- SCRIPT_HEADER (Only Get-Help comments and Param() above this point) ------- #>
#Initializing a $Stopwatch variable to use to measure script execution
$stopwatch = [system.diagnostics.stopwatch]::StartNew()
#Using Write-Debug and playing with $DebugPreference -> "Continue" will output whatever you put on Write-Debug "Your text/values"
# and "SilentlyContinue" will output nothing on Write-Debug "Your text/values"
$DebugPreference = "Continue"
# Set Error Action to your needs
$ErrorActionPreference = "SilentlyContinue"
#Script Version
$ScriptVersion = "1.9.1"
<# Version changes
v1.9.1 - just forgot
v1.9 - added ability to search one or more mailboxes based on a list -MailboxList parameter
v1.8.2 - fixed Get-Mailbox -Database $Database to include double quotes for database names with spaces in it
v1.8.1 - fixed OutputFile parameter to be included in both NormalRun and DLOnly parameters set
v1.8 - fixed issue exporting Send As for Distribugion Groups (was trying to reference $DL.Identity but selected
ALIAS, Send AS and Send On Behalf permissions only, forgot to add Identity in the Select)
V1.7 - replaced Get-Mailbox with Get-Recipient to get primarySMTP Addresses of Grant
Send On Behalf To entries
Also added the ability to export GrantSendOnBehalfTo from Distribution Groups,
Including by default the Dynamic distribution groups - specify $false to the
-IncludeDynamic parameter to exclude Dynamic DLs
v1 - Completed the script.
v0.1 - first script version
#>

$ScriptName = $MyInvocation.MyCommand.Name
If ($CheckVersion) {Write-Host "SCRIPT NAME :$ScriptName `nSCRIPT VERSION :$ScriptVersion";exit}
# Log or report file definition
# NOTE: use #PSScriptRoot in Powershell 3.0 and later or use $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition in Powershell 2.0
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition #<-- that's for Powershell 2.0
$OutputReport = "$($ScriptPath)\$($ScriptName)_$(get-date -f yyyy-MM-dd-HH-mm-ss).csv"
# Other Option for Log or report file definition (use one of these)
$ScriptLog = "$($ScriptPath)\$($ScriptName)-$(Get-Date -Format 'dd-MMMM-yyyy-HH-mm-ss-tt').txt"
<# ---------------------------- /SCRIPT_HEADER ---------------------------- #>
<# -------------------------- DECLARATIONS -------------------------- #>
[array]$report = @()
$Databases = $null
$DBProgressCount = $null
$Mailboxes = @()
<# /DECLARATIONS #>
<# -------------------------- FUNCTIONS -------------------------- #>
#region Functions
function Log {
    <#
     .SYNOPSIS
      Function to log input string to file and display it to screen
     
     .DESCRIPTION
      Function to log input string to file and display it to screen. Log entries in the log file are time stamped. Function allows for displaying text to screen in different colors.
     
     .PARAMETER String
      The string to be displayed to the screen and saved to the log file
     
     .PARAMETER Color
      The color in which to display the input string on the screen
      Default is White
      Valid options are
        Black
        Blue
        Cyan
        DarkBlue
        DarkCyan
        DarkGray
        DarkGreen
        DarkMagenta
        DarkRed
        DarkYellow
        Gray
        Green
        Magenta
        Red
        White
        Yellow
     
     .PARAMETER LogFile
      Path to the file where the input string should be saved.
      Example: c:\log.txt
      If absent, the input string will be displayed to the screen only and not saved to log file
     
     .EXAMPLE
      Write-Log -String "Hello World" -Color Yellow -LogFile c:\log.txt
      This example displays the "Hello World" string to the console in yellow, and adds it as a new line to the file c:\log.txt
      If c:\log.txt does not exist it will be created.
      Log entries in the log file are time stamped. Sample output:
        2014.08.06 06:52:17 AM: Hello World
     
     .EXAMPLE
      Write-Log "$((Get-Location).Path)" Cyan
      This example displays current path in Cyan, and does not log the displayed text to log file.
     
     .EXAMPLE
      "$((Get-Process | select -First 1).name) process ID is $((Get-Process | select -First 1).id)" | Write-Log -color DarkYellow
      Sample output of this example:
        "MDM process ID is 4492" in dark yellow
     
     .EXAMPLE
      Write-Log 'Found',(Get-ChildItem -Path .\ -File).Count,'files in folder',(Get-Item .\).FullName Green,Yellow,Green,Cyan .\mylog.txt
      Sample output will look like:
        Found 520 files in folder D:\Sandbox - and will have the listed foreground colors
     
     .LINK
      https://superwidgets.wordpress.com/2014/12/01/powershell-script-function-to-display-text-to-the-console-in-several-colors-and-save-it-to-log-with-timedate-stamp/
     
     .NOTES
      Function by Sam Boutros
      v1.0 - 08/06/2014
      v1.1 - 12/01/2014 - added multi-color display in the same line
      v1.2 - 8 August 2016 - updated date time stamp format, protect against bad LogFile name
     
    #>

    
        [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Low')] 
        Param(
            [Parameter(Mandatory=$true,
                       ValueFromPipeLine=$true,
                       ValueFromPipeLineByPropertyName=$true,
                       Position=0)]
                [String[]]$String, 
            [Parameter(Mandatory=$false,
                       Position=1)]
                [ValidateSet("Black","Blue","Cyan","DarkBlue","DarkCyan","DarkGray","DarkGreen","DarkMagenta","DarkRed","DarkYellow","Gray","Green","Magenta","Red","White","Yellow")]
                [String[]]$Color = "Green", 
            [Parameter(Mandatory=$false,
                       Position=2)]
                [String]$LogFile = $ScriptLog,
            [Parameter(Mandatory=$false,
                       Position=3)]
                [Switch]$NoNewLine
        )
    
    
        $LegalFileNameCharSet = "^[" + [Regex]::Escape("A-Za-z0-9^&'@{}[],$=!-#()%.+~_") + "]+$"
        if ($String.Count -gt 1) {
            $i=0
            foreach ($item in $String) {
                if ($Color[$i]) { $col = $Color[$i] } else { $col = "White" }
                Write-Host "$item " -ForegroundColor $col -NoNewline
                $i++
            }
            if (-not ($NoNewLine)) { Write-Host " " }
        } else { 
            if ($NoNewLine) { Write-Host $String -ForegroundColor $Color[0] -NoNewline }
                else { Write-Host $String -ForegroundColor $Color[0] }
        }
    
        if ($LogFile.Length -gt 2 -and !($LogFile -match $LegalFileNameCharSet)) {
            "$(Get-Date -format 'dd MMMM yyyy hh:mm:ss tt'): $($String -join " ")" | Out-File -Filepath $Logfile -Append 
        } else {
            Write-debug "Log: Missing -LogFile parameter or bad LogFile name. Will not save input string to log file.."
        }
    }

function _Progress {
    param([parameter(Mandatory = $false, Position = 1)] $PercentComplete = 100)
    Write-Progress -id 1 -activity "Working..." -status "In progress..." -PercentComplete ($PercentComplete)
    }

Function Test-ExchTools(){
    Try
    {
        Get-command Get-mailbox -ErrorAction Stop
        $ExchInstalledStatus = $true
        $Message = "Exchange tools are present !"
        Write-Host $Message -ForegroundColor Blue -BackgroundColor Red
    }
    Catch [System.SystemException]
    {
        $ExchInstalledStatus = $false
        $Message = "Exchange Tools are not present !"
        Write-Host $Message -ForegroundColor red -BackgroundColor Blue
        Exit
    }
    Return $ExchInstalledStatus
}
    
function IsEmpty($Param){
    If ($Param -eq "All" -or $Param -eq "" -or $Param -eq $Null -or $Param -eq 0) {
        Return $True
    } Else {
        Return $False
    }
}
<# /FUNCTIONS #>
#endregion Functions
<# -------------------------- EXECUTIONS -------------------------- #>
Log "********************** Beginning execution ***********************" Blue
Log "Testing if Exchange tools are present" Blue
Test-ExchTools
Log "Exchange Tools present ! continuing to test if user specified Output file" Red
If (IsEmpty $OutputFile) {
    Log "Not Output file specified, using the script standard name $OutputReport" Yellow
    $OutputFile = $OutputReport}

Log "Checking if user specified -DistributionGroupsOnly switch..." Blue
If ($DistributionGroupsOnly){
    Log "User specified the -DistribugionGroupsOnly switch. Beginning Distribution Groups SendAs / GrantSendOnBehalfTo permissions dump..." Red
    #Process same as Mailboxes but replacing the mailbox objects with Get-DistributionList | Select Name,PrimarySMTPAddress, GrantSendOnBehalfTo
    #We have 2 sorts of Distribution Groups : regular Distribution Groups (can be based on Distribution or Security Groups)
    #And Dynamic Distribution Groups
    Log "Getting all distribution Groups" Blue
    $DLs = Get-DistributionGroup | Select Identity,Alias, DisplayName, primarySMTPAddress, @{Name='GrantSendOnBehalfTo';Expression={[string]::join(";", ($_.GrantSendOnBehalfTo))}}
    Log "Testing whether the user set the -IncludeDynamic boolean parameter to `$false (`$true by default)" Green
    If($IncludeDynamic){
        Log "User didn't specify the -IncludeDynamic or set -IncludeDynamic to `$false - including Dynamic DLs" White
        $DLs += Get-DynamicDistributionGroup | Select Alias, DisplayName, primarySMTPAddress, @{Name='GrantSendOnBehalfTo';Expression={[string]::join(";", ($_.GrantSendOnBehalfTo))}}
    }

    If (IsEmpty $DLs){
        $msgNoDLsFound = "No Distribution Lists found"
        Log $msgNoDLsFound Red
        Exit
    }

    Foreach ($DL in $DLs){
        $msgWorkingOnDistributionGroup = "Working on Distribution Group $($DL.DisplayName) which Primary SMTP is $($DL.primarySMTPAddress.ToString())"
        Log $msgWorkingOnDistributionGroup Blue
        $SendAs = Get-ADPermission $($DL.identity) | ?{($_.extendedrights -like "*send-as*") -and ($_.isinherited -like "false") -and ($_.User -notlike "NT Authority\self")}
        #Initializing a new Powershell object to store our discovered properties
        $Obj = New-Object PSObject
        #Populating basic DL info to bind with SendAs / SendOnBehalf permissions
        $Obj | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $DL.DisplayName
        $obj | Add-Member -MemberType NoteProperty -Name "PrimarySMTPAddress" -Value $DL.PrimarySMTPAddress.ToString()

        If (IsEmpty $SendAs){
            Log "No custom Send As permissions detected"
            $Obj | Add-Member -MemberType NoteProperty -Name "SendAsPermissions" -Value ""
        } Else {
            Log "Found one or more SendAs Permission ! Dumping ..." Red
            [array]$UsersWithSendAs = @()
            ForEach($SAright in $SendAs){$UsersWithSendAs += ($SARight.User.ToString())}
            $strUsersWithSendAs = $UsersWithSendAs -join ";"
            $Obj | Add-Member -MemberType NoteProperty -Name "SendAsPermissions" -Value $strUsersWithSendAs
        }

        If (IsEmpty ($DL.GrantSendOnBehalfTo)){
            Log "No custom SendOnBehalf permissions detected"
            $Obj | Add-Member -MemberType NoteProperty -Name "SendOnBehalfPermissions" -Value ""
        } else {
            Log "Found one or more SendOnBehalf Permission ! Dumping ..." Blue
            $TableOfSendOnBehalfToConvert = $($DL.GrantSendOnBehalfTo) -Split (";")
            $SMTPAddressesOfSendOnBehalf = @()
            Foreach ($entry in $TableOfSendOnBehalfToConvert) {
                #Since the GrantSendOnBehalfTo entries HAVE to be mailbox-enabled users or mail enabled user or groups,
                #Getting primary SMTP address for each object, and storing these as a string separated by semicolon
                #to replace the string of DOMAIN/OU1/OU2/Name separated by semicolon
                $SMTPAddressesOfSendOnBehalf += (Get-Recipient $Entry).primarySMTPAddress
            }
            $SendOnBehalfConverted = $SMTPAddressesOfSendOnBehalf -join ";"
            $Obj | Add-Member -MemberType NoteProperty -Name "SendOnBehalfPermissions" -Value $SendOnBehalfConverted
        }

        $report += $Obj
    }
} ElseIf ($MailboxList){
    # ADDING THE -MAILBOXLIST PARAMETER TREATMENT
    # NOTE: The below code for this ElseIf {} block is copied from the last Else {} block below,
    #instead of taking all mailboxes from all databases, taking the list of mailboxes specified by the -MailboxList parameter aka $MailboxList variable
    $MailboxListCount = $MailboxList.Count
    Log "Using -MailboxList parameter, checking mailboxes from that list ($MailboxListCount mailboxes in the list)"
    Foreach ($CurMailbox in $MailboxList){
         Log "Processing mailbox $CurMailbox"
         Try {
            $Mailbox = Get-mailbox $CurMailbox -ErrorAction STOP
            Log "SUCCESS - Successfully located mailbox $CurMailbox : its primary SMTP address is : $($Mailbox.PrimarySMTPAddress)"
         } Catch {
            Log "ERROR - Something wrong happened trying to locate mailbox $CurMailbox . Wrong mailbox ID ... tried another mailbox ID (SMTP address, display name, DN,...)"
            Log "ERROR - Skipping mailbox $CurMailbox"
            Continue
         }
         Log "Working on mailbox $($Mailbox.DisplayName) which Primary SMTP is $($Mailbox.primarySMTPAddress.ToString())" Blue
         $SendAs=Get-ADPermission $mailbox.identity | ?{($_.extendedrights -like "*send-as*") -and ($_.isinherited -like "false") -and ($_.User -notlike "NT Authority\self")}
         $FullAccess=Get-MailboxPermission $Mailbox | ?{($_.AccessRights -like "*fullaccess*") -and ($_.User -notlike "*nt authority\self*") -and ($_.User -notlike "*nt authority\system*") -and ($_.User -notlike "*Exchange Trusted Subsystem*") -and ($_.User -notlike "*Exchange Servers*") -and ($_.IsInherited -like "false")}
         $SendOnBehalf = $mailbox | Select Alias, @{Name='GrantSendOnBehalfTo';Expression={[string]::join(";", ($_.GrantSendOnBehalfTo))}}
         #Initializing a new Powershell object to store our discovered properties
         $Obj = New-Object PSObject
         #Populating basic mailbox info to bind with SendAs / FullMailbox / SendOnBehalf permissions
         $Obj | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $Mailbox.DisplayName
         $obj | Add-Member -MemberType NoteProperty -Name "PrimarySMTPAddress" -Value $Mailbox.PrimarySMTPAddress.ToString()
         
         If (IsEmpty $SendAs){
             Log "No custom Send As permissions detected"
             $Obj | Add-Member -MemberType NoteProperty -Name "SendAsPermissions" -Value ""
         } Else {
             Log "Found one or more SendAs Permission ! Dumping ..." Red
             [array]$UsersWithSendAs = @()
             ForEach($SAright in $SendAs){$UsersWithSendAs += ($SARight.User.ToString())}
             $strUsersWithSendAs = $UsersWithSendAs -join ";"
             $Obj | Add-Member -MemberType NoteProperty -Name "SendAsPermissions" -Value $strUsersWithSendAs
         }

         If (IsEmpty $FullAccess){
             Log "No custom Full Access permissions detected"
             $Obj | Add-Member -MemberType NoteProperty -Name "FullAccessPermissions" -Value ""
         }  else {
             Log "Found one or more Full Access Permission ! Dumping ..." Blue
             [array]$UsersWithFullAccess = @()
             ForEach ($FARight in $FullAccess) {$UsersWithFullAccess += ($FARight.User.ToString())}
             $strUsersWithFullAccess = $UsersWithFullAccess -join ";"
             $Obj | Add-Member -MemberType NoteProperty -Name "FullAccessPermissions" -Value $strUsersWithFullAccess
         }
         
         If (IsEmpty ($SendOnBehalf.GrantSendOnBehalfTo)){
             Log "No custom SendOnBehalf permissions detected"
             $Obj | Add-Member -MemberType NoteProperty -Name "SendOnBehalfPermissions" -Value ""
         } else {
             Log "Found one or more SendOnBehalf Permission ! Dumping ..." Blue
             $TableOfSendOnBehalfToConvert = $($SendOnBehalf.GrantSendOnBehalfTo) -Split (";")
             $SMTPAddressesOfSendOnBehalf = @()
             Foreach ($entry in $TableOfSendOnBehalfToConvert) {
                 #Since the GrantSendOnBehalfTo entries HAVE to be mailbox-enabled users or mail enabled user or groups,
                 #Getting primary SMTP address for each object, and storing these as a string separated by semicolon
                 #to replace the string of DOMAIN/OU1/OU2/Name separated by semicolon
                 $SMTPAddressesOfSendOnBehalf += (Get-Recipient $Entry).primarySMTPAddress
             }
             $SendOnBehalfConverted = $SMTPAddressesOfSendOnBehalf -join ";"
             $Obj | Add-Member -MemberType NoteProperty -Name "SendOnBehalfPermissions" -Value $SendOnBehalfConverted
         }
         #Appending the current object into the $report variable (it's an array, remember)
         $report += $Obj

         #Cleaning the variables now before the next loop...
         $SendOnBehalfConverted = $null
         $obj = $Null
         $SMTPAddressesOfSendOnBehalf = $null
         $TableOfSendOnBehalfToConvert = $null
         $SendOnBehalfConverted = $null
         $SendAs = $null
         $FullAccess = $null
         $SendOnBehalf = $null
         #... add more later
    }

} Else {
    Log "Beginning routing to dump mailbox Send As, Full Access, and Send On Behalf permissions"
    Log "Getting all databases"
    $Databases = Get-MailboxDatabase
    $DBProgressCount = 0

    Foreach ($Database in $Databases){
        $DBProgressCount++
        Log "Processing Database $($Database.Name)"
        _Progress ($DBProgressCount/$($Databases.count)*100)
        
        $Mailboxescommand = "Get-Mailbox -resultsize unlimited -database `"$Database`""
        If ($ResourceMailboxes -or $SharedMailboxes) {
            Log "Specified Resource Mailboxes parameter ? $ResourceMailboxes"
            Log "Specified SharedMailboxes parameter ? $SharedMailboxes"
            $MailboxesCommand += " -RecipientTypeDetails "
            $combo = @()
            If ($ResourceMailboxes){$Combo += @("RoomMailbox", "EquipmentMailbox") }
            If ($SharedMailboxes){$Combo += "SharedMailbox"}
            $combo = $Combo -join ","
            $MailboxesCommand += $combo
        }
        Log "The full mailbox command launched is :"
        Log $Mailboxescommand
        #Launch the command built with the above routine, based on the switches the admin chooses
        $Mailboxes = Invoke-expression $Mailboxescommand
        #If we don't "break" the current loop occurence with a "Continue" instruction, there will be an empty line in the CSV when there are no mailboxes in a given database
        If (IsEmpty $Mailboxes){Continue}

        #We cycle through each mailbox to get the permissions
        #It's time consuming because of the AD queries...
        Log "Parsing $($Mailboxes.count) mailboxes..."
        Foreach ($Mailbox in $Mailboxes) {
            Log "Working on mailbox $($Mailbox.DisplayName) which Primary SMTP is $($Mailbox.primarySMTPAddress.ToString())" Blue
            $SendAs=Get-ADPermission $mailbox.identity | ?{($_.extendedrights -like "*send-as*") -and ($_.isinherited -like "false") -and ($_.User -notlike "NT Authority\self")}
            $FullAccess=Get-MailboxPermission $Mailbox | ?{($_.AccessRights -like "*fullaccess*") -and ($_.User -notlike "*nt authority\self*") -and ($_.User -notlike "*nt authority\system*") -and ($_.User -notlike "*Exchange Trusted Subsystem*") -and ($_.User -notlike "*Exchange Servers*") -and ($_.IsInherited -like "false")}
            $SendOnBehalf = $mailbox | Select Alias, @{Name='GrantSendOnBehalfTo';Expression={[string]::join(";", ($_.GrantSendOnBehalfTo))}}
            #Initializing a new Powershell object to store our discovered properties
            $Obj = New-Object PSObject
            #Populating basic mailbox info to bind with SendAs / FullMailbox / SendOnBehalf permissions
            $Obj | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $Mailbox.DisplayName
            $obj | Add-Member -MemberType NoteProperty -Name "PrimarySMTPAddress" -Value $Mailbox.PrimarySMTPAddress.ToString()
            
            If (IsEmpty $SendAs){
                Log "No custom Send As permissions detected"
                $Obj | Add-Member -MemberType NoteProperty -Name "SendAsPermissions" -Value ""
            } Else {
                Log "Found one or more SendAs Permission ! Dumping ..." Red
                [array]$UsersWithSendAs = @()
                ForEach($SAright in $SendAs){$UsersWithSendAs += ($SARight.User.ToString())}
                $strUsersWithSendAs = $UsersWithSendAs -join ";"
                $Obj | Add-Member -MemberType NoteProperty -Name "SendAsPermissions" -Value $strUsersWithSendAs
            }

            If (IsEmpty $FullAccess){
                Log "No custom Full Access permissions detected"
                $Obj | Add-Member -MemberType NoteProperty -Name "FullAccessPermissions" -Value ""
            }  else {
                Log "Found one or more Full Access Permission ! Dumping ..." Blue
                [array]$UsersWithFullAccess = @()
                ForEach ($FARight in $FullAccess) {$UsersWithFullAccess += ($FARight.User.ToString())}
                $strUsersWithFullAccess = $UsersWithFullAccess -join ";"
                $Obj | Add-Member -MemberType NoteProperty -Name "FullAccessPermissions" -Value $strUsersWithFullAccess
            }
            
            If (IsEmpty ($SendOnBehalf.GrantSendOnBehalfTo)){
                Log "No custom SendOnBehalf permissions detected"
                $Obj | Add-Member -MemberType NoteProperty -Name "SendOnBehalfPermissions" -Value ""
            } else {
                Log "Found one or more SendOnBehalf Permission ! Dumping ..." Blue
                $TableOfSendOnBehalfToConvert = $($SendOnBehalf.GrantSendOnBehalfTo) -Split (";")
                $SMTPAddressesOfSendOnBehalf = @()
                Foreach ($entry in $TableOfSendOnBehalfToConvert) {
                    #Since the GrantSendOnBehalfTo entries HAVE to be mailbox-enabled users or mail enabled user or groups,
                    #Getting primary SMTP address for each object, and storing these as a string separated by semicolon
                    #to replace the string of DOMAIN/OU1/OU2/Name separated by semicolon
                    $SMTPAddressesOfSendOnBehalf += (Get-Recipient $Entry).primarySMTPAddress
                }
                $SendOnBehalfConverted = $SMTPAddressesOfSendOnBehalf -join ";"
                $Obj | Add-Member -MemberType NoteProperty -Name "SendOnBehalfPermissions" -Value $SendOnBehalfConverted
            }
            #Appending the current object into the $report variable (it's an array, remember)
            $report += $Obj

            #Cleaning the variables now before the next loop...
            $SendOnBehalfConverted = $null
            $obj = $Null
            $SMTPAddressesOfSendOnBehalf = $null
            $TableOfSendOnBehalfToConvert = $null
            $SendOnBehalfConverted = $null
            $SendAs = $null
            $FullAccess = $null
            $SendOnBehalf = $null
            #... add more later
        }
    }
}


# Get mailbox forward to from mailboxes:Change the items below that are in bold to fit your needs.
# Get-Mailbox -Filter {ForwardingAddress -ne $Null} |Select Alias, ForwardingAddress | Export-Csv -NoType -encoding "unicode" C:\*location*\MailboxesForwardTo.csv
# Get mailbox grant send on behalf to:Change the items below that are in bold to fit your needs.
#Get-Mailbox -Filter {GrantSendOnBehalfTo -ne $Null} |Select Alias, @{Name='GrantSendOnBehalfTo';Expression={[string]::join(";", ($_.GrantSendOnBehalfTo))}} | Export-Csv -NoType -encoding "unicode" C:\*location*\MailboxesSendOnBehalf.csv
Log "saving file in $OutputFile"
$Report | export-csv -NoTypeInformation $OutputFile
Notepad $OutputFile

<# /EXECUTIONS #>
<# -------------------------- CLEANUP VARIABLES -------------------------- #>
$Report = $null
$OutputReport = $null
$obj = $null
$strUsersWithSendAs = $null
$strUsersWithFullAccess = $null
$UsersWithSendAs = $null
$UsersWithFullAccess = $null
$SendOnBehalf = $null
$FullAccess = $null
$SendAs = $null
$Mailboxes = $null
$Databases = $Null
<# /CLEANUP VARIABLES#>
<# ---------------------------- SCRIPT_FOOTER ---------------------------- #>
#Stopping StopWatch and report total elapsed time (TotalSeconds, TotalMilliseconds, TotalMinutes, etc...
$stopwatch.Stop()
Log "`n`nThe script took $($StopWatch.Elapsed.TotalSeconds) seconds to execute..."
<# ---------------- /SCRIPT_FOOTER (NOTHING BEYOND THIS POINT) ----------- #>