MyPSFunctions.MgGraph.ps1

<#
    ===========================================================================
     Created with: SAPIEN Technologies, Inc., PowerShell Studio 2021 v5.8.196
     Created on: 10/26/2023 7:46 PM
     Created by: John@MyPSFunctions.com
     Organization: MyPSFunctions
     Filename: MyPSFunctions.MgGraph.psm1
    -------------------------------------------------------------------------
     Module Name: MyPSFunctions.MgGraph
    ===========================================================================
#>


#region Basics
####################################################
############################## Basics ################
####################################################
Function Find-MgScopesOfCMDlet
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$CMDlet
    )
    
    Find-MgGraphCommand -Command $CMDlet | Select -First 1 -ExpandProperty Permissions
}

Function Get-MgToken
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$TenantID,
        [Parameter(Mandatory = $true,
                   Position = 2)]
        [String]$AppID,
        [Parameter(Mandatory = $true,
                   Position = 3)]
        [string]$AppSecret
    )
    
    # Construct URI and body needed for authentication
    $URI = "https://login.microsoftonline.com/" + $TenantID + "/oauth2/v2.0/token"
    $Body = @{
        Grant_Type    = "client_credentials"
        Scope          = "https://graph.microsoft.com/.default"
        Client_Id      = $AppID
        Client_Secret = $AppSecret
    }
    # Get OAuth 2.0 Token
    $connection = Invoke-RestMethod -Uri $URI -Method POST -Body $body
    # Unpack Access Token
    $Token = $connection.access_token
    Return $Token
}

#endregion

#region Users
####################################################
###################### Users ########################
####################################################
Function Generate-MgUserMicrosoft365GroupMembership
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$UPN
    )
    
    $MgGroups = Get-MgUserMemberOf -UserId $UPN
    #Initiate the Hash Table
    $Table = $Null
    $Table = @()
    
    
    foreach ($MgGroup in $MgGroups)
    {
        $MgGroupID = $Null
        $MgGroupID = $MgGroup.ID
        $FoundMgGroup = $Null
        $MgGroup_DisplayName = $Null
        $MgGroup_Mail = $Null
        $MgGroup_MailEnabled = $Null
        $MgGroup_SecurityEnabled = $Null
        Try
        {
            $FoundMgGroup = Get-mgGroup -GroupId $MgGroupID -ErrorAction Stop
            $MgGroup_DisplayName = $FoundMgGroup.DisplayName
            $MgGroup_Mail = $FoundMgGroup.Mail
            $MgGroup_MailEnabled = $FoundMgGroup.MailEnabled
            $MgGroup_SecurityEnabled = $FoundMgGroup.SecurityEnabled
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $FoundMgGroup = "Not Found - Failed with Error : $ErrorMessage"
            $MgGroup_DisplayName = "Not Found - Failed with Error : $ErrorMessage"
            $MgGroup_Mail = "Not Found - Failed with Error : $ErrorMessage"
            $MgGroup_MailEnabled = "Not Found - Failed with Error : $ErrorMessage"
            $MgGroup_SecurityEnabled = "Not Found - Failed with Error : $ErrorMessage"
        }
        
        
        $Table += New-object PSobject -Property ([Ordered] @{
                GroupID            = $MgGroupID;
                DisplayName        = $MgGroup_DisplayName;
                MailEnabled        = $MgGroup_MailEnabled;
                Mail            = $MgGroup_Mail;
                SecurityEnabled = $MgGroup_SecurityEnabled;
            })
    }
    $Table
}
Function Check-MgAllUsersStats
{
    [CmdletBinding()]
    param ()
    Connect-MgGraph -Scopes 'User.Read.All' -NoWelcome
    # All MgUsers
    $AllMgUsers = Get-MgUser -all -Property DisplayName, UserPrincipalName, UserType, AccountEnabled
    # All Member MgUsers
    $AllMemberMgUsers = $AllMgUsers | where { $_.UserType -ne "Guest" }
    # All Enabled MgUsers
    $AllEnabledMgUsers = $AllMgUsers | where { $_.UserType -ne "Guest" -and $_.AccountEnabled -eq $True }
    # All Disabled MgUsers
    $AllDisabledMgUsers = $AllMgUsers | where { $_.UserType -ne "Guest" -and $_.AccountEnabled -eq $false }
    
    #Counts
    $AllMgUsersCount = ($AllMgUsers | Measure).count
    $AllMemberMgUsersCount = ($AllMemberMgUsers | Measure).count
    $AllEnabledMgUsersCount = ($AllEnabledMgUsers | Measure).count
    $AllDisabledMgUsersCount = ($AllDisabledMgUsers | Measure).count
    
    $Table = $Null
    $Table = @()
    
    $Table += New-object PSobject -Property ([Ordered] @{
            AllMgUsersCount            = $AllMgUsersCount;
            AllMemberMgUsersCount   = $AllMemberMgUsersCount;
            AllEnabledMgUsersCount  = $AllEnabledMgUsersCount;
            AllDisabledMgUsersCount = $AllDisabledMgUsersCount;
        })
    $Table | fl
}

Function Generate-MyMgBetaUserSignInActivities
{
    Read-Host "Are you Connect to Beta MgGrap ?"
    ###############################################################################################################################################################################
    #################################################################### Variable #####################################################################
    ###############################################################################################################################################################################
    $Date = get-date -UFormat %d%m%Y
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ServerName = [Environment]::MachineName
    ###### Create Root Folder
    $RootFolder = $psscriptRoot + "\Users_Reports"
    
    ###### Create folder Variable
    $LogPathFolder = $RootFolder + "\Log\"
    $LogFile = $LogPathFolder + "Progress_" + $Date + ".log"
    
    
    $ReportPathFolder = $RootFolder + "\Reports\"
    
    ###### Create Folder
    Create-Folder $RootFolder
    Create-Folder $LogPathFolder
    Create-Folder $ReportPathFolder
    
    $Transcript_File = $LogPathFolder + "Transcript_" + $Date + ".txt"
    Start-Transcript -Path $Transcript_File -Append -Force
    ########### Initiate the Process log file when the script started ############
    $Initiat_LogA = "#################### starting the Script #####################"
    $Startat = "### The Script has been launch at $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")"
    $Startwith = "The Script has been start with the following Account:" + [Environment]::UserName
    $Starton = "The Script has been start on the following Computer:" + [Environment]::MachineName
    $Initiat_LogB = "##############################################################"
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogA | Out-File -FilePath $LogFile -Append
    $Startat | Out-File -FilePath $LogFile -Append
    $Startwith | Out-File -FilePath $LogFile -Append
    $Starton | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    
    ###############################################################################################################################################################################
    #################################################################### Main Script #####################################################################
    ###############################################################################################################################################################################
    
    
    # Found MgUsers
    Try
    {
        #Read-Host "The script going to retreive all users from the tenant"
        # All Users

            $Users = Get-MgBetaUser -all -filter "usertype ne 'Guest'" -Countvariable CountVar -ConsistencyLevel eventual -Property SignInActivity, SignInSessionsValidFromDateTime, RefreshTokensValidFromDateTime, DisplayName, UserPrincipalName
            $ReportFile = $ReportPathFolder + "All_Report_Users_SigninActivities_" + $DateFull + ".xlsx"
            Write-Log -Level INFO -Message "The script find All Users from the tenant"
        
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log -Level Error -LogPath $LogFile -Message "Failed to Find MgUsers"
        Write-Log -Level Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log -Level Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
        Write-Log -Level Error -LogPath $LogFile -Message "The Script will stop"
        # Exit the script
        Read-Host "End of Script"
    }
    
    # Loop
    $UsersInfo = $Null
    $UsersInfo = @()
    [Int]$i = 1
    $Count = ($Users | Measure).count
    foreach ($UserData in $Users)
    {
        $UserUPN = $UserData.UserPrincipalName
        Write-Log -Level warning -LogPath $LogFile -Message "The script is analyzing $UserUPN --- $i/$Count"
        # MgUser
        
        Write-log Warning -Message "The Script is searching for the MgUser: $UserUPN"
        $FoundMgUserStatus = "Yes"
        $LastNonInteractiveSignInDateTime = $Null
        $LastSignInDateTime = $Null
        $LastSuccessfulSignInDateTime = $Null
        $SignInSessionsValidFromDateTime = $Null
        $RefreshTokensValidFromDateTime = $Null
        If ($UserData.signinActivity.LastNonInteractiveSignInDateTime.DateTime)
        {
            $LastNonInteractiveSignInDateTime = Get-Date ($UserData.signinActivity.LastNonInteractiveSignInDateTime.DateTime) -Format "G"
            $LastNonInteractiveSignInDateTime = [datetime]::Parse($LastNonInteractiveSignInDateTime)
        }
        If ($UserData.SignInActivity.LastSignInDateTime.DateTime)
        {
            $LastSignInDateTime = Get-Date ($UserData.SignInActivity.LastSignInDateTime.DateTime) -Format "G"
            $LastSignInDateTime = [datetime]::Parse($LastSignInDateTime)
        }
        If ($UserData.SignInActivity.LastSuccessfulSignInDateTime.DateTime)
        {
            $LastSuccessfulSignInDateTime = Get-Date ($UserData.SignInActivity.LastSuccessfulSignInDateTime.DateTime) -Format "G"
            $LastSuccessfulSignInDateTime = [datetime]::Parse($LastSuccessfulSignInDateTime)
        }
        If ($UserData.SignInSessionsValidFromDateTime.DateTime)
        {
            $SignInSessionsValidFromDateTime = Get-Date ($UserData.SignInSessionsValidFromDateTime.DateTime) -Format "G"
            $SignInSessionsValidFromDateTime = [datetime]::Parse($SignInSessionsValidFromDateTime)
        }
        If ($UserData.RefreshTokensValidFromDateTime.DateTime)
        {
            $RefreshTokensValidFromDateTime = Get-Date ($UserData.RefreshTokensValidFromDateTime.DateTime) -Format "G"
            $RefreshTokensValidFromDateTime = [datetime]::Parse($RefreshTokensValidFromDateTime)
        }
        
        $DisplayName = $UserData.DisplayName
        $UserPrincipalName = $UserData.UserPrincipalName
            
        
        $UsersInfo += New-object PSobject -Property ([Ordered] @{
                DisplayName                                           = $DisplayName;
                UserPrincipalName                                   = $UserPrincipalName;
                LastSuccessfulSignInDateTime                       = $LastSuccessfulSignInDateTime;
                LastNonInteractiveSignInDateTime                   = $LastNonInteractiveSignInDateTime;
                LastSignInDateTime                 = $LastSignInDateTime;
                SignInSessionsValidFromDateTime  = $SignInSessionsValidFromDateTime;
                RefreshTokensValidFromDateTime  = $RefreshTokensValidFromDateTime;
            })
        $i++
    }
    
    $UsersInfo | Export-Excel $ReportFile -TableName "SignInActivities" -Title "SignIn Activities" -TitleBold -WorksheetName "SignInActivities" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFile"
}
Function Generate-MyMgBetaUserReport
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateSet('All', 'Enable', 'Disable')]
        [String]$Type
    )
    
    Read-Host "Are you Connect to Beta MgGraph and EXO?"
    ###############################################################################################################################################################################
    #################################################################### Variable #####################################################################
    ###############################################################################################################################################################################
    $Date = get-date -UFormat %d%m%Y
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ServerName = [Environment]::MachineName
    ###### Create Root Folder
    $RootFolder = $psscriptRoot + "\Users_Reports"
    
    ###### Create folder Variable
    $LogPathFolder = $RootFolder + "\Log\"
    $LogFile = $LogPathFolder + "Progress_" + $Date + ".log"
    
    
    $ReportPathFolder = $RootFolder + "\Reports\"
    
    ###### Create Folder
    Create-Folder $RootFolder
    Create-Folder $LogPathFolder
    Create-Folder $ReportPathFolder
    
    $Transcript_File = $LogPathFolder + "Transcript_" + $Date + ".txt"
    Start-Transcript -Path $Transcript_File -Append -Force
    ########### Initiate the Process log file when the script started ############
    $Initiat_LogA = "#################### starting the Script #####################"
    $Startat = "### The Script has been launch at $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")"
    $Startwith = "The Script has been start with the following Account:" + [Environment]::UserName
    $Starton = "The Script has been start on the following Computer:" + [Environment]::MachineName
    $Initiat_LogB = "##############################################################"
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogA | Out-File -FilePath $LogFile -Append
    $Startat | Out-File -FilePath $LogFile -Append
    $Startwith | Out-File -FilePath $LogFile -Append
    $Starton | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    
    ###############################################################################################################################################################################
    #################################################################### Main Script #####################################################################
    ###############################################################################################################################################################################
    
    #Found License Name
    Try
    {
        $LocalPath = ".\MapSKUID.csv"
        If (!(Test-Path $LocalPath))
        {
            Write-Log warning -Message "The script Download Microsoft Licensing CSV File"
            $URL = "https://download.microsoft.com/download/e/3/e/e3e9faf2-f28b-490a-9ada-c6089a1fc5b0/Product%20names%20and%20service%20plan%20identifiers%20for%20licensing.csv"
            $LocalPath = ".\MapSKUID.csv"
            Invoke-WebRequest -Uri $URL -OutFile $LocalPath
            
            
        }
        Else
        {
            Write-Log warning -Message "The folder $LocalPath is already exist"
            
        }
        $MicrosoftSKUs = Import-Csv $LocalPath
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to download $LocalPath"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
    }
    
    # Found MgUsers
    Try
    {
        #Read-Host "The script going to retreive all users from the tenant"
        # All Users
        If ($Type -eq "All")
        {
            $Users = Get-MgBetaUser -all -filter "usertype ne 'Guest'" -Countvariable CountVar -ConsistencyLevel eventual -Property SignInSessionsValidFromDateTime, RefreshTokensValidFromDateTime,CreatedDateTime, OnPremisesDistinguishedName, OnPremisesImmutableId, OnPremisesLastSyncDateTime, OnPremisesSamAccountName, OnPremisesSyncEnabled, OnPremisesUserPrincipalName, SignInActivity, MailNickname, UserType, AssignedLicenses, DisplayName, UserPrincipalName, JobTitle, Department, AccountEnabled, Mail, LastPasswordChangeDateTime, OnPremisesExtensionAttributes
            $ReportFile = $ReportPathFolder + "All_Report_Users_" + $DateFull + ".xlsx"
            Write-Log -Level INFO -Message "The script find All Users from the tenant"
        }
        # All Enable Users
        If ($Type -eq "Enable")
        {
            $Users = Get-MgBetaUser -all -filter "accountenabled eq true and usertype ne 'Guest'" -Countvariable CountVar -ConsistencyLevel eventual -Property SignInSessionsValidFromDateTime, RefreshTokensValidFromDateTime,CreatedDateTime, OnPremisesDistinguishedName, OnPremisesImmutableId, OnPremisesLastSyncDateTime, OnPremisesSamAccountName, OnPremisesSyncEnabled, OnPremisesUserPrincipalName, SignInActivity, MailNickname, UserType, AssignedLicenses, DisplayName, UserPrincipalName, JobTitle, Department, AccountEnabled, Mail, LastPasswordChangeDateTime, OnPremisesExtensionAttributes
            $ReportFile = $ReportPathFolder + "Enable_Report_Users_" + $DateFull + ".xlsx"
            Write-Log -Level INFO -Message "The script find all Enable Users from the tenant"
        }
        # All Disabled Users
        If ($Type -eq "Disable")
        {
            $Users = Get-MgBetaUser -all -filter "accountenabled eq false and usertype ne 'Guest'" -Countvariable CountVar -ConsistencyLevel eventual -Property SignInSessionsValidFromDateTime, RefreshTokensValidFromDateTime,CreatedDateTime, OnPremisesDistinguishedName, OnPremisesImmutableId, OnPremisesLastSyncDateTime, OnPremisesSamAccountName, OnPremisesSyncEnabled, OnPremisesUserPrincipalName, SignInActivity, MailNickname, UserType, AssignedLicenses, DisplayName, UserPrincipalName, JobTitle, Department, AccountEnabled, Mail, LastPasswordChangeDateTime, OnPremisesExtensionAttributes
            $ReportFile = $ReportPathFolder + "Disable_Report_Users_" + $DateFull + ".xlsx"
            Write-Log -Level INFO -Message "The script find all Disable Users from the tenant"
        }
        
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log -Level Error -LogPath $LogFile -Message "Failed to Find MgUsers"
        Write-Log -Level Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log -Level Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
        Write-Log -Level Error -LogPath $LogFile -Message "The Script will stop"
        # Exit the script
        Read-Host "End of Script"
    }
    
    # Loop
    $UsersInfo = $Null
    $UsersInfo = @()
    [Int]$i = 1
    $Count = ($Users | Measure).count
    foreach ($UserData in $Users)
    {
        $UserUPN = $UserData.UserPrincipalName
        Write-Log -Level warning -LogPath $LogFile -Message "The script is analyzing $UserUPN --- $i/$Count"
        # MgUser
        
        Write-log Warning -Message "The Script is searching for the MgUser: $UserUPN"
        $FoundMgUserStatus = "Yes"
        $LastNonInteractiveSignInDateTime = $Null
        $LastSignInDateTime = $Null
        $LastSuccessfulSignInDateTime = $Null
        $SignInSessionsValidFromDateTime = $Null
        $RefreshTokensValidFromDateTime = $Null
        $CreatedDateTime = $Null
        $OnPremisesDistinguishedName = $Null
        $OnPremisesImmutableId = $Null
        $OnPremisesLastSyncDateTime = $Null
        $OnPremisesSamAccountName = $Null
        $OnPremisesSyncEnabled = $Null
        $OnPremisesUserPrincipalName = $Null
        $MailNickname = $Null
        $DisplayName = $Null
        $UserPrincipalName = $Null
        $Department = $Null
        $Tittle = $Null
        $AccountEnabled = $Null
        $Mail = $Null
        $LastPasswordChangeDateTime = $Null
        $UserType = $Null
        $AssignedLicenses = $Null
        $Licenses = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute1 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute2 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute3 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute4 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute5 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute6 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute7 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute8 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute9 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute10 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute11 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute12 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute13 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute14 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute15 = $Null
        If ($UserData.signinActivity.LastNonInteractiveSignInDateTime.DateTime)
        {
            $LastNonInteractiveSignInDateTime = Get-Date ($UserData.signinActivity.LastNonInteractiveSignInDateTime.DateTime) -Format "G"
            $LastNonInteractiveSignInDateTime = [datetime]::Parse($LastNonInteractiveSignInDateTime)
        }
        If ($UserData.SignInActivity.LastSignInDateTime.DateTime)
        {
            $LastSignInDateTime = Get-Date ($UserData.SignInActivity.LastSignInDateTime.DateTime) -Format "G"
            $LastSignInDateTime = [datetime]::Parse($LastSignInDateTime)
        }
        If ($UserData.SignInActivity.LastSuccessfulSignInDateTime.DateTime)
        {
            $LastSuccessfulSignInDateTime = Get-Date ($UserData.SignInActivity.LastSuccessfulSignInDateTime.DateTime) -Format "G"
            $LastSuccessfulSignInDateTime = [datetime]::Parse($LastSuccessfulSignInDateTime)
        }
        If ($UserData.SignInSessionsValidFromDateTime.DateTime)
        {
            $SignInSessionsValidFromDateTime = Get-Date ($UserData.SignInSessionsValidFromDateTime.DateTime) -Format "G"
            $SignInSessionsValidFromDateTime = [datetime]::Parse($SignInSessionsValidFromDateTime)
        }
        If ($UserData.RefreshTokensValidFromDateTime.DateTime)
        {
            $RefreshTokensValidFromDateTime = Get-Date ($UserData.RefreshTokensValidFromDateTime.DateTime) -Format "G"
            $RefreshTokensValidFromDateTime = [datetime]::Parse($RefreshTokensValidFromDateTime)
        }
        $CreatedDateTime = $UserData.CreatedDateTime
        $OnPremisesDistinguishedName = $UserData.OnPremisesDistinguishedName
        $OnPremisesImmutableId = $UserData.OnPremisesImmutableId
        $OnPremisesLastSyncDateTime = $UserData.OnPremisesLastSyncDateTime
        $OnPremisesSamAccountName = $UserData.OnPremisesSamAccountName
        $OnPremisesSyncEnabled = $UserData.OnPremisesSyncEnabled
        $OnPremisesUserPrincipalName = $UserData.OnPremisesUserPrincipalName
        $MailNickname = $UserData.MailNickname
        $DisplayName = $UserData.DisplayName
        $UserPrincipalName = $UserData.UserPrincipalName
        $Department = $UserData.Department
        $Tittle = $UserData.JobTitle
        $AccountEnabled = $UserData.AccountEnabled
        $Mail = $UserData.Mail
        $LastPasswordChangeDateTime = $UserData.LastPasswordChangeDateTime
        $UserType = $UserData.UserType
        $AssignedLicenses = $UserData.AssignedLicenses
        $OnPremisesExtensionAttributes_ExtensionAttribute1 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute1
        $OnPremisesExtensionAttributes_ExtensionAttribute2 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute2
        $OnPremisesExtensionAttributes_ExtensionAttribute3 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute3
        $OnPremisesExtensionAttributes_ExtensionAttribute4 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute4
        $OnPremisesExtensionAttributes_ExtensionAttribute5 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute5
        $OnPremisesExtensionAttributes_ExtensionAttribute6 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute6
        $OnPremisesExtensionAttributes_ExtensionAttribute7 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute7
        $OnPremisesExtensionAttributes_ExtensionAttribute8 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute8
        $OnPremisesExtensionAttributes_ExtensionAttribute9 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute9
        $OnPremisesExtensionAttributes_ExtensionAttribute10 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute10
        $OnPremisesExtensionAttributes_ExtensionAttribute11 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute11
        $OnPremisesExtensionAttributes_ExtensionAttribute12 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute12
        $OnPremisesExtensionAttributes_ExtensionAttribute13 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute13
        $OnPremisesExtensionAttributes_ExtensionAttribute14 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute14
        $OnPremisesExtensionAttributes_ExtensionAttribute15 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute15
        $CreatedDateTime = $UserData.CreatedDateTime
        
        $UserLicenses = @()
        foreach ($AssignedLicense in $AssignedLicenses)
        {
            $SkuId = $Null
            $SkuId = $AssignedLicense.SkuId
            $UserLicenses += ($MicrosoftSKUs | where { $_.GUID -eq $SkuId } | Select -first 1).Product_Display_Name
        }
        $Licenses = $UserLicenses -join ";"
        
        
        # Recipient
        $FoundRecipientStatus = "No"
        $DeletedItemCount = "Not a Mailbox"
        $ItemCount = "Not a Mailbox"
        $TotalDeletedItemSize = "Not a Mailbox"
        $TotalItemSize = "Not a Mailbox"
        $FoundMailboxStatisticsStatus = "Not a Mailbox"
        $IsMailboxEnabled = "Not a Mailbox"
        $Recipient = $Null
        Try
        {
            
            Write-log Warning -Message "The Script is searching for the Recipient: $UserUPN"
            $Recipient = Get-Recipient $UserUPN
            If ($Recipient)
            {
                Write-Log Info -Message "The script find the recipient $UserUPN"
                $FoundRecipientStatus = "Yes"
                $PrimarySmtpAddress = $Recipient.PrimarySmtpAddress
                $RecipientTypeDetails = $Recipient.RecipientTypeDetails
                $IsDirSynced = $Recipient.IsDirSynced
                $WhenMailboxCreated = $Recipient.WhenMailboxCreated
                $WhenSoftDeleted = $Recipient.WhenSoftDeleted
                $WhenCreated = $Recipient.WhenCreated
            }
            Else
            {
                Write-Log Info -Message "The script find the recipient $UserUPN"
                $FoundRecipientStatus = "Not a Recipient"
                $PrimarySmtpAddress = "Not a Recipient"
                $RecipientTypeDetails = "Not a Recipient"
                $IsDirSynced = "Not a Recipient"
                $WhenMailboxCreated = "Not a Recipient"
                $WhenSoftDeleted = "Not a Recipient"
                $WhenCreated = "Not a Recipient"
            }
            
            
            If ($RecipientTypeDetails -like "*Mailbox")
            {
                
                #Mailbox Data
                $IsMailboxEnabled = "No Data Found"
                $FoundMailboxDataStatus = "No"
                Try
                {
                    Write-Log warning -Message "The script retreive Mailbox Data for $PrimarySmtpAddress"
                    $MailboxData = $Null
                    $MailboxData = Get-Mailbox $PrimarySmtpAddress
                    $IsMailboxEnabled = $MailboxData.IsMailboxEnabled
                    Write-Log Info -Message "The script retreived Mailbox Data for $PrimarySmtpAddress"
                    $FoundMailboxDataStatus = "Yes"
                }
                Catch
                {
                    $ErrorMessage = $Error[0].Exception.Message
                    $CMDLet = $Error[0].InvocationInfo.Line
                    $FailedItem = $Error[0].Exception.ItemName
                    Write-Log Error -Message "Failed to retreive Mailbox Data for $PrimarySmtpAddress"
                    Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                    Write-Log Error -Message "Failed with Error:$ErrorMessage"
                    $FoundMailboxDataStatus = "Failed with Error:$ErrorMessage"
                    
                    
                }
                #MailboxStatistics
                $DeletedItemCount = "No Data Found"
                $ItemCount = "No Data Found"
                $TotalDeletedItemSize = "No Data Found"
                $TotalItemSize = "No Data Found"
                Try
                {
                    Write-Log warning -Message "The script search Mailbox Statistics for $PrimarySmtpAddress"
                    $MailboxStatistics = Get-EXOMailboxStatistics $PrimarySmtpAddress
                    $DeletedItemCount = $MailboxStatistics.DeletedItemCount
                    $ItemCount = $MailboxStatistics.ItemCount
                    $TotalDeletedItemSize = $MailboxStatistics.TotalDeletedItemSize
                    $TotalItemSize = $MailboxStatistics.TotalItemSize
                    Write-Log Info -Message "The script found Mailbox Statistics info for $PrimarySmtpAddress"
                    $FoundMailboxStatisticsStatus = "Yes"
                }
                Catch
                {
                    $ErrorMessage = $Error[0].Exception.Message
                    $CMDLet = $Error[0].InvocationInfo.Line
                    $FailedItem = $Error[0].Exception.ItemName
                    Write-Log Error -Message "Failed to Retreive MailboxStatistics for $PrimarySmtpAddress"
                    Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                    Write-Log Error -Message "Failed with Error:$ErrorMessage"
                    $FoundMailboxStatisticsStatus = "Failed with Error:$ErrorMessage"
                    $DeletedItemCount = "Failed"
                    $ItemCount = "Failed"
                    $TotalDeletedItemSize = "Failed"
                    $TotalItemSize = "Failed"
                    
                }
                
                #Mailbox Permissions
                $MailboxPermissionUsers = "No Data Found"
                $MailboxPermissionAccessRights = "No Data Found"
                $RecipientPermissionTrustees = "No Data Found"
                $RecipientPermissionAccessRights = "No Data Found"
                
                Try
                {
                    Write-Log warning -Message "The script search Mailbox Permissions for $PrimarySmtpAddress"
                    $EXORecipientPermissions = Get-EXORecipientPermission $PrimarySmtpAddress
                    $EXOMailboxPermissions = Get-EXOMailboxPermission $PrimarySmtpAddress
                    $MailboxPermissionUsers = $EXOMailboxPermissions.User -join ";"
                    $MailboxPermissionAccessRights = $EXOMailboxPermissions.AccessRights -join ";"
                    $RecipientPermissionTrustees = $EXORecipientPermissions.Trustee -join ";"
                    $RecipientPermissionAccessRights = $EXORecipientPermissions.AccessRights -join ";"
                    Write-Log Info -Message "The script found Mailbox Permissions info for $PrimarySmtpAddress"
                    $FoundMailboxStatisticsStatus = "Yes"
                }
                Catch
                {
                    $ErrorMessage = $Error[0].Exception.Message
                    $CMDLet = $Error[0].InvocationInfo.Line
                    $FailedItem = $Error[0].Exception.ItemName
                    Write-Log Error -Message "Failed to Retreive MailboxStatistics for $PrimarySmtpAddress"
                    Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                    Write-Log Error -Message "Failed with Error:$ErrorMessage"
                    $FoundMailboxStatisticsStatus = "Failed with Error:$ErrorMessage"
                    $MailboxPermissionUsers = "Failed"
                    $MailboxPermissionAccessRights = "Failed"
                    $RecipientPermissionTrustees = "Failed"
                    $RecipientPermissionAccessRights = "Failed"
                }
                
            }
            Else
            {
                $DeletedItemCount = "Not a Mailbox"
                $ItemCount = "Not a Mailbox"
                $TotalDeletedItemSize = "Not a Mailbox"
                $TotalItemSize = "Not a Mailbox"
                $MailboxPermissionUsers = "Not a Mailbox"
                $MailboxPermissionAccessRights = "Not a Mailbox"
                $RecipientPermissionTrustees = "Not a Mailbox"
                $RecipientPermissionAccessRights = "Not a Mailbox"
            }
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -Message "Failed to find MgUser $UserUPN"
            Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -Message "Failed with Error:$ErrorMessage"
            $FoundRecipientStatus = "Failed with Error:$ErrorMessage"
        }
        
        $UsersInfo += New-object PSobject -Property ([Ordered] @{
                DisplayName                                           = $DisplayName;
                Tittle                                               = $Tittle;
                Department                                           = $Department;
                AccountEnabled                                       = $AccountEnabled;
                Mail                                               = $Mail;
                UserPrincipalName                                   = $UserPrincipalName;
                LastSuccessfulSignInDateTime                       = $LastSuccessfulSignInDateTime;
                LastNonInteractiveSignInDateTime                   = $LastNonInteractiveSignInDateTime;
                LastSignInDateTime                                   = $LastSignInDateTime;
                SignInSessionsValidFromDateTime                       = $SignInSessionsValidFromDateTime;
                RefreshTokensValidFromDateTime                       = $RefreshTokensValidFromDateTime;
                LastPasswordChangeDateTime                           = $LastPasswordChangeDateTime;
                OnPremisesDistinguishedName                           = $OnPremisesDistinguishedName;
                OnPremisesImmutableId                               = $OnPremisesImmutableId;
                OnPremisesLastSyncDateTime                           = $OnPremisesLastSyncDateTime;
                OnPremisesSamAccountName                           = $OnPremisesSamAccountName;
                OnPremisesSyncEnabled                               = $OnPremisesSyncEnabled;
                OnPremisesUserPrincipalName                           = $OnPremisesUserPrincipalName;
                OnPremisesExtensionAttributes_ExtensionAttribute1  = $OnPremisesExtensionAttributes_ExtensionAttribute1;
                OnPremisesExtensionAttributes_ExtensionAttribute2  = $OnPremisesExtensionAttributes_ExtensionAttribute2;
                OnPremisesExtensionAttributes_ExtensionAttribute3  = $OnPremisesExtensionAttributes_ExtensionAttribute3;
                OnPremisesExtensionAttributes_ExtensionAttribute4  = $OnPremisesExtensionAttributes_ExtensionAttribute4;
                OnPremisesExtensionAttributes_ExtensionAttribute5  = $OnPremisesExtensionAttributes_ExtensionAttribute5;
                OnPremisesExtensionAttributes_ExtensionAttribute6  = $OnPremisesExtensionAttributes_ExtensionAttribute6;
                OnPremisesExtensionAttributes_ExtensionAttribute7  = $OnPremisesExtensionAttributes_ExtensionAttribute7;
                OnPremisesExtensionAttributes_ExtensionAttribute8  = $OnPremisesExtensionAttributes_ExtensionAttribute8;
                OnPremisesExtensionAttributes_ExtensionAttribute9  = $OnPremisesExtensionAttributes_ExtensionAttribute9;
                OnPremisesExtensionAttributes_ExtensionAttribute10 = $OnPremisesExtensionAttributes_ExtensionAttribute10;
                OnPremisesExtensionAttributes_ExtensionAttribute11 = $OnPremisesExtensionAttributes_ExtensionAttribute11;
                OnPremisesExtensionAttributes_ExtensionAttribute12 = $OnPremisesExtensionAttributes_ExtensionAttribute12;
                OnPremisesExtensionAttributes_ExtensionAttribute13 = $OnPremisesExtensionAttributes_ExtensionAttribute13;
                OnPremisesExtensionAttributes_ExtensionAttribute14 = $OnPremisesExtensionAttributes_ExtensionAttribute14;
                OnPremisesExtensionAttributes_ExtensionAttribute15 = $OnPremisesExtensionAttributes_ExtensionAttribute15;
                CreatedDateTime                                       = $CreatedDateTime;
                MailNickname                                       = $MailNickname;
                UserType                                           = $UserType;
                Licenses                                           = $Licenses;
                FoundRecipient                                       = $FoundRecipientStatus;
                PrimarySmtpAddress                                   = $PrimarySmtpAddress;
                RecipientTypeDetails                               = $RecipientTypeDetails;
                IsDirSynced                                           = $IsDirSynced;
                IsMailboxEnabled                                   = $IsMailboxEnabled;
                WhenMailboxCreated                                   = $WhenMailboxCreated;
                WhenSoftDeleted                                       = $WhenSoftDeleted;
                WhenCreated                                           = $WhenCreated;
                FoundMailboxStatistics                               = $FoundMailboxStatisticsStatus;
                DeletedItemCount                                   = $DeletedItemCount;
                ItemCount                                           = $ItemCount;
                TotalDeletedItemSize                               = $TotalDeletedItemSize;
                TotalItemSize                                       = $TotalItemSize;
                MailboxPermissionUsers                               = $MailboxPermissionUsers;
                MailboxPermissionAccessRights                       = $MailboxPermissionAccessRights;
                RecipientPermissionTrustees                           = $RecipientPermissionTrustees;
                RecipientPermissionAccessRights                       = $RecipientPermissionAccessRights;
            })
        $i++
    }
    
    $UsersInfo | Export-Excel $ReportFile -TableName "UsersReport" -Title "Users Report" -TitleBold -WorksheetName "UsersReport" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFile"
}
Function Generate-MyMgUserReport
{
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateSet('All', 'Enable', 'Disable')]
        [String]$Type
    )
    
    Read-Host "Are you Connect to MgGraph and EXO?"
    ###############################################################################################################################################################################
    #################################################################### Variable #####################################################################
    ###############################################################################################################################################################################
    $Date = get-date -UFormat %d%m%Y
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ServerName = [Environment]::MachineName
    ###### Create Root Folder
    $RootFolder = $psscriptRoot + "\Users_Reports"
    
    ###### Create folder Variable
    $LogPathFolder = $RootFolder + "\Log\"
    $LogFile = $LogPathFolder + "Progress_" + $Date + ".log"
    
    
    $ReportPathFolder = $RootFolder + "\Reports\"
    
    ###### Create Folder
    Create-Folder $RootFolder
    Create-Folder $LogPathFolder
    Create-Folder $ReportPathFolder
    
    $Transcript_File = $LogPathFolder + "Transcript_" + $Date + ".txt"
    Start-Transcript -Path $Transcript_File -Append -Force
    ########### Initiate the Process log file when the script started ############
    $Initiat_LogA = "#################### starting the Script #####################"
    $Startat = "### The Script has been launch at $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")"
    $Startwith = "The Script has been start with the following Account:" + [Environment]::UserName
    $Starton = "The Script has been start on the following Computer:" + [Environment]::MachineName
    $Initiat_LogB = "##############################################################"
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogA | Out-File -FilePath $LogFile -Append
    $Startat | Out-File -FilePath $LogFile -Append
    $Startwith | Out-File -FilePath $LogFile -Append
    $Starton | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    
    ###############################################################################################################################################################################
    #################################################################### Main Script #####################################################################
    ###############################################################################################################################################################################
    
    #Found License Name
    Try
    {
        $LocalPath = ".\MapSKUID.csv"
        If (!(Test-Path $LocalPath))
        {
            Write-Log warning -Message "The script Download Microsoft Licensing CSV File"
            $URL = "https://download.microsoft.com/download/e/3/e/e3e9faf2-f28b-490a-9ada-c6089a1fc5b0/Product%20names%20and%20service%20plan%20identifiers%20for%20licensing.csv"
            $LocalPath = ".\MapSKUID.csv"
            Invoke-WebRequest -Uri $URL -OutFile $LocalPath
            
            
        }
        Else
        {
            Write-Log warning -Message "The folder $LocalPath is already exist"
            
        }
        $MicrosoftSKUs = Import-Csv $LocalPath
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to download $LocalPath"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
    }
    
    # Found MgUsers
    Try
    {
        #Read-Host "The script going to retreive all users from the tenant"
        # All Users
        If ($Type -eq "All")
        {
            $Users = Get-MgUser -all -filter "usertype ne 'Guest'" -Countvariable CountVar -ConsistencyLevel eventual -Property SignInSessionsValidFromDateTime, RefreshTokensValidFromDateTime,CreatedDateTime, OnPremisesDistinguishedName, OnPremisesImmutableId, OnPremisesLastSyncDateTime, OnPremisesSamAccountName, OnPremisesSyncEnabled, OnPremisesUserPrincipalName, SignInActivity, MailNickname, UserType, AssignedLicenses, DisplayName, UserPrincipalName, JobTitle, Department, AccountEnabled, Mail, LastPasswordChangeDateTime, OnPremisesExtensionAttributes
            $ReportFile = $ReportPathFolder + "All_Report_Users_" + $DateFull + ".xlsx"
            Write-Log -Level INFO -Message "The script find All Users from the tenant"
        }
        # All Enable Users
        If ($Type -eq "Enable")
        {
            $Users = Get-MgUser -all -filter "accountenabled eq true and usertype ne 'Guest'" -Countvariable CountVar -ConsistencyLevel eventual -Property SignInSessionsValidFromDateTime, RefreshTokensValidFromDateTime,CreatedDateTime, OnPremisesDistinguishedName, OnPremisesImmutableId, OnPremisesLastSyncDateTime, OnPremisesSamAccountName, OnPremisesSyncEnabled, OnPremisesUserPrincipalName, SignInActivity, MailNickname, UserType, AssignedLicenses, DisplayName, UserPrincipalName, JobTitle, Department, AccountEnabled, Mail, LastPasswordChangeDateTime, OnPremisesExtensionAttributes
            $ReportFile = $ReportPathFolder + "Enable_Report_Users_" + $DateFull + ".xlsx"
            Write-Log -Level INFO -Message "The script find all Enable Users from the tenant"
        }
        # All Disabled Users
        If ($Type -eq "Disable")
        {
            $Users = Get-MgUser -all -filter "accountenabled eq false and usertype ne 'Guest'" -Countvariable CountVar -ConsistencyLevel eventual -Property SignInSessionsValidFromDateTime, RefreshTokensValidFromDateTime,CreatedDateTime, OnPremisesDistinguishedName, OnPremisesImmutableId, OnPremisesLastSyncDateTime, OnPremisesSamAccountName, OnPremisesSyncEnabled, OnPremisesUserPrincipalName, SignInActivity, MailNickname, UserType, AssignedLicenses, DisplayName, UserPrincipalName, JobTitle, Department, AccountEnabled, Mail, LastPasswordChangeDateTime, OnPremisesExtensionAttributes
            $ReportFile = $ReportPathFolder + "Disable_Report_Users_" + $DateFull + ".xlsx"
            Write-Log -Level INFO -Message "The script find all Disable Users from the tenant"
        }
        
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log -Level Error -LogPath $LogFile -Message "Failed to Find MgUsers"
        Write-Log -Level Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log -Level Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
        Write-Log -Level Error -LogPath $LogFile -Message "The Script will stop"
        # Exit the script
        Read-Host "End of Script"
    }
    
    # Loop
    $UsersInfo = $Null
    $UsersInfo = @()
    [Int]$i = 1
    $Count = ($Users | Measure).count
    foreach ($UserData in $Users)
    {
        $UserUPN = $UserData.UserPrincipalName
        Write-Log -Level warning -LogPath $LogFile -Message "The script is analyzing $UserUPN --- $i/$Count"
        # MgUser
        
        Write-log Warning -Message "The Script is searching for the MgUser: $UserUPN"
        $FoundMgUserStatus = "Yes"
        $LastNonInteractiveSignInDateTime = $Null
        $LastSignInDateTime = $Null
        $SignInSessionsValidFromDateTime = $Null
        $RefreshTokensValidFromDateTime = $Null
        $CreatedDateTime = $Null
        $OnPremisesDistinguishedName = $Null
        $OnPremisesImmutableId = $Null
        $OnPremisesLastSyncDateTime = $Null
        $OnPremisesSamAccountName = $Null
        $OnPremisesSyncEnabled = $Null
        $OnPremisesUserPrincipalName = $Null
        $MailNickname = $Null
        $DisplayName = $Null
        $UserPrincipalName = $Null
        $Department = $Null
        $Tittle = $Null
        $AccountEnabled = $Null
        $Mail = $Null
        $LastPasswordChangeDateTime = $Null
        $UserType = $Null
        $AssignedLicenses = $Null
        $Licenses = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute1 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute2 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute3 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute4 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute5 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute6 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute7 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute8 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute9 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute10 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute11 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute12 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute13 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute14 = $Null
        $OnPremisesExtensionAttributes_ExtensionAttribute15 = $Null
        If ($UserData.signinActivity.LastNonInteractiveSignInDateTime.DateTime)
        {
            $LastNonInteractiveSignInDateTime = Get-Date ($UserData.signinActivity.LastNonInteractiveSignInDateTime.DateTime) -Format "G"
            $LastNonInteractiveSignInDateTime = [datetime]::Parse($LastNonInteractiveSignInDateTime)
        }
        If ($UserData.SignInActivity.LastSignInDateTime.DateTime)
        {
            $LastSignInDateTime = Get-Date ($UserData.SignInActivity.LastSignInDateTime.DateTime) -Format "G"
            $LastSignInDateTime = [datetime]::Parse($LastSignInDateTime)
        }
        If ($UserData.SignInSessionsValidFromDateTime.DateTime)
        {
            $SignInSessionsValidFromDateTime = Get-Date ($UserData.SignInSessionsValidFromDateTime.DateTime) -Format "G"
            $SignInSessionsValidFromDateTime = [datetime]::Parse($SignInSessionsValidFromDateTime)
        }
        If ($UserData.RefreshTokensValidFromDateTime.DateTime)
        {
            $RefreshTokensValidFromDateTime = Get-Date ($UserData.RefreshTokensValidFromDateTime.DateTime) -Format "G"
            $RefreshTokensValidFromDateTime = [datetime]::Parse($RefreshTokensValidFromDateTime)
        }
        $OnPremisesDistinguishedName = $UserData.OnPremisesDistinguishedName
        $OnPremisesImmutableId = $UserData.OnPremisesImmutableId
        $OnPremisesLastSyncDateTime = $UserData.OnPremisesLastSyncDateTime
        $OnPremisesSamAccountName = $UserData.OnPremisesSamAccountName
        $OnPremisesSyncEnabled = $UserData.OnPremisesSyncEnabled
        $OnPremisesUserPrincipalName = $UserData.OnPremisesUserPrincipalName
        $MailNickname = $UserData.MailNickname
        $DisplayName = $UserData.DisplayName
        $UserPrincipalName = $UserData.UserPrincipalName
        $Department = $UserData.Department
        $Tittle = $UserData.JobTitle
        $AccountEnabled = $UserData.AccountEnabled
        $Mail = $UserData.Mail
        $LastPasswordChangeDateTime = $UserData.LastPasswordChangeDateTime
        $UserType = $UserData.UserType
        $AssignedLicenses = $UserData.AssignedLicenses
        $OnPremisesExtensionAttributes_ExtensionAttribute1 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute1
        $OnPremisesExtensionAttributes_ExtensionAttribute2 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute2
        $OnPremisesExtensionAttributes_ExtensionAttribute3 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute3
        $OnPremisesExtensionAttributes_ExtensionAttribute4 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute4
        $OnPremisesExtensionAttributes_ExtensionAttribute5 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute5
        $OnPremisesExtensionAttributes_ExtensionAttribute6 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute6
        $OnPremisesExtensionAttributes_ExtensionAttribute7 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute7
        $OnPremisesExtensionAttributes_ExtensionAttribute8 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute8
        $OnPremisesExtensionAttributes_ExtensionAttribute9 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute9
        $OnPremisesExtensionAttributes_ExtensionAttribute10 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute10
        $OnPremisesExtensionAttributes_ExtensionAttribute11 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute11
        $OnPremisesExtensionAttributes_ExtensionAttribute12 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute12
        $OnPremisesExtensionAttributes_ExtensionAttribute13 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute13
        $OnPremisesExtensionAttributes_ExtensionAttribute14 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute14
        $OnPremisesExtensionAttributes_ExtensionAttribute15 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute15
        $CreatedDateTime = $UserData.CreatedDateTime
        
        $UserLicenses = @()
        foreach ($AssignedLicense in $AssignedLicenses)
        {
            $SkuId = $Null
            $SkuId = $AssignedLicense.SkuId
            $UserLicenses += ($MicrosoftSKUs | where { $_.GUID -eq $SkuId } | Select -first 1).Product_Display_Name
        }
        $Licenses = $UserLicenses -join ";"
        
        
        # Recipient
        $FoundRecipientStatus = "No"
        $DeletedItemCount = "Not a Mailbox"
        $ItemCount = "Not a Mailbox"
        $TotalDeletedItemSize = "Not a Mailbox"
        $TotalItemSize = "Not a Mailbox"
        $FoundMailboxStatisticsStatus = "Not a Mailbox"
        $IsMailboxEnabled = "Not a Mailbox"
        $Recipient = $Null
        $FoundRecipientStatus = "No"
        Try
        {
            
            Write-log Warning -Message "The Script is searching for the Recipient: $UserUPN"
            $Recipient = $Recipient = Get-Recipient $UserUPN
            Write-Log Info -Message "The script find the recipient $UserUPN"
            $FoundRecipientStatus = "Yes"
            $PrimarySmtpAddress = $Recipient.PrimarySmtpAddress
            $RecipientTypeDetails = $Recipient.RecipientTypeDetails
            $IsDirSynced = $Recipient.IsDirSynced
            $WhenMailboxCreated = $Recipient.WhenMailboxCreated
            $WhenSoftDeleted = $Recipient.WhenSoftDeleted
            $WhenCreated = $Recipient.WhenCreated
            $DeletedItemCount = "Not a Mailbox"
            $ItemCount = "Not a Mailbox"
            $TotalDeletedItemSize = "Not a Mailbox"
            $TotalItemSize = "Not a Mailbox"
            $FoundMailboxStatisticsStatus = "Not a Mailbox"
            $IsMailboxEnabled = "Not a Mailbox"
            If ($RecipientTypeDetails -like "*Mailbox")
            {
                
                #Mailbox Data
                $IsMailboxEnabled = "No Data Found"
                Try
                {
                    Write-Log warning -Message "The script retreive Mailbox Data for $PrimarySmtpAddress"
                    $MailboxData = $Null
                    $MailboxData = Get-Mailbox $PrimarySmtpAddress
                    $IsMailboxEnabled = $MailboxData.IsMailboxEnabled
                    Write-Log Info -Message "The script retreived Mailbox Data for $PrimarySmtpAddress"
                    $FoundMailboxDataStatus = "Yes"
                }
                Catch
                {
                    $ErrorMessage = $Error[0].Exception.Message
                    $CMDLet = $Error[0].InvocationInfo.Line
                    $FailedItem = $Error[0].Exception.ItemName
                    Write-Log Error -Message "Failed to retreive Mailbox Data for $PrimarySmtpAddress"
                    Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                    Write-Log Error -Message "Failed with Error:$ErrorMessage"
                    $FoundMailboxDataStatus = "Failed with Error:$ErrorMessage"
                    
                    
                }
                #MailboxStatistics
                $DeletedItemCount = "No Data Found"
                $ItemCount = "No Data Found"
                $TotalDeletedItemSize = "No Data Found"
                $TotalItemSize = "No Data Found"
                Try
                {
                    Write-Log warning -Message "The script search Mailbox Statistics for $PrimarySmtpAddress"
                    $MailboxStatistics = Get-EXOMailboxStatistics $PrimarySmtpAddress
                    $DeletedItemCount = $MailboxStatistics.DeletedItemCount
                    $ItemCount = $MailboxStatistics.ItemCount
                    $TotalDeletedItemSize = $MailboxStatistics.TotalDeletedItemSize
                    $TotalItemSize = $MailboxStatistics.TotalItemSize
                    Write-Log Info -Message "The script found Mailbox Statistics info for $PrimarySmtpAddress"
                    $FoundMailboxStatisticsStatus = "Yes"
                }
                Catch
                {
                    $ErrorMessage = $Error[0].Exception.Message
                    $CMDLet = $Error[0].InvocationInfo.Line
                    $FailedItem = $Error[0].Exception.ItemName
                    Write-Log Error -Message "Failed to Retreive MailboxStatistics for $PrimarySmtpAddress"
                    Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                    Write-Log Error -Message "Failed with Error:$ErrorMessage"
                    $FoundMailboxStatisticsStatus = "Failed with Error:$ErrorMessage"
                    $DeletedItemCount = "Failed"
                    $ItemCount = "Failed"
                    $TotalDeletedItemSize = "Failed"
                    $TotalItemSize = "Failed"
                    
                }
                
                #Mailbox Permissions
                $MailboxPermissionUsers = "No Data Found"
                $MailboxPermissionAccessRights = "No Data Found"
                $RecipientPermissionTrustees = "No Data Found"
                $RecipientPermissionAccessRights = "No Data Found"
                
                Try
                {
                    Write-Log warning -Message "The script search Mailbox Permissions for $PrimarySmtpAddress"
                    $EXORecipientPermissions = Get-EXORecipientPermission $PrimarySmtpAddress
                    $EXOMailboxPermissions = Get-EXOMailboxPermission $PrimarySmtpAddress
                    $MailboxPermissionUsers = $EXOMailboxPermissions.User -join ";"
                    $MailboxPermissionAccessRights = $EXOMailboxPermissions.AccessRights -join ";"
                    $RecipientPermissionTrustees = $EXORecipientPermissions.Trustee -join ";"
                    $RecipientPermissionAccessRights = $EXORecipientPermissions.AccessRights -join ";"
                    Write-Log Info -Message "The script found Mailbox Permissions info for $PrimarySmtpAddress"
                    $FoundMailboxStatisticsStatus = "Yes"
                }
                Catch
                {
                    $ErrorMessage = $Error[0].Exception.Message
                    $CMDLet = $Error[0].InvocationInfo.Line
                    $FailedItem = $Error[0].Exception.ItemName
                    Write-Log Error -Message "Failed to Retreive MailboxStatistics for $PrimarySmtpAddress"
                    Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                    Write-Log Error -Message "Failed with Error:$ErrorMessage"
                    $FoundMailboxStatisticsStatus = "Failed with Error:$ErrorMessage"
                    $MailboxPermissionUsers = "Failed"
                    $MailboxPermissionAccessRights = "Failed"
                    $RecipientPermissionTrustees = "Failed"
                    $RecipientPermissionAccessRights = "Failed"
                }
                
            }
            Else
            {
                $DeletedItemCount = "Not a Mailbox"
                $ItemCount = "Not a Mailbox"
                $TotalDeletedItemSize = "Not a Mailbox"
                $TotalItemSize = "Not a Mailbox"
                $MailboxPermissionUsers = "Not a Mailbox"
                $MailboxPermissionAccessRights = "Not a Mailbox"
                $RecipientPermissionTrustees = "Not a Mailbox"
                $RecipientPermissionAccessRights = "Not a Mailbox"
            }
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -Message "Failed to find MgUser $UserUPN"
            Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -Message "Failed with Error:$ErrorMessage"
            $FoundRecipientStatus = "Failed with Error:$ErrorMessage"
        }
        
        $UsersInfo += New-object PSobject -Property ([Ordered] @{
                DisplayName                                           = $DisplayName;
                Tittle                                               = $Tittle;
                Department                                           = $Department;
                AccountEnabled                                       = $AccountEnabled;
                Mail                                               = $Mail;
                UserPrincipalName                                   = $UserPrincipalName;
                LastNonInteractiveSignInDateTime                   = $LastNonInteractiveSignInDateTime;
                LastSignInDateTime                                   = $LastSignInDateTime;
                SignInSessionsValidFromDateTime                       = $SignInSessionsValidFromDateTime;
                RefreshTokensValidFromDateTime                       = $RefreshTokensValidFromDateTime;
                LastPasswordChangeDateTime                           = $LastPasswordChangeDateTime;
                OnPremisesDistinguishedName                           = $OnPremisesDistinguishedName;
                OnPremisesImmutableId                               = $OnPremisesImmutableId;
                OnPremisesLastSyncDateTime                           = $OnPremisesLastSyncDateTime;
                OnPremisesSamAccountName                           = $OnPremisesSamAccountName;
                OnPremisesSyncEnabled                               = $OnPremisesSyncEnabled;
                OnPremisesUserPrincipalName                           = $OnPremisesUserPrincipalName;
                OnPremisesExtensionAttributes_ExtensionAttribute1  = $OnPremisesExtensionAttributes_ExtensionAttribute1;
                OnPremisesExtensionAttributes_ExtensionAttribute2  = $OnPremisesExtensionAttributes_ExtensionAttribute2;
                OnPremisesExtensionAttributes_ExtensionAttribute3  = $OnPremisesExtensionAttributes_ExtensionAttribute3;
                OnPremisesExtensionAttributes_ExtensionAttribute4  = $OnPremisesExtensionAttributes_ExtensionAttribute4;
                OnPremisesExtensionAttributes_ExtensionAttribute5  = $OnPremisesExtensionAttributes_ExtensionAttribute5;
                OnPremisesExtensionAttributes_ExtensionAttribute6  = $OnPremisesExtensionAttributes_ExtensionAttribute6;
                OnPremisesExtensionAttributes_ExtensionAttribute7  = $OnPremisesExtensionAttributes_ExtensionAttribute7;
                OnPremisesExtensionAttributes_ExtensionAttribute8  = $OnPremisesExtensionAttributes_ExtensionAttribute8;
                OnPremisesExtensionAttributes_ExtensionAttribute9  = $OnPremisesExtensionAttributes_ExtensionAttribute9;
                OnPremisesExtensionAttributes_ExtensionAttribute10 = $OnPremisesExtensionAttributes_ExtensionAttribute10;
                OnPremisesExtensionAttributes_ExtensionAttribute11 = $OnPremisesExtensionAttributes_ExtensionAttribute11;
                OnPremisesExtensionAttributes_ExtensionAttribute12 = $OnPremisesExtensionAttributes_ExtensionAttribute12;
                OnPremisesExtensionAttributes_ExtensionAttribute13 = $OnPremisesExtensionAttributes_ExtensionAttribute13;
                OnPremisesExtensionAttributes_ExtensionAttribute14 = $OnPremisesExtensionAttributes_ExtensionAttribute14;
                OnPremisesExtensionAttributes_ExtensionAttribute15 = $OnPremisesExtensionAttributes_ExtensionAttribute15;
                CreatedDateTime                                       = $CreatedDateTime;
                MailNickname                                       = $MailNickname;
                UserType                                           = $UserType;
                Licenses                                           = $Licenses;
                FoundRecipient                                       = $FoundRecipientStatus;
                PrimarySmtpAddress                                   = $PrimarySmtpAddress;
                RecipientTypeDetails                               = $RecipientTypeDetails;
                IsDirSynced                                           = $IsDirSynced;
                IsMailboxEnabled                                   = $IsMailboxEnabled;
                WhenMailboxCreated                                   = $WhenMailboxCreated;
                WhenSoftDeleted                                       = $WhenSoftDeleted;
                WhenCreated                                           = $WhenCreated;
                FoundMailboxStatistics                               = $FoundMailboxStatisticsStatus;
                DeletedItemCount                                   = $DeletedItemCount;
                ItemCount                                           = $ItemCount;
                TotalDeletedItemSize                               = $TotalDeletedItemSize;
                TotalItemSize                                       = $TotalItemSize;
                MailboxPermissionUsers                               = $MailboxPermissionUsers;
                MailboxPermissionAccessRights                       = $MailboxPermissionAccessRights;
                RecipientPermissionTrustees                           = $RecipientPermissionTrustees;
                RecipientPermissionAccessRights                       = $RecipientPermissionAccessRights;
            })
        $i++
    }
    
    $UsersInfo | Export-Excel $ReportFile -TableName "UsersReport" -Title "Users Report" -TitleBold -WorksheetName "UsersReport" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFile"
}
Function Disable-UserMailboxForDepartureUsingCSV
{
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$CSVFile,
        [Parameter(Mandatory = $true,
                   Position = 2)]
        [String]$Admin
    )
    
    ###############################################################################################################################################################################
    #################################################################### Variable #####################################################################
    ###############################################################################################################################################################################
    $Date = get-date -UFormat %d%m%Y
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ServerName = [Environment]::MachineName
    ###### Create Root Folder
    $RootFolder = $psscriptRoot + "\DisabledUsers"
    
    ###### Create folder Variable
    $LogPathFolder = $RootFolder + "\Log\"
    $LogFile = $LogPathFolder + "Progress_" + $Date + ".log"
    
    
    $ReportPathFolder = $RootFolder + "\Reports\"
    $ReportFile = $ReportPathFolder + "DisabledUsers_" + $DateFull + ".xlsx"
    ###### Create Folder
    Create-Folder $RootFolder
    Create-Folder $LogPathFolder
    Create-Folder $ReportPathFolder
    
    $Transcript_File = $LogPathFolder + "Transcript_" + $Date + ".txt"
    Start-Transcript -Path $Transcript_File -Append -Force
    ########### Initiate the Process log file when the script started ############
    $Initiat_LogA = "#################### starting the Script #####################"
    $Startat = "### The Script has been launch at $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")"
    $Startwith = "The Script has been start with the following Account:" + [Environment]::UserName
    $Starton = "The Script has been start on the following Computer:" + [Environment]::MachineName
    $Initiat_LogB = "##############################################################"
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogA | Out-File -FilePath $LogFile -Append
    $Startat | Out-File -FilePath $LogFile -Append
    $Startwith | Out-File -FilePath $LogFile -Append
    $Starton | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    $Initiat_LogB | Out-File -FilePath $LogFile -Append
    
    ###############################################################################################################################################################################
    #################################################################### Main Script #####################################################################
    ###############################################################################################################################################################################
    
    # Import CSVFile
    Try
    {
        Read-Host "Expected CSV Column: UPN"
        $Users = Import-Csv $CSVFile
        Write-Log -Level INFO -LogPath $LogFile -Message "The script import successfully :$CSVFile"
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log -Level Error -LogPath $LogFile -Message "Failed to import $CSVFile "
        Write-Log -Level Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log -Level Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
        Write-Log -Level Error -LogPath $LogFile -Message "The Script will stop"
        # Exit the script
        Read-Host "End of Script"
    }
    
    #Initiate the Hash Table
    [Int]$i = 1
    $Table = $Null
    $Table = @()
    $Count = ($Users | Measure).count
    
    foreach ($User in $Users)
    {
        $Primary = $null
        $Primary = $User.UPN
        
        # Disable MgUser
        Try
        {
            Write-Log warning -LogPath $LogFile -Message "The script will Disable MgUser $Primary --- $i/$Count"
            Disable-MgAccount -UPN $Primary -Confirm
            Write-Log Info -LogPath $LogFile -Message "The script Disable MgUser $Primary"
            $DisabledMgUserStatus = "success"
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -LogPath $LogFile -Message "Failed to Disable MgUser $Primary"
            Write-Log Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
            $DisabledMgUserStatus = "Failed with Error:$ErrorMessage"
        }
        
        
        
        # Get Mailbox Data
        Try
        {
            Write-Log warning -LogPath $LogFile -Message "The script will get $Primary to Maiblox Data"
            $Mailbox = $Null
            $Mailbox = Get-Mailbox $Primary
            Write-Log Info -LogPath $LogFile -Message "The script get Mailbox Data for $Primary"
            
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -LogPath $LogFile -Message "Failed to get Mailbox Data for $Primary"
            Write-Log Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
            $GetMailboxDataStatus = "Failed with Error:$ErrorMessage"
        }
        # Change Name
        Try
        {
            $DisplayName = $Null
            $Name = $Null
            $DisplayName = $Mailbox.DisplayName
            $Name = $Mailbox.Name
            $NewDisplayName = $Null
            $NewName = $Null
            $NewDisplayName = "[Disable] - " + $DisplayName
            $NewName = "[Disable] - " + $Name
            
            Write-Log warning -LogPath $LogFile -Message "The script will change $Primary DisplayName From $DisplayName to $NewDisplayName - Name from $Name to $NewName"
            Set-Mailbox $Primary -DisplayName $NewDisplayName -Name $NewName
            Write-Log Info -LogPath $LogFile -Message "The script changed $Primary DisplayName From $DisplayName to $NewDisplayName - Name from $Name to $NewName"
            $ChangeNamesStatus = "Success"
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -LogPath $LogFile -Message "Failed to change $Primary DisplayName From $DisplayName to $NewDisplayName - Name from $Name to $NewName"
            Write-Log Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
            $ChangeNamesStatus = "Failed with Error:$ErrorMessage"
        }
        # Convert to shared
        Try
        {
            Write-Log warning -LogPath $LogFile -Message "The script will convert $Primary to Shared mailbox"
            Set-Mailbox $Primary -Type Shared
            Write-Log Info -LogPath $LogFile -Message "The script converted $Primary to shared mailbox"
            $ConvertToSharedStatus = "Success"
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -LogPath $LogFile -Message "Failed to convert $Primary to Shared Mailbox"
            Write-Log Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
            $ConvertToSharedStatus = "Failed with Error:$ErrorMessage"
        }
        
        
        # Disable Mail Flow
        Try
        {
            Write-Log warning -LogPath $LogFile -Message "The script will disable Mail Flow for $Primary"
            Set-Mailbox $Primary -RequireSenderAuthenticationEnabled $True -AcceptMessagesOnlyFrom $Primary
            Write-Log Info -LogPath $LogFile -Message "The script disabled Mail Flow for $Primary"
            $DisableMailFlowStatus = "Success"
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -LogPath $LogFile -Message "Failed to disable Mail Flow for $Primary"
            Write-Log Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
            $DisableMailFlowStatus = "Failed with Error:$ErrorMessage"
        }
        
        # Hide from the GAL
        Try
        {
            Write-Log warning -LogPath $LogFile -Message "The script will hide the mailbox $Primary from the GAL"
            Set-Mailbox $Primary -RequireSenderAuthenticationEnabled $True -HiddenFromAddressListsEnabled $True -AcceptMessagesOnlyFrom $Primary
            Write-Log Info -LogPath $LogFile -Message "The script hid the mailbox $Primary from the GAL"
            $HiddenFromGALStatus = "Success"
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -LogPath $LogFile -Message "Failed to hide the mailbox $Primary from the GAL"
            Write-Log Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
            $HiddenFromGALStatus = "Failed with Error:$ErrorMessage"
        }
        
        
        # Full Access Permission without AutoMapping
        Try
        {
            Write-Log warning -LogPath $LogFile -Message "The script will grant $Admin Full Access without AutoMapping to $Primary"
            Add-MailboxPermission -Identity $Primary -User $Admin -AccessRights FullAccess -AutoMapping:$false
            Write-Log Info -LogPath $LogFile -Message "The script disabled Mail Flow and hide the mailbox from the GAL"
            $GrantFullAccessStatus = "Success"
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -LogPath $LogFile -Message "Failed to disable Mail Flow and hide the mailbox from the GAL"
            Write-Log Error -LogPath $LogFile -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -LogPath $LogFile -Message "Failed with Error:$ErrorMessage"
            $GrantFullAccessStatus = "Failed with Error:$ErrorMessage"
        }
        
        $Table += New-object PSobject -Property ([Ordered] @{
                Primary                  = $Primary;
                DisplayName              = $DisplayName;
                NewDisplayName          = $NewDisplayName;
                Name                  = $Name;
                NewName                  = $NewName;
                DisabledMgUserStatus  = $DisabledMgUserStatus;
                ChangeNamesStatus      = $ChangeNamesStatus;
                ConvertToSharedStatus = $ConvertToSharedStatus;
                DisableMailFlowStatus = $DisableMailFlowStatus;
                HiddenFromGALStatus   = $HiddenFromGALStatus;
                GrantFullAccessStatus = $GrantFullAccessStatus
            })
        $i++
    }
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ReportFilexlsx = ".\Report_DisabledUsers_" + $DateFull + ".xlsx"
    $Table | Export-Excel $ReportFilexlsx -TableName "DisabledUsers" -Title "Disabled Users" -TitleBold -WorksheetName "DisabledUsers" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -LogPath $LogFile -Message "Generate the following Report: $ReportFilexlsx"
}
Function Get-MgRecipientUser
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$UPN
    )
    $MgRecipientUser = @()
    #Found License Name
    Try
    {
        $LocalPath = ".\MapSKUID.csv"
        If (!(Test-Path $LocalPath))
        {
            Write-Log warning -Message "The script Download Microsoft Licensing CSV File"
            $URL = "https://download.microsoft.com/download/e/3/e/e3e9faf2-f28b-490a-9ada-c6089a1fc5b0/Product%20names%20and%20service%20plan%20identifiers%20for%20licensing.csv"
            $LocalPath = ".\MapSKUID.csv"
            Invoke-WebRequest -Uri $URL -OutFile $LocalPath
            
        }
        Else
        {
            Write-Log warning -Message "The folder $LocalPath is already exist"
        }
        $MicrosoftSKUs = Import-Csv $LocalPath
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to download $LocalPath"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
    }
    # MgUser
    $FoundMgUserStatus = "No"
    
    Try
    {
        
        Write-log Warning -Message "The Script is searching for the MgUser: $UPN"
        $User = Get-MgUser -UserId $UPN
        $UserIdentity = $User.ID
        $UserData = Get-MgUser -UserId $UserIdentity -Property SignInSessionsValidFromDateTime, RefreshTokensValidFromDateTime, CreatedDateTime, OnPremisesDistinguishedName, OnPremisesImmutableId, OnPremisesLastSyncDateTime, OnPremisesSamAccountName, OnPremisesSyncEnabled, OnPremisesUserPrincipalName, SignInActivity, MailNickname, UserType, AssignedLicenses, DisplayName, UserPrincipalName, JobTitle, Department, AccountEnabled, Mail, LastPasswordChangeDateTime, OnPremisesExtensionAttributes
        Write-Log Info -Message "The script find the MgUser $UPN (DN: $UserIdentity)"
        $FoundMgUserStatus = "Yes"
        If ($UserData.signinActivity.LastNonInteractiveSignInDateTime.DateTime)
        {
            $LastNonInteractiveSignInDateTime = Get-Date ($UserData.signinActivity.LastNonInteractiveSignInDateTime.DateTime) -Format "G"
            $LastNonInteractiveSignInDateTime = [datetime]::Parse($LastNonInteractiveSignInDateTime)
        }
        If ($UserData.SignInActivity.LastSignInDateTime.DateTime)
        {
            $LastSignInDateTime = Get-Date ($UserData.SignInActivity.LastSignInDateTime.DateTime) -Format "G"
            $LastSignInDateTime = [datetime]::Parse($LastSignInDateTime)
        }
        If ($UserData.SignInSessionsValidFromDateTime.DateTime)
        {
            $SignInSessionsValidFromDateTime = Get-Date ($UserData.SignInSessionsValidFromDateTime.DateTime) -Format "G"
            $SignInSessionsValidFromDateTime = [datetime]::Parse($SignInSessionsValidFromDateTime)
        }
        If ($UserData.RefreshTokensValidFromDateTime.DateTime)
        {
            $RefreshTokensValidFromDateTime = Get-Date ($UserData.RefreshTokensValidFromDateTime.DateTime) -Format "G"
            $RefreshTokensValidFromDateTime = [datetime]::Parse($RefreshTokensValidFromDateTime)
        }
        
        $OnPremisesDistinguishedName = $UserData.OnPremisesDistinguishedName
        $OnPremisesImmutableId = $UserData.OnPremisesImmutableId
        $OnPremisesLastSyncDateTime = $UserData.OnPremisesLastSyncDateTime
        $OnPremisesSamAccountName = $UserData.OnPremisesSamAccountName
        $OnPremisesSyncEnabled = $UserData.OnPremisesSyncEnabled
        $OnPremisesUserPrincipalName = $UserData.OnPremisesUserPrincipalName
        $MailNickname = $UserData.MailNickname
        $DisplayName = $UserData.DisplayName
        $UserPrincipalName = $UserData.UserPrincipalName
        $Department = $UserData.Department
        $Tittle = $UserData.JobTitle
        $AccountEnabled = $UserData.AccountEnabled
        $Mail = $UserData.Mail
        $LastPasswordChangeDateTime = $UserData.LastPasswordChangeDateTime
        $UserType = $UserData.UserType
        $AssignedLicenses = $UserData.AssignedLicenses
        $OnPremisesExtensionAttributes_ExtensionAttribute1 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute1
        $OnPremisesExtensionAttributes_ExtensionAttribute2 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute2
        $OnPremisesExtensionAttributes_ExtensionAttribute3 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute3
        $OnPremisesExtensionAttributes_ExtensionAttribute4 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute4
        $OnPremisesExtensionAttributes_ExtensionAttribute5 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute5
        $OnPremisesExtensionAttributes_ExtensionAttribute6 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute6
        $OnPremisesExtensionAttributes_ExtensionAttribute7 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute7
        $OnPremisesExtensionAttributes_ExtensionAttribute8 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute8
        $OnPremisesExtensionAttributes_ExtensionAttribute9 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute9
        $OnPremisesExtensionAttributes_ExtensionAttribute10 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute10
        $OnPremisesExtensionAttributes_ExtensionAttribute11 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute11
        $OnPremisesExtensionAttributes_ExtensionAttribute12 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute12
        $OnPremisesExtensionAttributes_ExtensionAttribute13 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute13
        $OnPremisesExtensionAttributes_ExtensionAttribute14 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute14
        $OnPremisesExtensionAttributes_ExtensionAttribute15 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute15
        $CreatedDateTime = $UserData.CreatedDateTime
        
        $UserLicenses = @()
        foreach ($AssignedLicense in $AssignedLicenses)
        {
            $SkuId = $Null
            $SkuId = $AssignedLicense.SkuId
            $UserLicenses += ($MicrosoftSKUs | where { $_.GUID -eq $SkuId } | Select -first 1).Product_Display_Name
        }
        $Licenses = $UserLicenses -join ";"
        
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to find MgUser $UPN"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
        $FoundMgUserStatus = "Failed with Error:$ErrorMessage"
    }
    # Recipient
    $FoundRecipientStatus = "No"
    Try
    {
        
        Write-log Warning -Message "The Script is searching for the Recipient: $UPN"
        $Recipient = $Recipient = Get-Recipient $UPN
        Write-Log Info -Message "The script find the recipient $UPN (DN: $UserIdentity)"
        $FoundRecipientStatus = "Yes"
        $PrimarySmtpAddress = $Recipient.PrimarySmtpAddress
        $RecipientTypeDetails = $Recipient.RecipientTypeDetails
        $IsDirSynced = $Recipient.IsDirSynced
        $WhenMailboxCreated = $Recipient.WhenMailboxCreated
        $WhenSoftDeleted = $Recipient.WhenSoftDeleted
        $WhenCreated = $Recipient.WhenCreated
        $DeletedItemCount = "Not a Mailbox"
        $ItemCount = "Not a Mailbox"
        $TotalDeletedItemSize = "Not a Mailbox"
        $TotalItemSize = "Not a Mailbox"
        $FoundMailboxStatisticsStatus = "Not a Mailbox"
        $IsMailboxEnabled = "Not a Mailbox"
        If ($RecipientTypeDetails -like "*Mailbox")
        {
            
            #Mailbox Data
            $IsMailboxEnabled = "No Data Found"
            Try
            {
                Write-Log warning -Message "The script retreive Mailbox Data for $PrimarySmtpAddress"
                $MailboxData = $Null
                $MailboxData = Get-Mailbox $PrimarySmtpAddress
                $IsMailboxEnabled = $MailboxData.IsMailboxEnabled
                Write-Log Info -Message "The script retreived Mailbox Data for $PrimarySmtpAddress"
                $FoundMailboxDataStatus = "Yes"
            }
            Catch
            {
                $ErrorMessage = $Error[0].Exception.Message
                $CMDLet = $Error[0].InvocationInfo.Line
                $FailedItem = $Error[0].Exception.ItemName
                Write-Log Error -Message "Failed to retreive Mailbox Data for $PrimarySmtpAddress"
                Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                Write-Log Error -Message "Failed with Error:$ErrorMessage"
                $FoundMailboxDataStatus = "Failed with Error:$ErrorMessage"
                
                
            }
            #MailboxStatistics
            $DeletedItemCount = "No Data Found"
            $ItemCount = "No Data Found"
            $TotalDeletedItemSize = "No Data Found"
            $TotalItemSize = "No Data Found"
            Try
            {
                Write-Log warning -Message "The script search Mailbox Statistics for $PrimarySmtpAddress"
                $MailboxStatistics = Get-EXOMailboxStatistics $PrimarySmtpAddress
                $DeletedItemCount = $MailboxStatistics.DeletedItemCount
                $ItemCount = $MailboxStatistics.ItemCount
                $TotalDeletedItemSize = $MailboxStatistics.TotalDeletedItemSize
                $TotalItemSize = $MailboxStatistics.TotalItemSize
                Write-Log Info -Message "The script found Mailbox Statistics info for $PrimarySmtpAddress"
                $FoundMailboxStatisticsStatus = "Yes"
            }
            Catch
            {
                $ErrorMessage = $Error[0].Exception.Message
                $CMDLet = $Error[0].InvocationInfo.Line
                $FailedItem = $Error[0].Exception.ItemName
                Write-Log Error -Message "Failed to Retreive MailboxStatistics for $PrimarySmtpAddress"
                Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                Write-Log Error -Message "Failed with Error:$ErrorMessage"
                $FoundMailboxStatisticsStatus = "Failed with Error:$ErrorMessage"
                $DeletedItemCount = "Failed"
                $ItemCount = "Failed"
                $TotalDeletedItemSize = "Failed"
                $TotalItemSize = "Failed"
                
            }
            
            #Mailbox Permissions
            $MailboxPermissionUsers = "No Data Found"
            $MailboxPermissionAccessRights = "No Data Found"
            $RecipientPermissionTrustees = "No Data Found"
            $RecipientPermissionAccessRights = "No Data Found"
            
            Try
            {
                Write-Log warning -Message "The script search Mailbox Permissions for $PrimarySmtpAddress"
                $EXORecipientPermissions = Get-EXORecipientPermission $PrimarySmtpAddress
                $EXOMailboxPermissions = Get-EXOMailboxPermission $PrimarySmtpAddress
                $MailboxPermissionUsers = $EXOMailboxPermissions.User -join ";"
                $MailboxPermissionAccessRights = $EXOMailboxPermissions.AccessRights -join ";"
                $RecipientPermissionTrustees = $EXORecipientPermissions.Trustee -join ";"
                $RecipientPermissionAccessRights = $EXORecipientPermissions.AccessRights -join ";"
                Write-Log Info -Message "The script found Mailbox Permissions info for $PrimarySmtpAddress"
                $FoundMailboxStatisticsStatus = "Yes"
            }
            Catch
            {
                $ErrorMessage = $Error[0].Exception.Message
                $CMDLet = $Error[0].InvocationInfo.Line
                $FailedItem = $Error[0].Exception.ItemName
                Write-Log Error -Message "Failed to Retreive MailboxStatistics for $PrimarySmtpAddress"
                Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                Write-Log Error -Message "Failed with Error:$ErrorMessage"
                $FoundMailboxStatisticsStatus = "Failed with Error:$ErrorMessage"
                $MailboxPermissionUsers = "Failed"
                $MailboxPermissionAccessRights = "Failed"
                $RecipientPermissionTrustees = "Failed"
                $RecipientPermissionAccessRights = "Failed"
            }
            
        }
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to find MgUser $UPN"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
        $FoundRecipientStatus = "Failed with Error:$ErrorMessage"
    }
    
    $MgRecipientUser += New-object PSobject -Property ([Ordered] @{
            UPN                                                   = $UPN;
            Identity                                           = $UserIdentity;
            FoundMgUser                                           = $FoundMgUserStatus;
            DisplayName                                           = $DisplayName;
            Tittle                                               = $Tittle;
            Department                                           = $Department;
            AccountEnabled                                       = $AccountEnabled;
            Mail                                               = $Mail;
            UserPrincipalName                                   = $UserPrincipalName;
            LastNonInteractiveSignInDateTime                   = $LastNonInteractiveSignInDateTime;
            LastSignInDateTime                                   = $LastSignInDateTime;
            SignInSessionsValidFromDateTime                       = $SignInSessionsValidFromDateTime;
            RefreshTokensValidFromDateTime                       = $RefreshTokensValidFromDateTime;
            LastPasswordChangeDateTime                           = $LastPasswordChangeDateTime;
            OnPremisesDistinguishedName                           = $OnPremisesDistinguishedName;
            OnPremisesImmutableId                               = $OnPremisesImmutableId;
            OnPremisesLastSyncDateTime                           = $OnPremisesLastSyncDateTime;
            OnPremisesSamAccountName                           = $OnPremisesSamAccountName;
            OnPremisesSyncEnabled                               = $OnPremisesSyncEnabled;
            OnPremisesUserPrincipalName                           = $OnPremisesUserPrincipalName;
            OnPremisesExtensionAttributes_ExtensionAttribute1  = $OnPremisesExtensionAttributes_ExtensionAttribute1;
            OnPremisesExtensionAttributes_ExtensionAttribute2  = $OnPremisesExtensionAttributes_ExtensionAttribute2;
            OnPremisesExtensionAttributes_ExtensionAttribute3  = $OnPremisesExtensionAttributes_ExtensionAttribute3;
            OnPremisesExtensionAttributes_ExtensionAttribute4  = $OnPremisesExtensionAttributes_ExtensionAttribute4;
            OnPremisesExtensionAttributes_ExtensionAttribute5  = $OnPremisesExtensionAttributes_ExtensionAttribute5;
            OnPremisesExtensionAttributes_ExtensionAttribute6  = $OnPremisesExtensionAttributes_ExtensionAttribute6;
            OnPremisesExtensionAttributes_ExtensionAttribute7  = $OnPremisesExtensionAttributes_ExtensionAttribute7;
            OnPremisesExtensionAttributes_ExtensionAttribute8  = $OnPremisesExtensionAttributes_ExtensionAttribute8;
            OnPremisesExtensionAttributes_ExtensionAttribute9  = $OnPremisesExtensionAttributes_ExtensionAttribute9;
            OnPremisesExtensionAttributes_ExtensionAttribute10 = $OnPremisesExtensionAttributes_ExtensionAttribute10;
            OnPremisesExtensionAttributes_ExtensionAttribute11 = $OnPremisesExtensionAttributes_ExtensionAttribute11;
            OnPremisesExtensionAttributes_ExtensionAttribute12 = $OnPremisesExtensionAttributes_ExtensionAttribute12;
            OnPremisesExtensionAttributes_ExtensionAttribute13 = $OnPremisesExtensionAttributes_ExtensionAttribute13;
            OnPremisesExtensionAttributes_ExtensionAttribute14 = $OnPremisesExtensionAttributes_ExtensionAttribute14;
            OnPremisesExtensionAttributes_ExtensionAttribute15 = $OnPremisesExtensionAttributes_ExtensionAttribute15;
            CreatedDateTime                                       = $CreatedDateTime;
            MailNickname                                       = $MailNickname;
            UserType                                           = $UserType;
            Licenses                                           = $Licenses;
            FoundRecipient                                       = $FoundRecipientStatus;
            PrimarySmtpAddress                                   = $PrimarySmtpAddress;
            RecipientTypeDetails                               = $RecipientTypeDetails;
            IsDirSynced                                           = $IsDirSynced;
            IsMailboxEnabled                                   = $IsMailboxEnabled;
            WhenMailboxCreated                                   = $WhenMailboxCreated;
            WhenSoftDeleted                                       = $WhenSoftDeleted;
            WhenCreated                                           = $WhenCreated;
            FoundMailboxStatistics                               = $FoundMailboxStatisticsStatus;
            DeletedItemCount                                   = $DeletedItemCount;
            ItemCount                                           = $ItemCount;
            TotalDeletedItemSize                               = $TotalDeletedItemSize;
            TotalItemSize                                       = $TotalItemSize;
            MailboxPermissionUsers                               = $MailboxPermissionUsers;
            MailboxPermissionAccessRights                       = $MailboxPermissionAccessRights;
            RecipientPermissionTrustees                           = $RecipientPermissionTrustees;
            RecipientPermissionAccessRights                       = $RecipientPermissionAccessRights;
        })
    Return $MgRecipientUser
}
Function Get-MgBetaRecipientUser
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$UPN
    )
    $MgRecipientUser = @()
    #Found License Name
    Try
    {
        $LocalPath = ".\MapSKUID.csv"
        If (!(Test-Path $LocalPath))
        {
            Write-Log warning -Message "The script Download Microsoft Licensing CSV File"
            $URL = "https://download.microsoft.com/download/e/3/e/e3e9faf2-f28b-490a-9ada-c6089a1fc5b0/Product%20names%20and%20service%20plan%20identifiers%20for%20licensing.csv"
            $LocalPath = ".\MapSKUID.csv"
            Invoke-WebRequest -Uri $URL -OutFile $LocalPath
            
        }
        Else
        {
            Write-Log warning -Message "The folder $LocalPath is already exist"
        }
        $MicrosoftSKUs = Import-Csv $LocalPath
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to download $LocalPath"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
    }
    # MgUser
    $FoundMgUserStatus = "No"
    
    Try
    {
        
        Write-log Warning -Message "The Script is searching for the MgUser: $UPN"
        $User = Get-MgBetaUser -UserId $UPN
        $UserIdentity = $User.ID
        $UserData = Get-MgBetaUser -UserId $UserIdentity -Property SignInSessionsValidFromDateTime, RefreshTokensValidFromDateTime,CreatedDateTime, OnPremisesDistinguishedName, OnPremisesImmutableId, OnPremisesLastSyncDateTime, OnPremisesSamAccountName, OnPremisesSyncEnabled, OnPremisesUserPrincipalName, SignInActivity, MailNickname, UserType, AssignedLicenses, DisplayName, UserPrincipalName, JobTitle, Department, AccountEnabled, Mail, LastPasswordChangeDateTime, OnPremisesExtensionAttributes
        Write-Log Info -Message "The script find the MgUser $UPN (DN: $UserIdentity)"
        $FoundMgUserStatus = "Yes"
        If ($UserData.signinActivity.LastNonInteractiveSignInDateTime.DateTime)
        {
            $LastNonInteractiveSignInDateTime = Get-Date ($UserData.signinActivity.LastNonInteractiveSignInDateTime.DateTime) -Format "G"
            $LastNonInteractiveSignInDateTime = [datetime]::Parse($LastNonInteractiveSignInDateTime)
        }
        If ($UserData.SignInActivity.LastSignInDateTime.DateTime)
        {
            $LastSignInDateTime = Get-Date ($UserData.SignInActivity.LastSignInDateTime.DateTime) -Format "G"
            $LastSignInDateTime = [datetime]::Parse($LastSignInDateTime)
        }
        If ($UserData.SignInActivity.LastSuccessfulSignInDateTime.DateTime)
        {
            $LastSuccessfulSignInDateTime = Get-Date ($UserData.SignInActivity.LastSuccessfulSignInDateTime.DateTime) -Format "G"
            $LastSuccessfulSignInDateTime = [datetime]::Parse($LastSuccessfulSignInDateTime)
        }
        If ($UserData.SignInSessionsValidFromDateTime.DateTime)
        {
            $SignInSessionsValidFromDateTime = Get-Date ($UserData.SignInSessionsValidFromDateTime.DateTime) -Format "G"
            $SignInSessionsValidFromDateTime = [datetime]::Parse($SignInSessionsValidFromDateTime)
        }
        If ($UserData.RefreshTokensValidFromDateTime.DateTime)
        {
            $RefreshTokensValidFromDateTime = Get-Date ($UserData.RefreshTokensValidFromDateTime.DateTime) -Format "G"
            $RefreshTokensValidFromDateTime = [datetime]::Parse($RefreshTokensValidFromDateTime)
        }
        
        $OnPremisesDistinguishedName = $UserData.OnPremisesDistinguishedName
        $OnPremisesImmutableId = $UserData.OnPremisesImmutableId
        $OnPremisesLastSyncDateTime = $UserData.OnPremisesLastSyncDateTime
        $OnPremisesSamAccountName = $UserData.OnPremisesSamAccountName
        $OnPremisesSyncEnabled = $UserData.OnPremisesSyncEnabled
        $OnPremisesUserPrincipalName = $UserData.OnPremisesUserPrincipalName
        $MailNickname = $UserData.MailNickname
        $DisplayName = $UserData.DisplayName
        $UserPrincipalName = $UserData.UserPrincipalName
        $Department = $UserData.Department
        $Tittle = $UserData.JobTitle
        $AccountEnabled = $UserData.AccountEnabled
        $Mail = $UserData.Mail
        $LastPasswordChangeDateTime = $UserData.LastPasswordChangeDateTime
        $UserType = $UserData.UserType
        $AssignedLicenses = $UserData.AssignedLicenses
        $OnPremisesExtensionAttributes_ExtensionAttribute1 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute1
        $OnPremisesExtensionAttributes_ExtensionAttribute2 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute2
        $OnPremisesExtensionAttributes_ExtensionAttribute3 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute3
        $OnPremisesExtensionAttributes_ExtensionAttribute4 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute4
        $OnPremisesExtensionAttributes_ExtensionAttribute5 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute5
        $OnPremisesExtensionAttributes_ExtensionAttribute6 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute6
        $OnPremisesExtensionAttributes_ExtensionAttribute7 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute7
        $OnPremisesExtensionAttributes_ExtensionAttribute8 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute8
        $OnPremisesExtensionAttributes_ExtensionAttribute9 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute9
        $OnPremisesExtensionAttributes_ExtensionAttribute10 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute10
        $OnPremisesExtensionAttributes_ExtensionAttribute11 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute11
        $OnPremisesExtensionAttributes_ExtensionAttribute12 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute12
        $OnPremisesExtensionAttributes_ExtensionAttribute13 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute13
        $OnPremisesExtensionAttributes_ExtensionAttribute14 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute14
        $OnPremisesExtensionAttributes_ExtensionAttribute15 = $UserData.OnPremisesExtensionAttributes.ExtensionAttribute15
        $CreatedDateTime = $UserData.CreatedDateTime
        
        $UserLicenses = @()
        foreach ($AssignedLicense in $AssignedLicenses)
        {
            $SkuId = $Null
            $SkuId = $AssignedLicense.SkuId
            $UserLicenses += ($MicrosoftSKUs | where { $_.GUID -eq $SkuId } | Select -first 1).Product_Display_Name
        }
        $Licenses = $UserLicenses -join ";"
        
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to find MgUser $UPN"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
        $FoundMgUserStatus = "Failed with Error:$ErrorMessage"
    }
    # Recipient
    $FoundRecipientStatus = "No"
    Try
    {
        
        Write-log Warning -Message "The Script is searching for the Recipient: $UPN"
        $Recipient = $Recipient = Get-Recipient $UPN
        Write-Log Info -Message "The script find the recipient $UPN (DN: $UserIdentity)"
        $FoundRecipientStatus = "Yes"
        $PrimarySmtpAddress = $Recipient.PrimarySmtpAddress
        $RecipientTypeDetails = $Recipient.RecipientTypeDetails
        $IsDirSynced = $Recipient.IsDirSynced
        $WhenMailboxCreated = $Recipient.WhenMailboxCreated
        $WhenSoftDeleted = $Recipient.WhenSoftDeleted
        $WhenCreated = $Recipient.WhenCreated
        $DeletedItemCount = "Not a Mailbox"
        $ItemCount = "Not a Mailbox"
        $TotalDeletedItemSize = "Not a Mailbox"
        $TotalItemSize = "Not a Mailbox"
        $FoundMailboxStatisticsStatus = "Not a Mailbox"
        $IsMailboxEnabled = "Not a Mailbox"
        If ($RecipientTypeDetails -like "*Mailbox")
        {
            
            #Mailbox Data
            $IsMailboxEnabled = "No Data Found"
            Try
            {
                Write-Log warning -Message "The script retreive Mailbox Data for $PrimarySmtpAddress"
                $MailboxData = $Null
                $MailboxData = Get-Mailbox $PrimarySmtpAddress
                $IsMailboxEnabled = $MailboxData.IsMailboxEnabled
                Write-Log Info -Message "The script retreived Mailbox Data for $PrimarySmtpAddress"
                $FoundMailboxDataStatus = "Yes"
            }
            Catch
            {
                $ErrorMessage = $Error[0].Exception.Message
                $CMDLet = $Error[0].InvocationInfo.Line
                $FailedItem = $Error[0].Exception.ItemName
                Write-Log Error -Message "Failed to retreive Mailbox Data for $PrimarySmtpAddress"
                Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                Write-Log Error -Message "Failed with Error:$ErrorMessage"
                $FoundMailboxDataStatus = "Failed with Error:$ErrorMessage"
                
                
            }
            #MailboxStatistics
            $DeletedItemCount = "No Data Found"
            $ItemCount = "No Data Found"
            $TotalDeletedItemSize = "No Data Found"
            $TotalItemSize = "No Data Found"
            Try
            {
                Write-Log warning -Message "The script search Mailbox Statistics for $PrimarySmtpAddress"
                $MailboxStatistics = Get-EXOMailboxStatistics $PrimarySmtpAddress
                $DeletedItemCount = $MailboxStatistics.DeletedItemCount
                $ItemCount = $MailboxStatistics.ItemCount
                $TotalDeletedItemSize = $MailboxStatistics.TotalDeletedItemSize
                $TotalItemSize = $MailboxStatistics.TotalItemSize
                Write-Log Info -Message "The script found Mailbox Statistics info for $PrimarySmtpAddress"
                $FoundMailboxStatisticsStatus = "Yes"
            }
            Catch
            {
                $ErrorMessage = $Error[0].Exception.Message
                $CMDLet = $Error[0].InvocationInfo.Line
                $FailedItem = $Error[0].Exception.ItemName
                Write-Log Error -Message "Failed to Retreive MailboxStatistics for $PrimarySmtpAddress"
                Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                Write-Log Error -Message "Failed with Error:$ErrorMessage"
                $FoundMailboxStatisticsStatus = "Failed with Error:$ErrorMessage"
                $DeletedItemCount = "Failed"
                $ItemCount = "Failed"
                $TotalDeletedItemSize = "Failed"
                $TotalItemSize = "Failed"
                
            }
            
            #Mailbox Permissions
            $MailboxPermissionUsers = "No Data Found"
            $MailboxPermissionAccessRights = "No Data Found"
            $RecipientPermissionTrustees = "No Data Found"
            $RecipientPermissionAccessRights = "No Data Found"
            
            Try
            {
                Write-Log warning -Message "The script search Mailbox Permissions for $PrimarySmtpAddress"
                $EXORecipientPermissions = Get-EXORecipientPermission $PrimarySmtpAddress
                $EXOMailboxPermissions = Get-EXOMailboxPermission $PrimarySmtpAddress
                $MailboxPermissionUsers = $EXOMailboxPermissions.User -join ";"
                $MailboxPermissionAccessRights = $EXOMailboxPermissions.AccessRights -join ";"
                $RecipientPermissionTrustees = $EXORecipientPermissions.Trustee -join ";"
                $RecipientPermissionAccessRights = $EXORecipientPermissions.AccessRights -join ";"
                Write-Log Info -Message "The script found Mailbox Permissions info for $PrimarySmtpAddress"
                $FoundMailboxStatisticsStatus = "Yes"
            }
            Catch
            {
                $ErrorMessage = $Error[0].Exception.Message
                $CMDLet = $Error[0].InvocationInfo.Line
                $FailedItem = $Error[0].Exception.ItemName
                Write-Log Error -Message "Failed to Retreive MailboxStatistics for $PrimarySmtpAddress"
                Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
                Write-Log Error -Message "Failed with Error:$ErrorMessage"
                $FoundMailboxStatisticsStatus = "Failed with Error:$ErrorMessage"
                $MailboxPermissionUsers = "Failed"
                $MailboxPermissionAccessRights = "Failed"
                $RecipientPermissionTrustees = "Failed"
                $RecipientPermissionAccessRights = "Failed"
            }
            
        }
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to find MgUser $UPN"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
        $FoundRecipientStatus = "Failed with Error:$ErrorMessage"
    }
    
    $MgRecipientUser += New-object PSobject -Property ([Ordered] @{
            UPN                                                   = $UPN;
            Identity                                           = $UserIdentity;
            FoundMgUser                                           = $FoundMgUserStatus;
            DisplayName                                           = $DisplayName;
            Tittle                                               = $Tittle;
            Department                                           = $Department;
            AccountEnabled                                       = $AccountEnabled;
            Mail                                               = $Mail;
            UserPrincipalName                                   = $UserPrincipalName;
            LastSuccessfulSignInDateTime                       = $LastSuccessfulSignInDateTime;
            LastNonInteractiveSignInDateTime                   = $LastNonInteractiveSignInDateTime;
            LastSignInDateTime                                   = $LastSignInDateTime;
            SignInSessionsValidFromDateTime                       = $SignInSessionsValidFromDateTime;
            RefreshTokensValidFromDateTime                       = $RefreshTokensValidFromDateTime;
            LastPasswordChangeDateTime                           = $LastPasswordChangeDateTime;
            OnPremisesDistinguishedName                           = $OnPremisesDistinguishedName;
            OnPremisesImmutableId                               = $OnPremisesImmutableId;
            OnPremisesLastSyncDateTime                           = $OnPremisesLastSyncDateTime;
            OnPremisesSamAccountName                           = $OnPremisesSamAccountName;
            OnPremisesSyncEnabled                               = $OnPremisesSyncEnabled;
            OnPremisesUserPrincipalName                           = $OnPremisesUserPrincipalName;
            OnPremisesExtensionAttributes_ExtensionAttribute1  = $OnPremisesExtensionAttributes_ExtensionAttribute1;
            OnPremisesExtensionAttributes_ExtensionAttribute2  = $OnPremisesExtensionAttributes_ExtensionAttribute2;
            OnPremisesExtensionAttributes_ExtensionAttribute3  = $OnPremisesExtensionAttributes_ExtensionAttribute3;
            OnPremisesExtensionAttributes_ExtensionAttribute4  = $OnPremisesExtensionAttributes_ExtensionAttribute4;
            OnPremisesExtensionAttributes_ExtensionAttribute5  = $OnPremisesExtensionAttributes_ExtensionAttribute5;
            OnPremisesExtensionAttributes_ExtensionAttribute6  = $OnPremisesExtensionAttributes_ExtensionAttribute6;
            OnPremisesExtensionAttributes_ExtensionAttribute7  = $OnPremisesExtensionAttributes_ExtensionAttribute7;
            OnPremisesExtensionAttributes_ExtensionAttribute8  = $OnPremisesExtensionAttributes_ExtensionAttribute8;
            OnPremisesExtensionAttributes_ExtensionAttribute9  = $OnPremisesExtensionAttributes_ExtensionAttribute9;
            OnPremisesExtensionAttributes_ExtensionAttribute10 = $OnPremisesExtensionAttributes_ExtensionAttribute10;
            OnPremisesExtensionAttributes_ExtensionAttribute11 = $OnPremisesExtensionAttributes_ExtensionAttribute11;
            OnPremisesExtensionAttributes_ExtensionAttribute12 = $OnPremisesExtensionAttributes_ExtensionAttribute12;
            OnPremisesExtensionAttributes_ExtensionAttribute13 = $OnPremisesExtensionAttributes_ExtensionAttribute13;
            OnPremisesExtensionAttributes_ExtensionAttribute14 = $OnPremisesExtensionAttributes_ExtensionAttribute14;
            OnPremisesExtensionAttributes_ExtensionAttribute15 = $OnPremisesExtensionAttributes_ExtensionAttribute15;
            CreatedDateTime                                       = $CreatedDateTime;
            MailNickname                                       = $MailNickname;
            UserType                                           = $UserType;
            Licenses                                           = $Licenses;
            FoundRecipient                                       = $FoundRecipientStatus;
            PrimarySmtpAddress                                   = $PrimarySmtpAddress;
            RecipientTypeDetails                               = $RecipientTypeDetails;
            IsDirSynced                                           = $IsDirSynced;
            IsMailboxEnabled                                   = $IsMailboxEnabled;
            WhenMailboxCreated                                   = $WhenMailboxCreated;
            WhenSoftDeleted                                       = $WhenSoftDeleted;
            WhenCreated                                           = $WhenCreated;
            FoundMailboxStatistics                               = $FoundMailboxStatisticsStatus;
            DeletedItemCount                                   = $DeletedItemCount;
            ItemCount                                           = $ItemCount;
            TotalDeletedItemSize                               = $TotalDeletedItemSize;
            TotalItemSize                                       = $TotalItemSize;
            MailboxPermissionUsers                               = $MailboxPermissionUsers;
            MailboxPermissionAccessRights                       = $MailboxPermissionAccessRights;
            RecipientPermissionTrustees                           = $RecipientPermissionTrustees;
            RecipientPermissionAccessRights                       = $RecipientPermissionAccessRights;
        })
    Return $MgRecipientUser
}
Function Create-MgAccount
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [String]$UserName,
        [Parameter(Mandatory = $true,
                   Position = 2)]
        [String]$FirstName,
        [Parameter(Mandatory = $true,
                   Position = 3)]
        [String]$LastName,
        [Parameter(Mandatory = $true,
                   Position = 4)]
        [String]$DisplayName,
        [Parameter(Mandatory = $true,
                   Position = 5)]
        [String]$UsageLocation,
        [Parameter(Mandatory = $true,
                   Position = 6)]
        [String]$LicenseGroupName,
        [Parameter(Mandatory = $true,
                   Position = 7)]
        [String]$TempPassword,
        [Parameter(Mandatory = $true,
                   Position = 8)]
        [String]$MailNickName,
        [Parameter(Position = 9)]
        [Switch]$Confirm
    )
    
    If ($Confirm)
    {
        Write-Log Warning -Message "Please make sure you are connected to MgGraph using the following Scopes Domain.ReadWrite.All, Directory.ReadWrite.All, User.ReadWrite.All, Organization.Read.All, Group.ReadWrite.All"
        Read-Host "Are you ready to continue?"
    }

    $PasswordProfile = @{
        Password = $TempPassword
    }
    # Create Users
    Try
    {
        Write-Log warning -Message "The script will try to create the user: $DisplayName ($UserName)"
        $MgUser = $Null
        $MgUser = New-MgUser -DisplayName $DisplayName -GivenName $FirstName -Surname $LastName -PasswordProfile $PasswordProfile -AccountEnabled -MailNickName $MailNickName -UserPrincipalName $UserName -UsageLocation $UsageLocation
        $MgUserID = $Null
        $MgUserID = $MgUser.ID
        Write-Log INFO -Message "The script created the user: $DisplayName ($UserName)"
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to create the user: $DisplayName ($UserName)"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
    }
    
    
    #Find License Group
    Try
    {
        Write-Log warning -Message "The script will try find the group $LicenseGroupName"
        $MgLicenseGroup = Get-MgGroup -Filter "DisplayName eq '$LicenseGroupName'"
        $LicenseGroupNameID = $Null
        $LicenseGroupNameID = $MgLicenseGroup.Id
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to find the group $LicenseGroupName"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
        
    }
    
    #Add User to license Group
    If ($LicenseGroupNameID)
    {
        Try
        {
            Write-Log INFO -Message "The script found $LicenseGroupName"
            Write-Log warning -Message "The script will try to add $DisplayName ($UserPrincipalName - $MgUserID) to $LicenseGroupName"
            New-MgGroupMember -GroupId $LicenseGroupNameID -DirectoryObjectId $MgUserID
            Write-Log INFO -Message "The script added $DisplayName ($UserPrincipalName - $MgUserID) to $LicenseGroupName"
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -Message "Failed to add $DisplayName ($UserPrincipalName - $MgUserID) to $LicenseGroupName"
            Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -Message "Failed with Error:$ErrorMessage"
            
        }
    }
    Else
    {
        Write-Log Error -Message "Failed to find the group $LicenseGroupName"
    }
}
Function Disable-MgAccount
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true,
                   Position = 1)]
        [string]$UPN,
        [Parameter(Position = 2)]
        [switch]$Confirm
    )
    
    # Find User
    Try
    {
        $MgUser = Get-MgUser -UserId $UPN
        $DisplayName = $MgUser.DisplayName
        $UserID = $MgUser.ID
        Write-Host "The script find the user: $DisplayName (UPN:$UPN) with the following ObjectID: $UserID" -ForegroundColor Green
        If (!($Confirm)) { Read-Host "Are you sure you want to Disable the AAD Account & revoke all Azure Tokens of $DisplayName? Press Any Key to continue or CTRL+C to Cancel" }
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        Write-Host "Failed with Error:$ErrorMessage" -ForegroundColor Red
        Write-Host "The script will stop" -ForegroundColor Red
        
    }
    
    # Disable AAD Account
    Try
    {
        Update-MgUser -UserId $UserID -AccountEnabled:$false
        Write-Host "The script disabled AAD Account $UPN" -ForegroundColor green
    }
    Catch
    { $ErrorMessage = $Error[0].Exception.Message; Write-Host "Failed with Error:$ErrorMessage" -ForegroundColor Red }
    
    # Revoke AAD Tokens
    Try
    {
        Revoke-MgUserSignInSession -UserId $UserID
        Write-Host "The script revoke all tokens for $UPN" -ForegroundColor Green
    }
    Catch
    { $ErrorMessage = $Error[0].Exception.Message; Write-Host "Failed with Error:$ErrorMessage" -ForegroundColor Red }
}
Function Check-MgADConnectLastSync
{
    $MgOrganization = Get-MgOrganization | select OnPremisesLastSyncDateTime
    $Time = $MgOrganization.OnPremisesLastSyncDateTime
    $NextTime = $Time.Addminutes(30)
    $ToTimeZoneObj = [system.timezoneinfo]::GetSystemTimeZones() | Where-Object { $_.id -eq "Eastern Standard Time" }
    $TargetZoneTime = [system.timezoneinfo]::ConvertTime($Time, $ToTimeZoneObj)
    $NextTargetZoneTime = [system.timezoneinfo]::ConvertTime($NextTime, $ToTimeZoneObj)
    Write-host "The Last Synchronization was : " -NoNewline; Write-host "$TargetZoneTime" -ForegroundColor Green
    Write-host "The Next Synchronization will be at : " -NoNewline; Write-host "$NextTargetZoneTime" -ForegroundColor Yellow
}
#endregion

#region Licenses
####################################################
##################### Licenses ########################
####################################################
Function Generate-MgLicenseReportPerSKU
{
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    # Generate list of available licenses on the tenant
    $URL = "https://download.microsoft.com/download/e/3/e/e3e9faf2-f28b-490a-9ada-c6089a1fc5b0/Product%20names%20and%20service%20plan%20identifiers%20for%20licensing.csv"
    $LocalPath = ".\MapSKUID_" + $DateFull + ".csv"
    Invoke-WebRequest -Uri $URL -OutFile $LocalPath
    $MicrosoftSKUs = Import-Csv $LocalPath
    
    $TenantSKUs = Get-MgSubscribedSku
    $TenantName = $TenantSKUs.AccountName | select -First 1
    $SKUs = $Null
    $SKUs = @()
    foreach ($TenantSKU in $TenantSKUs)
    {
        $TenantSKU_SkuId = $Null
        $TenantSKU_Name = $Null
        $TenantSKU_ConsumedUnits = $Null
        $TenantSKU_SkuPartNumber = $Null
        $TenantSKU_SkuId = $TenantSKU.SkuId
        $TenantSKU_ConsumedUnits = $TenantSKU.ConsumedUnits
        $TenantSKU_SkuPartNumber = $TenantSKU.SkuPartNumber
        $TenantSKU_Name = ($MicrosoftSKUs | where { $_.GUID -eq $TenantSKU_SkuId } | Select -first 1).Product_Display_Name
        $SKUs += New-object PSobject -Property ([Ordered] @{
                Name          = $TenantSKU_Name;
                ConsumedUnits = $TenantSKU_ConsumedUnits;
                SkuPartNumber = $TenantSKU_SkuPartNumber;
                SkuId          = $TenantSKU_SkuId;
            })
    }
    #Generate for selected SKU
    $SKUs | ft
    $SelectedSKU = $SKUs | Out-GridView -PassThru
    $SelectedSKUGUID = $SelectedSKU.Skuid
    $SelectedSKUName = $SelectedSKU.Name
    $SelectedSkuPartNumber = $SelectedSKU.SkuPartNumber
    Write-Log warning -Message "Selected SKU is: $SelectedSKUName"
    [Array]$MgUsers = Get-MgUser -Filter "assignedLicenses/`$count ne 0 and userType eq 'Member'" -ConsistencyLevel eventual -CountVariable Records -All -Property displayName, userPrincipalName, country, department, assignedlicenses, createdDateTime, jobTitle | Sort-Object DisplayName
    $Users = $Null
    $Users = @()
    Foreach ($MgUser in $MgUsers)
    {
        $displayName = $Null
        $userPrincipalName = $Null
        $country = $Null
        $department = $Null
        $assignedlicenses = $Null
        $createdDateTime = $Null
        $jobTitle = $Null
        $displayName = $MgUser.displayName
        $userPrincipalName = $MgUser.userPrincipalName
        $country = $MgUser.country
        $department = $MgUser.department
        $assignedlicenses = $MgUser.assignedlicenses.Skuid -join ";"
        $createdDateTime = $MgUser.createdDateTime
        $jobTitle = $MgUser.jobTitle
        
        $Users += New-object PSobject -Property ([Ordered] @{
                displayName          = $displayName;
                userPrincipalName = $userPrincipalName;
                country              = $country;
                department          = $department;
                assignedlicenses  = $assignedlicenses;
                createdDateTime   = $createdDateTime;
                jobTitle          = $jobTitle;
            })
        
    }
    $UsersCount = ($Users | Measure).count
    Write-Log warning -Message "The tenant has $UsersCount users"
    $LicensedUsers = $Users | where { $_.AssignedLicenses -like "*$($SelectedSKUGUID)*" } | select displayName, userPrincipalName, country, department, createdDateTime, jobTitle
    $LicensedUsersCount = ($LicensedUsers | Measure).count
    Write-Log warning -Message "The selected SKU $SelectedSKUName has $LicensedUsersCount users"
    
    $ReportFilexlsx = "LicensesReport_" + $TenantName + "_" + $SelectedSkuPartNumber + "_" + $DateFull + ".xlsx"
    $LicensedUsers | Export-Excel $ReportFilexlsx --TableName "AssignedLicenses" -Title "Assigned Licenses" -TitleBold -WorksheetName "AssignedLicenses" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFilexlsx"
    
}

Function Generate-MgLicenseReport
{
    [CmdletBinding()]
    param ()
    
    $URL = "https://download.microsoft.com/download/e/3/e/e3e9faf2-f28b-490a-9ada-c6089a1fc5b0/Product%20names%20and%20service%20plan%20identifiers%20for%20licensing.csv"
    $LocalPath = ".\MapSKUID.csv"
    Invoke-WebRequest -Uri $URL -OutFile $LocalPath
    $SKUs =   $LocalPath
    
    [Array]$Users = Get-MgUser -Filter "assignedLicenses/`$count ne 0 and userType eq 'Member'" -ConsistencyLevel eventual -CountVariable Records -All -Property id, displayName, userPrincipalName, country, department, assignedlicenses, createdDateTime, jobTitle, signInActivity | Sort-Object DisplayName
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    
    
    [Int]$i = 1
    $Table = $Null
    $Table = @()
    $Count = ($Users | Measure).count
    foreach ($User in $Users)
    {
        $DisplayName = $Null
        $DisplayName = $User.DisplayName
        $id = $Null
        $id = $User.id
        $userPrincipalName = $Null
        $userPrincipalName = $User.userPrincipalName
        $AssignedLicenses = $Null
        $AssignedLicenses = $User.assignedlicenses
        $LastSigninDateTime = $Null
        $LastSigninDateTime = $User.signInActivity.LastSigninDateTime
        $LastNonInteractiveSignInDateTime = $Null
        $LastNonInteractiveSignInDateTime = $User.signInActivity.LastNonInteractiveSignInDateTime
        $jobTitle = $Null
        $jobTitle = $User.jobTitle
        $department = $Null
        $department = $User.department
        $SKU_NameData = $Null
        $SKU_NameData = @()
        write-log warning -message "Analyzing $DisplayName ($UserprincipalName) --- $i/$Count"
        Foreach ($AssignedLicense in $AssignedLicenses)
        {
            $AssignedLicense_SKUID = $AssignedLicense.Skuid
            $SKU_NameData += ($Skus | where { $_.GUID -eq $AssignedLicense_SKUID } | Select -first 1).Product_Display_Name
        }
        $SKU_Names = $SKU_NameData -join ";"
        $Table += New-object PSobject -Property ([Ordered] @{
                DisplayName                         = $DisplayName;
                userPrincipalName                 = $userPrincipalName;
                id                                 = $id;
                JobTitle                         = $jobTitle;
                Department                         = $department;
                SKU_Names                         = $SKU_Names;
                LastSigninDateTime                 = $LastSigninDateTime;
                LastNonInteractiveSignInDateTime = $LastNonInteractiveSignInDateTime;
            })
        
        $i++
    }
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ReportFilexlsx = ".\Report_LicensedUsers_" + $DateFull + ".xlsx"
    $Table | Export-Excel $ReportFilexlsx --TableName "LicensedUsers" -Title "Licensed Users" -TitleBold -WorksheetName "LicensedUsers" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFilexlsx"
    
}
#endregion

#region App
####################################################
###################### Apps #########################
####################################################
Function Generate-MgReportOauthAuditReportToExcel
{
    [CmdletBinding()]
    param ()
    $MissingModules = $null
    $MissingModules = @()
    If (!(Get-InstalledModule -Name "MSIdentityTools" -ErrorAction SilentlyContinue)) { Write-Log Error -Message "MS Identity Tools Powershell module is not installed. The script will try to install the module"; $MissingModules += "Missing Powershell Module MSIdentityTools" }
    If (!(Get-InstalledModule -Name "ImportExcel" -ErrorAction SilentlyContinue)) { Write-Log Error -Message "ImportExcel Powershell module is not installed. The script will try to install the module"; $MissingModules += "Missing Powershell Module ImportExcel" }
    
    If ($MissingModules.count -eq 0)
    {
        Write-Log Info -Message "MSIdentityTools & ImportExcel modules are installed"
        
        Try
        {
            Write-Log warning -Message "Script will prompt to connect to your tenant using MSGraph with Application.Read.all Scope"
            Connect-MgGraph -Scopes Directory.Read.All -NoWelcome
            Write-Log Info -Message "Script connected to your tenant using MSGraph"
            $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
            $ReportFile = "ReportAppConsentGrant_" + $DateFull + ".xlsx"
            Export-MsIdAppConsentGrantReport -ReportOutputType Excelworkbook -ExcelWorkbookPath $ReportFile
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -Message "Failed to "
            Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -Message "Failed with Error:$ErrorMessage"
            $Status = "Failed"
        }
        
        
    }
    Else
    {
        If (!(Get-InstalledModule -Name "MSIdentityTools" -ErrorAction SilentlyContinue))
        {
            Write-Log Error -Message "MS Identity Tools Powershell module will be installed"
            Install-Module -Name MSIdentityTools -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Log info -Message "MSIdentityTools Powershell module is installed"
        }
        If (!(Get-InstalledModule -Name "ImportExcel" -ErrorAction SilentlyContinue))
        {
            Write-Log Error -Message "ImportExcel Powershell module will be installed"
            Install-Module -Name ImportExcel -SkipPublisherCheck -Scope CurrentUser -Force -AllowClobber -Confirm:$False; Write-Log info -Message "ImportExcel Powershell module is installed"
        }
        Generate-ReportOauthAuditReportToExcel
    }
    
    
}
Function Generate-MgEnterpriseAppsAssignmentsConsentsSettingsReport
{
    [CmdletBinding()]
    param ()
    
    # Get All Enterprise Applications & App Registration
    $Applications = Get-MgServicePrincipal -All
    
    #Initiate the Hash Table
    [Int]$i = 1
    $Table = $Null
    $Table = @()
    $Count = ($Applications | Measure).count
    
    ForEach ($Application in $Applications)
    {
        # Name,AppID,VisibleToUser, AssignedRequired
        $AccountEnabled = $Application.AccountEnabled
        $DisplayName = $Application.DisplayName
        $AppDescription = $Application.AppDescription
        $Description = $Application.Description
        $Notes = $Application.Notes
        $AppId = $Application.Id
        $AppRoleAssignmentRequired = $Application.AppRoleAssignmentRequired
        $LoginUrl = $Application.LoginUrl
        $ResourceSpecificApplicationPermissions = $Application.ResourceSpecificApplicationPermissions
        $ServicePrincipalType = $Application.ServicePrincipalType
        $SignInAudience = $Application.SignInAudience
        $CreatedDate = $Application.AdditionalProperties.createdDateTime
        
        Write-log Warning -message "The script is analyzing $DisplayName ….. --- $i/$Count"
        #Assigments (Users,Groups,SPs) to ServicePrincipals
        $Assignments = Get-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $AppId -All
        $AssignedUsers = $Null
        $AssignedUsers = @()
        $AssignedGroups = $Null
        $AssignedGroups = @()
        $AssignedServicePrincipals = $Null
        $AssignedServicePrincipals = @()
        $AssignedOthers = $Null
        $AssignedOthers = @()
        foreach ($Assignment in $Assignments)
        {
            $PrincipalType = $Null
            $PrincipalType = $Assignment.PrincipalType
            $PrincipalDisplayName = $Null
            $PrincipalDisplayName = $Assignment.PrincipalDisplayName
            
            switch ($PrincipalType)
            {
                User
                {
                    $AssignedUsers += New-object PSobject -Property ([Ordered] @{
                            DisplayName = $PrincipalDisplayName;
                        })
                }
                Group
                {
                    $AssignedGroups += New-object PSobject -Property ([Ordered] @{
                            DisplayName = $PrincipalDisplayName;
                        })
                }
                ServicePrincipal
                {
                    $AssignedServicePrincipals += New-object PSobject -Property ([Ordered] @{
                            DisplayName = $PrincipalDisplayName;
                        })
                }
                Default
                {
                    $AssignedOthers += New-object PSobject -Property ([Ordered] @{
                            DisplayName = $PrincipalDisplayName;
                        })
                }
            }
        }
        $ListAssignedUsers = $AssignedUsers.DisplayName -join ";"
        $ListAssignedGroups = $AssignedGroups.DisplayName -join ";"
        $ListAssignedServicePrincipals = $AssignedServicePrincipals.DisplayName -join ";"
        $ListAssignedOthers = $AssignedOthers.DisplayName -join ";"
        
        # Permissions (Delegate)
        $Oauth2Permissions = $Null
        $Oauth2Permissions = Get-MgServicePrincipalOauth2PermissionGrant -ServicePrincipalId $AppId -All
        if ($Oauth2Permissions)
        {
            foreach ($Oauth2Permission in $Oauth2Permissions)
            {
                $ConsentType = $Null
                $ConsentType = $Oauth2Permission.ConsentType
                If ($ConsentType -eq "AllPrincipals")
                {
                    $AdminConsentScopes = $null
                    $AdminConsentScopes = $Oauth2Permission.Scope
                }
                If ($ConsentType -eq "Principal")
                {
                    $UserConsentScopes = $null
                    $UserConsentScopes = $Oauth2Permission.Scope
                }
            }
            
        }
        
        $Table += New-object PSobject -Property ([Ordered] @{
                DisplayName                  = $DisplayName;
                Description                  = $Description;
                Notes                      = $Notes;
                ServicePrincipalType      = $ServicePrincipalType;
                Id                          = $AppId;
                AppRoleAssignmentRequired = $AppRoleAssignmentRequired;
                AccountEnabled              = $AccountEnabled;
                SignInAudience              = $SignInAudience;
                CreatedDate                  = $CreatedDate;
                AssignedUsers              = $ListAssignedUsers;
                AssignedGroups              = $ListAssignedGroups;
                AssignedServicePrincipals = $ListAssignedServicePrincipals;
                AssignedOthers              = $ListAssignedOthers;
                AdminConsent              = $AdminConsentScopes;
                UserConsent                  = $UserConsentScopes;
            })
        
        $i++
        
    }
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ReportFilexlsx = ".\Report_EnterpriseApplicationsUsage_" + $DateFull + ".xlsx"
    $Table | Export-Excel $ReportFilexlsx -TableName "" -Title "" -TitleBold -WorksheetName "" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFilexlsx"
}
Function Generate-MgEnterpriseAppsCertificatesSecretsReport
{
    
    [CmdletBinding()]
    param ()
    
    # Connect to Graph
    
    Try
    {
        Write-Log Info -Message "The script is trying to connect to Graph with the following scope Application.ReadWrite.All"
        Connect-MgGraph -Scopes 'Application.ReadWrite.All'
        Write-Log warning -Message "The script connected to Graph with the following scope Application.ReadWrite.All"
        $StatusMgConnection = "Success"
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to Connect to MgGraph"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
        $StatusMgConnection = "Failed"
    }
    
    # Retreive Service Principals
    Try
    {
        Write-Log Info -Message "The script is trying to retreive all Service Principals on the tenant"
        $ServicePrincipals = Get-MgServicePrincipal -all
        Write-Log Info -Message "The script retreived all Service Principals on the tenant"
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to retreive all Service Principals on the tenant"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
        Exit
    }
    
    # Retreive App Registrations
    
    Try
    {
        Write-Log Info -Message "The script is trying to retreive all App Registrations on the tenant"
        $AppRegistrations = Get-MgApplication -all
        Write-Log Info -Message "The script retreived all App Registrations on the tenant"
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to retreive all App Registrations on the tenant"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
    }
    
    #Initiate the Hash Table
    [Int]$i = 1
    $SPTable = $Null
    $SPTable = @()
    $SPCount = ($ServicePrincipals | Measure).count
    [Int]$ii = 1
    $ARTable = $Null
    $ARTable = @()
    $ARCount = ($AppRegistrations | Measure).count
    $Now = Get-Date
    ForEach ($ServicePrincipal in $ServicePrincipals)
    {
        $ServicePrincipal_Name = $ServicePrincipal.DisplayName
        $ServicePrincipal_ID = $ServicePrincipal.Id
        $ServicePrincipal_AppID = $ServicePrincipal.AppId
        Write-log Warning -message "The script is analyzing $ServicePrincipal_Name ($ServicePrincipal_ID) ….. --- $i/$SPCount"
        #Owners
        Try
        {
            Write-Log Info -Message "The script is trying to retreive Service Principal owners for $ServicePrincipal_Name ($ServicePrincipal_ID)"
            $Owners = $Null
            $Owners = Get-MgServicePrincipalOwner -ServicePrincipalId $ServicePrincipal_ID
            $Usernames = $Null
            $Usernames = $Owners.AdditionalProperties.userPrincipalName -join ';'
            $OwnerIDs = $Null
            $OwnerIDs = $Owners.Id -join ';'
            Write-Log Info -Message "The script retreived Service Principal owners"
        }
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -Message "Failed to retreive Service Principal owners of $ServicePrincipal_Name ($ServicePrincipal_ID)"
            Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -Message "Failed with Error:$ErrorMessage"
            $Usernames = $Null
            $OwnerIDs = $Null
        }
        
        
        
        # Retreive Secrets and Certificates
        
        Try
        {
            
            Write-Log Info -Message "The script is trying to retreive Service Principal Secrets and certificates for $ServicePrincipal_Name ($ServicePrincipal_ID )"
            $AppCreds = $Null
            $AppCreds = Get-MgServicePrincipal -ServicePrincipalId $ServicePrincipal_ID | Select-Object PasswordCredentials, KeyCredentials
            Write-Log Info -Message "The script retreived Service Principals Secrets and certificates"
            $Secrets = $Null
            $Secrets = $AppCreds.PasswordCredentials
            $Certs = $Null
            $Certs = $AppCreds.KeyCredentials
        }
        
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -Message "Failed to retreive all Service Principals Secrets and certificates"
            Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -Message "Failed with Error:$ErrorMessage"
            $Secrets = $Null
            $Certs = $Null
        }
        
        
        
        # Secrets
        
        foreach ($Secret in $Secrets)
        {
            
            $Secret_StartDate = $Null
            $Secret_EndDate = $Null
            $Secret_SecretName = $Null
            $Secret_StartDate = $Secret.StartDateTime
            $Secret_EndDate = $Secret.EndDateTime
            $Secret_SecretName = $Secret.DisplayName
            $SPTable += New-object PSobject -Property ([Ordered] @{
                    'ApplicationName'   = $ServicePrincipal_Name;
                    'Object ID'            = $ServicePrincipal_ID;
                    'ApplicationID'        = $ServicePrincipal_AppID;
                    'Secret Name'        = $Secret_SecretName;
                    'Secret Start Date' = $Secret_StartDate;
                    'Secret End Date'   = $Secret_EndDate;
                    'Owners'            = $Usernames;
                    'Owner_ObjectIDs'   = $OwnerIDs;
                })
            
        }
        
        
        
        # Certificates
        
        foreach ($Cert in $Certs)
        {
            
            $Cert_StartDate = $Null
            $Cert_EndDate = $Null
            $Cert_CertName = $Null
            $Cert_StartDate = $Cert.StartDateTime
            $Cert_EndDate = $Cert.EndDateTime
            $Cert_CertName = $Cert.DisplayName
            
            
            
            $SPTable += New-object PSobject -Property ([Ordered] @{
                    'ApplicationName'         = $ServicePrincipal_Name;
                    'Object ID'                 = $ServicePrincipal_ID;
                    'ApplicationID'             = $ServicePrincipal_AppID;
                    'Certificate Name'         = $Cert_CertName;
                    'Certificate Start Date' = $Cert_StartDate;
                    'Certificate End Date'   = $Cert_EndDate;
                    'Owners'                 = $Usernames;
                    'Owner_ObjectIDs'         = $OwnerIDs;
                })
        }
        $i++
    }
    
    ForEach ($AppRegistration in $AppRegistrations)
    {
        $AppRegistration_Name = $AppRegistration.DisplayName
        $AppRegistration_ID = $AppRegistration.Id
        $AppRegistration_AppID = $AppRegistration.AppId
        Write-log Warning -message "The script is analyzing $AppRegistration_Name ($AppRegistration_ID) ….. --- $i/$ARCount"
        #Owners
        Try
        {
            Write-Log Info -Message "The script is trying to retreive App Registrations owners for $AppRegistration_Name ($AppRegistration_ID)"
            $Owners = $Null
            $Owners = Get-MgApplicationOwner -ApplicationId $AppRegistration_ID
            $Usernames = $Null
            $Usernames = $Owners.AdditionalProperties.userPrincipalName -join ';'
            $OwnerIDs = $Null
            $OwnerIDs = $Owners.Id -join ';'
            Write-Log Info -Message "The script retreived App Registrations owners"
        }
        
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -Message "Failed to retreive App Registrations owners of $AppRegistration_Name ($AppRegistration_ID)"
            Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -Message "Failed with Error:$ErrorMessage"
            $Usernames = $Null
            $OwnerIDs = $Null
        }
        
        # Retreive Secrets and Certificates
        Try
        {
            Write-Log Info -Message "The script is trying to retreive App Registration Secrets and certificates for $AppRegistration_Name ($AppRegistration_ID )"
            $AppCreds = $Null
            $AppCreds = Get-MgApplication -ApplicationId $AppRegistration_ID | Select-Object PasswordCredentials, KeyCredentials
            Write-Log Info -Message "The script retreived App Registration Secrets and certificates"
            $Secrets = $Null
            $Secrets = $AppCreds.PasswordCredentials
            $Certs = $Null
            $Certs = $AppCreds.KeyCredentials
        }
        
        Catch
        {
            $ErrorMessage = $Error[0].Exception.Message
            $CMDLet = $Error[0].InvocationInfo.Line
            $FailedItem = $Error[0].Exception.ItemName
            Write-Log Error -Message "Failed to retreive all App Registration Secrets and certificates"
            Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
            Write-Log Error -Message "Failed with Error:$ErrorMessage"
            $Secrets = $Null
            $Certs = $Null
            
        }
        
        
        
        # Secrets
        
        foreach ($Secret in $Secrets)
        {
            $Secret_StartDate = $Null
            $Secret_EndDate = $Null
            $Secret_SecretName = $Null
            $Secret_StartDate = $Secret.StartDateTime
            $Secret_EndDate = $Secret.EndDateTime
            $Secret_SecretName = $Secret.DisplayName
            
            $ARTable += New-object PSobject -Property ([Ordered] @{
                    'ApplicationName'   = $AppRegistration_Name;
                    'Object ID'            = $AppRegistration_ID;
                    'ApplicationID'        = $AppRegistration_AppID;
                    'Secret Name'        = $Secret_SecretName;
                    'Secret Start Date' = $Secret_StartDate;
                    'Secret End Date'   = $Secret_EndDate;
                    'Owners'            = $Usernames;
                    'Owner_ObjectIDs'   = $OwnerIDs;
                })
        }
        
        # Certificates
        foreach ($Cert in $Certs)
        {
            $Cert_StartDate = $Null
            $Cert_EndDate = $Null
            $Cert_CertName = $Null
            $Cert_StartDate = $Cert.StartDateTime
            $Cert_EndDate = $Cert.EndDateTime
            $Cert_CertName = $Cert.DisplayName
            $SPTable += New-object PSobject -Property ([Ordered] @{
                    'ApplicationName'         = $AppRegistration_Name;
                    'Object ID'                 = $AppRegistration_ID;
                    'ApplicationID'             = $AppRegistration_AppID;
                    'Certificate Name'         = $Cert_CertName;
                    'Certificate Start Date' = $Cert_StartDate;
                    'Certificate End Date'   = $Cert_EndDate;
                    'Owners'                 = $Usernames;
                    'Owner_ObjectIDs'         = $OwnerIDs;
                })
        }
        $ii++
    }
        
        $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
        $ReportFilexlsx = ".\Report_ServicePrincipals_AppRegistrations_" + $DateFull + ".xlsx"
        $SPTable | Export-Excel $ReportFilexlsx -TableName "ServicePrincipals" -Title "Service Principals" -TitleBold -WorksheetName "ServicePrincipals" -TableStyle Medium9 -AutoSize -AutoFilter
        $ARTable | Export-Excel $ReportFilexlsx -TableName "AppRegistrations" -Title "App Registrations" -TitleBold -WorksheetName "AppRegistrations" -TableStyle Medium9 -AutoSize -AutoFilter -Append
        Write-log INFO -Message "Generate the following Report: $ReportFilexlsx"
}

Function Remove-MgLegacyServicePrincipal
{
    [CmdletBinding()]
    param
    (
        [String]$ID,
        [String]$Name
    )
    If ($Name)
    {
        $Filter = "DisplayName eq '" + $Name + "'"
        $ServicePrincipal = Get-MgServicePrincipal -Filter $Filter
        
    }
    Else
    {
        $ServicePrincipal = Get-MgServicePrincipal -ServicePrincipalId
    }
    
    $ServicePrincipal | ft
    $Validation = Read-Host "Are you sure you want Remove this Service Principal (Service Principal will be deleted without restore options)? Y <Yes> , N <No>"
    
    If ($Validation -eq "Y")
    {
        $servicePrincipalId = $ServicePrincipal.ID
        Remove-MgServicePrincipal -ServicePrincipalId $servicePrincipalId
    }
    Else
    {
        Write-Host "No Action was taken"
        Exit
    }
}

Function Generate-MgLegacyServicePrincipalReport
{
    [CmdletBinding()]
    param ()
    Write-Log Info -Message "The script is trying to connect to Graph with the following scope Application.ReadWrite.All"
    Connect-MgGraph -Scopes 'Application.ReadWrite.All'
    Write-Log warning -Message "The script connected to Graph with the following scope Application.ReadWrite.All"
    $AllServicePrincipals = Get-MgServicePrincipal -all
    $LegacyServicePrincipals = $AllServicePrincipals | Where { $_.ServicePrincipalType -eq "Legacy" }
    $Table = $Null
    $Table = @()
    
    foreach ($LegacyServicePrincipal in $LegacyServicePrincipals)
    {
        $ReplyUrls = $Null
        $ReplyUrls = $LegacyServicePrincipal.ReplyUrls
        $ReplyUrls = $ReplyUrls -join ";"
        $DisplayName = $Null
        $DisplayName = $LegacyServicePrincipal.DisplayName
        $AppId = $Null
        $AppId = $LegacyServicePrincipal.AppId
        $Id = $Null
        $Id = $LegacyServicePrincipal.Id
        $ServicePrincipal_ServicePrincipalNames = $Null
        $ServicePrincipalNames = $Null
        $ServicePrincipal_ServicePrincipalNames = $LegacyServicePrincipal.ServicePrincipalNames
        $ServicePrincipalNames = $ServicePrincipal_ServicePrincipalNames -join ";"
        $ServicePrincipalType = $Null
        $ServicePrincipalType = $LegacyServicePrincipal.ServicePrincipalType
        $CreatedDateTime = $Null
        $CreatedDateTime = $LegacyServicePrincipal.AdditionalProperties.createdDateTime
        $Table += New-object PSobject -Property ([Ordered] @{
                DisplayName              = $DisplayName;
                AppId                  = $AppId;
                Id                      = $Id;
                ReplyUrls              = $ReplyUrls;
                ServicePrincipalNames = $ServicePrincipalNames;
                ServicePrincipalType  = $ServicePrincipalType;
                CreatedDateTime          = $CreatedDateTime;
            })
        
    }
    
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ReportFilexlsx = ".\Report_LegacyServicePrincipals_" + $DateFull + ".xlsx"
    $Table | Export-Excel $ReportFilexlsx --TableName "ServicePrincipals" -Title "Legacy Service Principals" -TitleBold -WorksheetName "ServicePrincipals" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFilexlsx"
    
}

Function Generate-MgServicePrincipalReport
{
    [CmdletBinding()]
    param ()
    Write-Log Info -Message "The script is trying to connect to Graph with the following scope Application.ReadWrite.All"
    Connect-MgGraph -Scopes 'Application.ReadWrite.All'
    Write-Log warning -Message "The script connected to Graph with the following scope Application.ReadWrite.All"
    $ServicePrincipals = Get-MgServicePrincipal -all
    $Table = $Null
    $Table = @()
    
    foreach ($ServicePrincipal in $ServicePrincipals)
    {
        $ReplyUrls = $Null
        $ReplyUrls = $ServicePrincipal.ReplyUrls
        $ReplyUrls = $ReplyUrls -join ";"
        $DisplayName = $Null
        $DisplayName = $ServicePrincipal.DisplayName
        $AppId = $Null
        $AppId = $ServicePrincipal.AppId
        $Id = $Null
        $Id = $ServicePrincipal.Id
        $ServicePrincipal_ServicePrincipalNames = $Null
        $ServicePrincipalNames = $Null
        $ServicePrincipal_ServicePrincipalNames = $ServicePrincipal.ServicePrincipalNames
        $ServicePrincipalNames = $ServicePrincipal_ServicePrincipalNames -join ";"
        $ServicePrincipalType = $Null
        $ServicePrincipalType = $ServicePrincipal.ServicePrincipalType
        $CreatedDateTime = $Null
        $CreatedDateTime = $ServicePrincipal.AdditionalProperties.createdDateTime
        $OAuthPermissions = $Null
        $OAuthPermissions = $ServicePrincipal.Oauth2PermissionScopes
        If ($OAuthPermissions)
        {
            foreach ($OAuthPermission in $OAuthPermissions)
            {
                $IsEnabled = $Null
                $IsEnabled = $OAuthPermission.IsEnabled
                $Type = $Null
                $Type = $OAuthPermission.Type
                $Value = $Null
                $Value = $OAuthPermission.Value
                
                $Table += New-object PSobject -Property ([Ordered] @{
                        DisplayName              = $DisplayName;
                        AppId                  = $AppId;
                        Id                      = $Id;
                        ReplyUrls              = $ReplyUrls;
                        ServicePrincipalNames = $ServicePrincipalNames;
                        ServicePrincipalType  = $ServicePrincipalType;
                        CreatedDateTime          = $CreatedDateTime;
                        OAuthPermission          = $Value + ":" + $Type + "(" + $IsEnabled + ")"
                    })
            }
        }
        Else
        {
            $Table += New-object PSobject -Property ([Ordered] @{
                    DisplayName              = $DisplayName;
                    AppId                  = $AppId;
                    Id                      = $Id;
                    ReplyUrls              = $ReplyUrls;
                    ServicePrincipalNames = $ServicePrincipalNames;
                    ServicePrincipalType  = $ServicePrincipalType;
                    CreatedDateTime          = $CreatedDateTime;
                    OAuthPermission          = "no Permission"
                })
        }
        
        
    }
    
    $DateFull = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $ReportFile = ".\Mg_ServicesPrincipals_" + $DateFull + ".csv"
    $Table | Export-Csv $ReportFile -NoTypeInformation -Encoding UTF8
    $ReportFilexlsx = ".\Report_ServicesPrincipals_" + $DateFull + ".xlsx"
    $Table | Export-Excel $ReportFilexlsx --TableName "ServicePrincipals" -Title "Service Principals" -TitleBold -WorksheetName "ServicePrincipals" -TableStyle Medium9 -AutoSize -AutoFilter
    Write-log INFO -Message "Generate the following Report: $ReportFilexlsx"
    
}

#endregion

#region AAD

Function Generate-MgConditionalAccessPoliciesReport
{
    #Source https://github.com/Donovand4/ConditionalAccessPolicyReport/blob/master/Generate-ConditionalAccessReport.ps1
    # Find Tenant Name :Microsoft.Graph.Identity.DirectoryManagement
    #Check if Module ImportExcel is installed
    If (!(Get-InstalledModule -Name ImportExcel -ErrorAction Silentlycontinue))
    {
        Write-Log Error -Message "ImportExcel module is not installed - Please use the following CMDLet : Install-Module ImportExcel"
        #Start-Sleep -Seconds 10
        Read-Host "Pause before closing Powershell - Please use CTRL+C to cancel"
        Exit
    }
    
    #Connect using MgGraph
    
    Try
    {
        Write-Log Warning -Message "Trying to connect to MgGraph"
        Connect-MgGraph -Scopes 'Policy.Read.All', 'Directory.Read.All' -NoWelcome
        $MgContext = Get-MgContext
        $MgScopes = $MgContext.Scopes -join ";"
        Write-Log Info -Message "Connected to MgGraph with the following scopes: $MgScopes"
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to connect to MgGraph"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
        #Start-Sleep -Seconds 10
        Read-Host "Pause before closing Powershell - Please use CTRL+C to cancel"
        Exit
    }
    # Tenant Name
    $OnMicrosoft = (Get-MgDomain | where { $_.IsInitial }).Id
    $TenantName = $OnMicrosoft.Substring(0, $OnMicrosoft.IndexOf("."))
    # Variable
    
    $Date = Get-Date -Format "ddMMyyyy_HH-mm-ss"
    $Filename = "Report_ConditionalAccessPolicies_" + $TenantName + "_" + $Date
    $NamedLocationsFileName = "NamedLocations - " + $TenantName + "_" + $Date
    $ConditionalAccessPoliciesFileName = "Backup_ConditionalAccessPolicies - " + $TenantName + "_" + $Date
    #Function
    function Report-DirectoryApps
    {
        param (
            [Parameter(Mandatory = $true)]
            [String[]]$AppID
        )
        ($servicePrincipals | Where-Object { $_.AppID -eq $AppID }).DisplayName
    }
    
    function Report-NamedLocations
    {
        param (
            [Parameter(Mandatory = $true)]
            [String[]]$ID
        )
        switch ($ID)
        {
            '00000000-0000-0000-0000-000000000000' { 'Unknown Site' }
            'All' { 'All' }
            'AllTrusted' { 'AllTrusted' }
            Default {
                ($namedLocations | Where-Object { $_.ID -eq $ID }).displayName
            }
        }
    }
    
    function Get-TypeOfNamedLocations
    {
        param (
            [Parameter(Mandatory = $true)]
            [String[]]$TypeString
        )
        switch ($TypeString)
        {
            '#microsoft.graph.ipNamedLocation' { 'ipNamedLocation' }
            '#microsoft.graph.countryNamedLocation' { 'countryNamedLocation' }
            Default {
                "UnknownType"
            }
        }
    }
    
    function Report-Users
    {
        param (
            [Parameter(Mandatory = $true)]
            [String[]]$ID
        )
        switch ($ID)
        {
            'GuestsOrExternalUsers' { 'GuestsOrExternalUsers' }
            'All' { 'All' }
            Default {
                $user = (Get-MgUser -UserId "$($ID)" -ErrorAction SilentlyContinue).userprincipalname
                if ($user)
                {
                    $user
                }
                else
                {
                    "LookingUpError-$($ID)"
                }
            }
        }
    }
    
    function Report-Groups
    {
        param (
            [Parameter(Mandatory = $true)]
            [String[]]$ID
        )
        switch ($ID)
        {
            'GuestsOrExternalUsers' { 'GuestsOrExternalUsers' }
            'All' { 'All' }
            Default {
                $group = (Get-MgGroup -GroupId "$($ID)" -ErrorAction silentlycontinue).displayname
                if ($group)
                {
                    $group
                }
                else
                {
                    "LookingUpError-$($ID)"
                }
            }
        }
    }
    
    # Collect Named Locations
    Try
    {
        Write-Log warning -Message "Collecting Named Locations..."
        $namedLocations = Get-MgIdentityConditionalAccessNamedLocation | select-object displayname, id,`
                                                                                       @{ name = "Type"; expression = { ($_.AdditionalProperties.'@odata.type' | ForEach-Object { Get-TypeOfNamedLocations -TypeString $_ }) } },`
                                                                                       @{ name = "isTrusted"; expression = { $_.additionalproperties.isTrusted } },`
                                                                                       @{ name = "ipRanges"; expression = { $_.additionalproperties.ipRanges.cidrAddress -join "," } },`
                                                                                       @{ name = "Country"; express = { $_.additionalproperties.countriesAndRegions -join "," } },`
                                                                                       @{ name = "includeUnknownCountriesAndRegions"; expression = { $_.additionalproperties.includeUnknownCountriesAndRegions } },`
                                                                                       @{ name = "countryLookupMethod"; expression = { $_.additionalproperties.countryLookupMethod } }
        Write-Log Info -Message "Named Locations have been collected"
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to Collect Named Locations"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
    }
    
    # Collect Service Principals
    Try
    {
        Write-Log warning -Message "Collecting Service Principals..."
        $servicePrincipals = Get-MgServicePrincipal -All | Select-Object DisplayName, AppId
        Write-Log Info -Message " Service Principals have been collected"
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to collect Service Principals"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
    }
    
    # Collect ConditionalAccess Policies Data
    Try
    {
        Write-Log warning -Message "Collecting Conditional Access Policies..."
        $MgConditionalAccessPolicies = Get-MgIdentityConditionalAccessPolicy -All
        Write-Log Info -Message "Conditional Access Policies have been collected"
    }
    Catch
    {
        $ErrorMessage = $Error[0].Exception.Message
        $CMDLet = $Error[0].InvocationInfo.Line
        $FailedItem = $Error[0].Exception.ItemName
        Write-Log Error -Message "Failed to collect Conditional Access Policies"
        Write-Log Error -Message "Failed to run the following CMDLet: $CMDLet"
        Write-Log Error -Message "Failed with Error:$ErrorMessage"
    }
    
    $Report = @()
    #Collects the conditional access policies using the mgconditionalaccesspolicy command.
    foreach ($pol in $MgConditionalAccessPolicies)
    {
        $Report += New-Object PSobject -Property @{
            'Displayname' = $pol.displayName
            'Description' = $pol.Description
            'State'          = $pol.state
            'ID'          = $pol.id
            'createdDateTime' = if ($pol.createdDateTime) { $pol.createdDateTime } else { 'Null' }
            'ModifiedDateTime' = if ($pol.ModifiedDateTime) { $pol.ModifiedDateTime } else { 'Null' }
            'UserIncludeUsers' = if ($pol.Conditions.Users.IncludeUsers) { ($pol.Conditions.Users.IncludeUsers | ForEach-Object { (Report-Users -ID $_) }) -join ',' } else { 'Not Configured' }
            'UserExcludeUsers' = if ($pol.Conditions.Users.ExcludeUsers) { ($pol.Conditions.Users.ExcludeUsers | ForEach-Object { (Report-Users -ID $_) }) -join ',' } else { 'Not Configured' }
            'UserIncludeGroups' = if ($pol.Conditions.Users.IncludeGroups) { ($pol.Conditions.Users.IncludeGroups | ForEach-Object { (Report-Groups -ID $_) }) -join ',' } else { 'Not Configured' }
            'UserExcludeGroups' = if ($pol.Conditions.Users.ExcludeGroups) { ($pol.Conditions.Users.ExcludeGroups | ForEach-Object { (Report-Groups -ID $_) }) -join ',' } else { 'Not Configured' }
            'ConditionSignInRiskLevels' = if ($pol.Conditions.SignInRiskLevels) { $pol.Conditions.SignInRiskLevels -join ',' } else { 'Not Configured' }
            'ConditionClientAppTypes' = if ($pol.Conditions.ClientAppTypes) { $pol.Conditions.ClientAppTypes -join ',' } else { 'Not Configured' }
            'PlatformIncludePlatforms' = if ($pol.Conditions.Platforms.IncludePlatforms) { $pol.Conditions.Platforms.IncludePlatforms -join ',' } else { 'Not Configured' }
            'PlatformExcludePlatforms' = if ($pol.Conditions.Platforms.ExcludePlatforms) { $pol.Conditions.Platforms.ExcludePlatforms -join ',' } else { 'Not Configured' }
            'DevicesFilterStatesMode' = if ($pol.Conditions.Devices.DeviceFilter.Mode) { $pol.Conditions.Devices.DeviceFilter.Mode -join "," } else { "Failed to Report" }
            'DevicesFilterStatesRule' = if ($pol.Conditions.Devices.DeviceFilter.Rule) { $pol.Conditions.Devices.DeviceFilter.Rule -join "," } else { "Failed to Report" }
            'ApplicationIncludeApplications' = if ($pol.Conditions.Applications.IncludeApplications) { ($pol.Conditions.Applications.IncludeApplications | ForEach-Object { Report-DirectoryApps -AppID $_ }) -join ',' } else { 'Not Configured' }
            'ApplicationExcludeApplications' = if ($pol.Conditions.Applications.ExcludeApplications) { ($pol.Conditions.Applications.ExcludeApplications | ForEach-Object { Report-DirectoryApps -AppID $_ }) -join ',' } else { 'Not Configured' }
            'ApplicationIncludeUserActions' = if ($pol.Conditions.Applications.IncludeUserActions) { $pol.Conditions.Applications.IncludeUserActions -join ',' } else { 'Not Configured' }
            'LocationIncludeLocations' = if ($pol.Conditions.Locations.IncludeLocations) { ($pol.Conditions.Locations.IncludeLocations | ForEach-Object { Report-NamedLocations -ID $_ }) -join ',' } else { 'Not Configured' }
            'LocationExcludeLocations' = if ($pol.Conditions.Locations.ExcludeLocations) { ($pol.Conditions.Locations.ExcludeLocations | ForEach-Object { Report-NamedLocations -ID $_ }) -join ',' } else { 'Not Configured' }
            'GrantControlBuiltInControls' = if ($pol.GrantControls.BuiltInControls) { $pol.GrantControls.BuiltInControls -join ',' } else { 'Not Configured' }
            'GrantControlTermsOfUse' = if ($pol.GrantControls.TermsOfUse) { $pol.GrantControls.TermsOfUse -join ',' } else { 'Not Configured' }
            'GrantControlOperator' = if ($pol.GrantControls.Operator) { $pol.GrantControls.Operator } else { 'Not Configured' }
            'GrantControlCustomAuthenticationFactors' = if ($pol.GrantControls.CustomAuthenticationFactors) { $pol.GrantControls.CustomAuthenticationFactors -join ',' } else { 'Not Configured' }
            'CloudAppSecurityCloudAppSecurityType' = if ($pol.SessionControls.CloudAppSecurity.CloudAppSecurityType) { $pol.SessionControls.CloudAppSecurity.CloudAppSecurityType } else { 'Not Configured' }
            'ApplicationEnforcedRestrictions' = if ($pol.SessionControls.ApplicationEnforcedRestrictions.IsEnabled) { $pol.SessionControls.ApplicationEnforcedRestrictions.IsEnabled } else { 'Not Configured' }
            'CloudAppSecurityIsEnabled' = if ($pol.SessionControls.CloudAppSecurity.IsEnabled) { $pol.SessionControls.CloudAppSecurity.IsEnabled } else { 'Not Configured' }
            'PersistentBrowserIsEnabled' = if ($pol.SessionControls.PersistentBrowser.IsEnabled) { $pol.SessionControls.PersistentBrowser.IsEnabled } else { 'Not Configured' }
            'PersistentBrowserMode' = if ($pol.SessionControls.PersistentBrowser.Mode) { $pol.SessionControls.PersistentBrowser.Mode } else { 'Not Configured' }
            'SignInFrequencyIsEnabled' = if ($pol.SessionControls.SignInFrequency.IsEnabled) { $pol.SessionControls.SignInFrequency.IsEnabled } else { 'Not Configured' }
            'SignInFrequencyType' = if ($pol.SessionControls.SignInFrequency.Type) { $pol.SessionControls.SignInFrequency.Type } else { 'Not Configured' }
            'SignInFrequencyValue' = if ($pol.SessionControls.SignInFrequency.Value) { $pol.SessionControls.SignInFrequency.Value } else { 'Not Configured' }
        }
    }
    
    Write-Log warning -Message 'Generating the Reports & backups ...'
    $ReportData = $Report | Select-Object -Property Displayname, Description, State, ID, createdDateTime, ModifiedDateTime, UserIncludeUsers, UserExcludeUsers, UserIncludeGroups, UserExcludeGroups, ConditionSignInRiskLevels, ConditionClientAppTypes, PlatformIncludePlatforms, PlatformExcludePlatforms, DevicesFilterStatesMode, DevicesFilterStatesRule, ApplicationIncludeApplications, ApplicationExcludeApplications, ApplicationIncludeUserActions, LocationIncludeLocations, LocationExcludeLocations, GrantControlBuiltInControls, GrantControlTermsOfUse, GrantControlOperator, GrantControlCustomAuthenticationFactors, ApplicationEnforcedRestrictions, CloudAppSecurityCloudAppSecurityType, CloudAppSecurityIsEnabled, PersistentBrowserIsEnabled, PersistentBrowserMode, SignInFrequencyIsEnabled, SignInFrequencyType, SignInFrequencyValue | Sort-Object -Property Displayname
    Write-Log warning -Message "Generating the Excel Reports. $($Filename.xlsx)"
    $ReportData | Export-excel -Path "$Filename.xlsx"
    Write-Log warning -Message "Generating the Excel Reports for Named locations. $($NamedLocationsFileName.xlsx)"
    $namedLocations | Export-excel -Path "$NamedLocationsFileName.xlsx"
    Write-Log warning -Message "Generating the Conditional Access policies Backup File. $($ConditionalAccessPoliciesFileName.xml)"
    $MgConditionalAccessPolicies | Export-Clixml "$ConditionalAccessPoliciesFileName.xml"
    Write-Log warning -Message 'Disconnecting from Microsoft Graph'
    Disconnect-MgGraph
    
    
}

#endregion