I did a github request to have the script into veeamhub repository but not yes validated.
I post it here for people who want to test it and want to give me some feedback about some bug / error / missing parts
It's designed for V7 and not tested on V6 build
Code: Select all
# =======================================================
# NAME: VBM365audit.ps1
# AUTHOR: Commenge Damien, Axians Cloud Builder
# DATE: 11/07/2022
#
# VERSION 1.04
# COMMENTS: This script is created to Audit Veeam backup for microsoft 365
# <N/A> is used for not available
# =======================================================
<#
# 16/07/2022 
    Update lot of code for better performance
# 18/07/2022 
    Change date format and replace VBM to VB365
# 26/07/2022 
    Optimize path creation
# 09/08/2023 
    Add storage account
    Add backup copy
    Add encryption key
    Add Teams graph API
    Add modern authentication notifications    
#>
# =======================================================
#Requires -Modules @{ ModuleName="Veeam.Archiver.PowerShell"; ModuleVersion="6.0" }
#Date to create folder
$Date = Get-Date -Format "yyyy-MM-dd HH_mm"
#ReportPath to create folder
$ReportPath="C:\temp\VBM365Audit\$Date"
#Create folder
New-Item -ItemType Directory -Path $ReportPath -Force | Out-Null
#Report path
$HTMLReportPath = "$ReportPath\VeeamBackupMicrosoft365.html"
#Web page title
$HTMLTitle = "VBM365 report"
#Web page CSS style
$HTMLCSS = @'
<style>
    body{color:black;font-family:Vinci Sans Light;font-size:0.79em;line-height:1.25;margin:5;}
    a{color:black;}
    H1{color:white;font-family:Verdana;font-weight:bold;font-size:20pt;margin-bottom:50px;margin-top:40px;text-align:center;background-color:#005EB8;}
    H2{color:#A20067;font-family:Verdana;font-size:16pt;margin-left:14px;text-align:left;}
    H3{color:#005EB8;font-family:Verdana;font-size:13pt;margin-left:16px;}
    H4{color:black;font-family:Verdana;font-size:11pt;margin-left:16px;}
    table {border-collapse: collapse;margin-left:10px;border-radius:7px 7px 0px 0px;}
    th, td {padding: 8px;text-align: left;border-bottom: 1px solid #ddd;}
    th {background-color: #006400;color: white;}
    td:first-child{font-weight:bold;}
    tr:nth-child(even){background-color: #f2f2f2}
    table.table2 td:first-child{background-color: #A20067;color: white}
</style>
'@
#Connect to VBO Server
Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - Connecting to VBM 365 server"
try {
    Connect-VBOServer -ErrorAction Stop
    Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - Connected to VBM 365 server"
}
catch [System.Management.Automation.RuntimeException]{
    Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - Connexion is already done"
}
catch {
    Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - $($_.Exception.message) " -ForegroundColor Red
    return
}
 <#
 .SYNOPSIS
    Get configuration Summary from Veeam Microsoft 365 server
 .DESCRIPTION
    Get server name, OS, OS build and VBM365 version
 .EXAMPLE 
    Get-DCVB365Summary
 #>
function Get-DCVB365Summary
{
    Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Summary"
    $ServerName   = $env:COMPUTERNAME
    $ServerOS     = (Get-CimInstance Win32_OperatingSystem).Caption
    $OSBuild      = Get-ItemPropertyValue -path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion" -name 'UBR'
    $VB365build   = (Get-VBOVersion).ProductVersion
    
    
    [PScustomObject]@{
        Name            = $ServerName
        OS              = $ServerOS
        OSBuild         = $OSBuild
        VB365Version    = $VB365build
    }
}
 <#
 .SYNOPSIS
    Get configuration about organizations
 .DESCRIPTION
    Get organization name, account used, type (on premise, hybride, O365), service (exchange, sharepoint), region, authentication (basic, modern with legacy protocol, modern), auxiliar backup account/application number
 .EXAMPLE 
    Get-DCVB365Organization
 #>
function Get-DCVB365Organization
{
    Write-host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Organization"
    $Organization = Get-VBOOrganization
    if ($Organization.Office365ExchangeConnectionSettings)
    {
        $OrgAuth = (Get-VBOOrganization).Office365ExchangeConnectionSettings.AuthenticationType
    }
    else
    {
        $OrgAuth = (Get-VBOOrganization).Office365SharePointConnectionSettings.AuthenticationType
    }
    if ($OrgAuth -eq "Basic")
    {
        $AuxAccount = (Get-VBOOrganization).backupaccounts.count
    }
    else
    {
        $AuxAccount = (Get-VBOOrganization).backupapplications.count
    }
    [PScustomObject]@{
        Name            = $Organization.OfficeName
        Account         = $Organization.username
        Type            = $Organization.type
        Service         = $Organization.BackupParts
        Region          = $Organization.region
        Authentication  = $OrgAuth
        AuxAccount      = $AuxAccount
    }
}
 <#
 .SYNOPSIS
    Get configuration about backup job configuration
 .DESCRIPTION
    Get job name, type, included object, excluded object, repository, proxy, schedule, active or disabled state
 .EXAMPLE 
    Get-DCVB365BackupJob
 #>
function Get-DCVB365BackupJob
{
    Write-host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Backup Jobs"
    foreach ($Job in Get-VBOJob)
    {
        #Get proxy name from associated proxy ID repository
        $JobSchedule = "<N/A>"
        if ($Job.schedulepolicy.EnableSchedule -and $Job.SchedulePolicy.Type -eq "daily")
        {
             $JobSchedule = [string]$Job.SchedulePolicy.DailyTime + " " + $Job.SchedulePolicy.DailyType
        }
        if ($Job.schedulepolicy.EnableSchedule -and $Job.SchedulePolicy.Type -eq "Periodically")
        {
             $JobSchedule = $Job.SchedulePolicy.PeriodicallyEvery
        }
        [PScustomObject]@{
            Name        = $Job.Name
            Type        = $Job.JobBackupType
            InclObject  = $Job.SelectedItems -join ", "
            ExclObject  = $Job.ExcludedItems -join ", "
            Repository  = $Job.Repository
            Proxy       = (Get-VBOProxy -id (Get-VBORepository -Name $Job.Repository).Proxy.Id -ExtendedView:$False).Hostname
            Schedule    = $JobSchedule
            Enabled     = $Job.IsEnabled
        }
    }
}
<#
 .SYNOPSIS
    Get configuration about backup copy job configuration
 .DESCRIPTION
    Get job name, repository, backupjob linked, schedule, active or disabled state
 .EXAMPLE 
    Get-DCVB365BackupCopyJob
 #>
function Get-DCVB365BackupCopyJob
{
    Write-host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Backup copy Jobs"
    $CopyJobs = Get-VBOCopyJob
    if ($CopyJobs)
    {
        foreach ($CopyJob in $CopyJobs)
        {
            if ($CopyJob.SchedulePolicy.Type -eq "daily")
            {
                 $JobSchedule = [string]$CopyJob.SchedulePolicy.DailyTime + " " + $CopyJob.SchedulePolicy.DailyType
            }
            if ($CopyJob.SchedulePolicy.Type -eq "Periodically")
            {
                 $JobSchedule = $CopyJob.SchedulePolicy.PeriodicallyEvery
            }
            else 
            {
                $JobSchedule = $CopyJob.SchedulePolicy.Type
            }
            [PScustomObject]@{
                Name            = $CopyJob.name
                Repository      = $CopyJob.Repository
                BackupLinked    = $CopyJob.BackupJob.name
                Schedule        = $JobSchedule
                Enabled         = $CopyJob.IsEnabled
            }
        }
    }
    else
    {
        [PScustomObject]@{
            Name            = "<N/A>"
            Repository      = "<N/A>"
            BackupLinked    = "<N/A>"
            Schedule        = "<N/A>"
            Enabled         = "<N/A>"
        }        
    }
}
 <#
 .SYNOPSIS
    Get configuration about proxy configuration
 .DESCRIPTION
    Get proxy name, port, thread number, throttling, internet proxy used or not, internet proxy port and account
 .EXAMPLE 
    Get-DCVB365Proxy
 #>
function Get-DCVB365Proxy
{
    Write-host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Proxy"
    foreach ($Proxy in (Get-VBOProxy -ExtendedView:$False))
    {
        $Proxy = [PScustomObject]@{
            Name            = $Proxy.hostname
            Port            = $Proxy.port
            Thread          = $Proxy.ThreadsNumber
            Throttling      = [string]$Proxy.ThrottlingValue + " " + $Proxy.ThrottlingUnit
            IntProxyHost    = "<N/A>"
            IntProxyPort    = "<N/A>"
            IntProxyAccount = "<N/A>"
        }
        if ($Proxy.InternetProxy.UseInternetProxy)
        {
            $Proxy.IntProxyHost     = $Proxy.InternetProxy.UseInternetProxy.Host
            $Proxy.IntProxyPort     = $Proxy.InternetProxy.UseInternetProxy.Port
            $Proxy.IntProxyAccount  = $Proxy.InternetProxy.UseInternetProxy.User
        }
    }
    $Proxy
}
 <#
 .SYNOPSIS
    Get configuration about repository configuration
 .DESCRIPTION
    Get repository name, proxy associated, path, retention type and value, repository object name and encryption
 .EXAMPLE 
    Get-DCVB365Repository
 #>
 function Get-DCVB365Repository
 {
 
     Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Repository"
 
     foreach ($Repository in Get-VBORepository)
     {
        $Proxy        =  (Get-VBOProxy -id (Get-VBORepository -name $Repository.Name).Proxy.Id -ExtendedView:$False).Hostname
        $Retention    = [string]$Repository.RetentionPeriod + " " + $Repository.RetentionType
         $ObjectName   = "<N/A>"
         if ($Repository.ObjectStorageRepository)
         {
             $ObjectName = $Repository.ObjectStorageRepository.Name
         }
         [int]$UsedStorage = ($Repository.Capacity - $Repository.FreeSpace) / 1GB
         [int]$TotalStorage = $Repository.Capacity / 1GB
         [PScustomObject]@{
             Name                = $Repository.Name
             Proxy               = $Proxy
             Path                = $Repository.Path
             ObjectRepository    = $ObjectName
             Retention           = $Retention
             Encryption          = $Repository.EnableObjectStorageEncryption
             'Storage(GB)'             = [String]$UsedStorage + "/" +  $TotalStorage
         }
     }
 }
 
 <#
 .SYNOPSIS
    Get configuration about object repository configuration
 .DESCRIPTION
    Get repository name, folder, type, UsedSpace, size limit and if it's long term achive
 .EXAMPLE 
    Get-DCVB365ObjectRepository
 #>
 function Get-DCVB365ObjectRepository
 {
     Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Object Repository"
 
     foreach ($ObjectStorage in Get-VBOObjectStorageRepository)
     {
         $SizeLimit = "<N/A>"
         if ($ObjectStorage.EnableSizeLimit)
         {
             $SizeLimit = [String]$ObjectStorage.UsedSpace + "/" + $ObjectStorage.SizeLimit
         }
         [PScustomObject]@{
             Name        = $ObjectStorage.name
             Folder      = $ObjectStorage.Folder
             Type        = $ObjectStorage.Type
             'UsedSpace(GB)'   = [int]($ObjectStorage.UsedSpace / 1GB)
             SizeLimit   = $SizeLimit
             LongTerm    = $ObjectStorage.IsLongTerm
         }
     }
 }
 <#
 .SYNOPSIS
    Get configuration about license
 .DESCRIPTION
    Get license type, expiration date, customer, contact, usage
 .EXAMPLE 
    Get-DCVB365License
 #>
 function Get-DCVB365License
 {
 
     Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 License"
     $License         = (Get-VBOLicense)
     $Usage    = [string]$License.usedNumber + "/" + (Get-VBOLicense).TotalNumber
 
     [PScustomObject]@{
         Type        = $License.Type
         Expiration  = $License.ExpirationDate.ToUniversalTime().ToString("yyyy/MM/dd")
         To          = $License.LicensedTo
         Contact     = $License.ContactPerson
         Number      = $Usage
     }
 }
 <#
 .SYNOPSIS
    Get configuration about restore operator configuration
 .DESCRIPTION
    Get role name, organization, operator, associated object, excluded object
 .EXAMPLE 
    Get-DCVB365RestoreOperator
 #>
function Get-DCVB365RestoreOperator
{
    Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Restore Operator"
    $Roles = Get-VBORbacRole
    if ($role)
    {
        foreach ($Role in $Roles)
        {
                $IncludedObject = "Organization"
                $ExcludedObject = "<N/A>"
                if ($Role.RoleType -ne "EntireOrganization")
                {
                    $IncludedObject = $Role.SelectedItems.DisplayName -join ", "
                }
                if ($Role.ExcludedItems)
                {
                $ExcludedObject = $Role.ExcludedItems.DisplayName -join ", "
                }
                [PScustomObject]@{
                    Role            = $Role.Name
                    Organization    = (Get-VBOOrganization -Id ($Role.OrganizationId)).Name
                    Operator        = $Role.Operators.DisplayName -join ", "
                    IncludedObject  = $IncludedObject
                    ExcludedObject  = $ExcludedObject
                }
            }
        }
    else
    {
        [PScustomObject]@{
            Role            = "<N/A>"
            Organization    = "<N/A>"
            Operator        = "<N/A>"
            IncludedObject  = "<N/A>"
            ExcludedObject  = "<N/A>"
        }
    }
}
 <#
 .SYNOPSIS
    Get configuration about RestAPI configuration
 .DESCRIPTION
    Get state, token life time, port, certificate thumbprint friendly name and expiration date
 .EXAMPLE 
    Get-DCVB365RestAPI
 #>
function Get-DCVB365RestAPI
{
    Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 REST API"
        
    $RestAPI = Get-VBORestAPISettings
    [PScustomObject]@{
        Enabled             = $RestAPI.IsServiceEnabled
        CertThumbprint      = $RestAPI.CertificateThumbprint
        CertFriendlyName    = $RestAPI.CertificateFriendlyName
        CertExpiration      = $RestAPI.CertificateExpirationDate.ToUniversalTime().ToString("yyyy/MM/dd")
        TokenTime           = $RestAPI.AuthTokenLifeTime
        Port                = $RestAPI.HTTPSPort
    }
}
 <#
 .SYNOPSIS
    Get configuration about Restore portal configuration
 .DESCRIPTION
    Get state, application ID, certificate thumbprint friendly name and expiration date
 .EXAMPLE 
    Get-DCVB365RestorePortal
 #>
 function Get-DCVB365RestorePortal
 {
 
     Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Restore portal"
 
     $RestorePortal = Get-VBORestorePortalSettings
 
     [PScustomObject]@{
         Enabled             = $RestorePortal.IsServiceEnabled
         CertThumbprint      = $RestorePortal.CertificateThumbprint
         CertFriendlyName    = $RestorePortal.CertificateFriendlyName
         CertExpiration      = $RestorePortal.CertificateExpirationDate.ToUniversalTime().ToString("yyyy/MM/dd")
         AzureApplicationID  = $RestorePortal.ApplicationId.Guid
     }
 }
 <#
 .SYNOPSIS
    Get configuration about operator Authentication portal configuration
 .DESCRIPTION
    Get state, certificate thumbprint friendly name and expiration date
 .EXAMPLE 
    Get-DCVB365OperatorAuthentication
 #>
 function Get-DCVB365OperatorAuthentication
 {
     Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Authentication"
 
     $OperatorAuthentication = Get-VBOOperatorAuthenticationSettings
 
     [PScustomObject]@{
         Enabled             = $OperatorAuthentication.AuthenticationEnabled
         CertThumbprint      = "InFutureVersion"
         CertFriendlyName    = $OperatorAuthentication.CertificateFriendlyName
         CertExpiration      = $OperatorAuthentication.CertificateExpirationDate.ToUniversalTime().ToString("yyyy/MM/dd")
     }
 }
 <#
 .SYNOPSIS
    Get configuration about internet proxy
 .DESCRIPTION
    Get state, host, port and account
 .EXAMPLE 
    Get-DCVB365InternetProxy
 #>
function Get-DCVB365InternetProxy
{
    Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Internet Proxy"
    $InternetProxySetting = Get-VBOInternetProxySettings
    $InternetProxy = [PScustomObject]@{
        Enabled   = $InternetProxySetting.UseInternetProxy
        Host      = "<N/A>"
        Port      = "<N/A>"
        Account   = "<N/A>"
    }
    if ($InternetProxySetting.UseInternetProxy)
    {
        $InternetProxy.Host    = $InternetProxySetting.Host
        $InternetProxy.Port    = $InternetProxySetting.Port
        $InternetProxy.Account = $InternetProxySetting.User
    }
    $InternetProxy
}
 <#
 .SYNOPSIS
    Get configuration about SMTP
 .DESCRIPTION
    Get state, server, port, ssl, account, type
 .EXAMPLE 
    Get-DCVB365SMTP
 #>
 function Get-DCVB365SMTP
 {
     Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 SMTP configuration"
 
     $SMTPSetting = Get-VBOEmailSettings
     $Type = if ($SMTPSetting.AuthenticationType -eq "CustomSmtp")
             {
                 "SMTP authentication"
             }
             else
             {
                 $SMTPSetting.AuthenticationType
             }
     $SMTP = [PScustomObject]@{
         Enabled = $SMTPSetting.EnableNotification
         Type    = "<N/A>"
         Server  = "<N/A>"
         Port    = "<N/A>"
         SSL     = "<N/A>"
         Account = "<N/A>"
     }
     if ($SMTPSetting.EnableNotification)
     {
         $SMTP.Type   = $Type
 
 
         if ($Type -eq "SMTP authentication") 
         {
             $SMTP.Port   = $SMTPSetting.Port
             $SMTP.Server = $SMTPSetting.SMTPServer
             $SMTP.SSL    = $SMTPSetting.UseSSL
 
             if ($SMTPSetting.UseAuthentication)
             {
                 $SMTP.Account = $SMTPSetting.Username
             }
         }
         else
         {
             $SMTP.Server = $SMTPSetting.MailApiUrl
             $SMTP.Account = $SMTPSetting.UserId
         }
     }
     $SMTP
 }
 <#
 .SYNOPSIS
    Get configuration about Notifications
 .DESCRIPTION
    Get state, sender, receiver, notification on success, warning and failure, send only last retry notification
 .EXAMPLE 
    Get-DCVB365Notification
 #>
function Get-DCVB365Notification
{
    Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Notifications"
    $NotificationSetting = (Get-VBOEmailSettings)
    $Notification = [PScustomObject]@{
        Enabled     = $NotificationSetting.EnableNotification
        Sender      = "<N/A>"
        Receiver    = "<N/A>"
        Success     = "<N/A>"
        Warning     = "<N/A>"
        Failure     = "<N/A>"
        LastRetry   = "<N/A>"
    }
    if ($NotificationSetting.EnableNotification)
    {
        $Notification.Sender     = $NotificationSetting.From -join ", "
        $Notification.Receiver   = $NotificationSetting.To -join ", "
        $Notification.Success    = $NotificationSetting.NotifyOnSuccess
        $Notification.Warning    = $NotificationSetting.NotifyOnWarning
        $Notification.Failure    = $NotificationSetting.NotifyOnFailure
        $Notification.LastRetry  = $NotificationSetting.SupressUntilLastRetry
    }
    $Notification
}
 <#
 .SYNOPSIS
    Get configuration about cloud storage account
 .DESCRIPTION
    Get account, type and description
 .EXAMPLE 
    Get-DCVB365StorageAccount
 #>
function Get-DCVB365StorageAccount
{
    Write-host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Cloud storage account"
    #Azure storage account
    $AzureAccount = Get-VBOAzureBlobAccount
    foreach ($account in $AzureAccount)
    {
        [PSCustomObject]@{
            Account = $Account.Name
            Type = "Azure Blob"
            Description = $Account.Description
        }
    }
    #Amazon storage account
    $AmazonAccount = Get-VBOAmazonS3Account
    foreach ($account in $AmazonAccount)
    {
        [PSCustomObject]@{
            Account = $Account.AccessKey
            Type = "Amazon S3"
            Description = $Account.Description
        }
    }
    #S3 compatible storage account
    $S3Compatible = Get-VBOAmazonS3CompatibleAccount
    foreach ($account in $S3Compatible)
    {
        [PSCustomObject]@{
            Account = $Account.AccessKey
            Type = "Amazon S3"
            Description = $Account.Description
        }
    }
}
 <#
 .SYNOPSIS
    Get configuration about cloud storage account
 .DESCRIPTION
    Get account, type and description
 .EXAMPLE 
    Get-DCVB365StorageAccount
 #>
function Get-DCVB365EncryptionKey
{
    Write-host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Encryption key"
    $EncryptionKey = Get-VBOEncryptionKey
    foreach ($obj in $EncryptionKey)
    {
        $repository = Get-VBORepository | Where-Object {$_.ObjectStorageEncryptionKey.ID.Guid -eq $obj.Id.Guid}
        [PSCustomObject]@{
            Repository = $repository.Name
            Description = $obj.Description
        }
    }
}
 <#
 .SYNOPSIS
    Get configuration about Teams Graph API state on VBM365 and proxy
 .DESCRIPTION
    Get Teams graph API state enabled or disabled on all proxies and Veeam 365 server
 .EXAMPLE 
    Get-DCVB365StorageAccount
 #>
function Get-DCVB365TeamsGraphAPIState
{
    Write-host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Teams graph api state"
    #VBM365 server
    [PSCustomObject]@{
        Server        = $env:COMPUTERNAME 
        TeamsGraphApi = (Get-VBOServer).IsTeamsGraphAPIBackupEnabled
    }
    $Proxy = Get-VBOProxy 
    foreach ($obj in $Proxy)
    {
        [PSCustomObject]@{
            Server = $obj.Hostname
            TeamsGraphApi = $obj.IsTeamsGraphAPIBackupEnabled
        }
    }
}
##########################################################################
<#
.SYNOPSIS
   Generate HTML report
.DESCRIPTION
   Use all variable to build html report with CSS style 
.EXAMPLE
   Get-HTMLReport -Path "C:\temp\report.html"
#>
Function Get-HTMLReport
{
    [CmdletBinding()]
    Param
    (
        #HTML file path
        [Parameter(Mandatory)]
        [System.IO.FileInfo]$Path
    )
    Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm") - VBM365 Building HTML"
    #region HTML
    # chrisdent: STYLE: In the code below `CreateArray` is something of a misleading function name.
    # chrisdent: ENHANCEMENT: Perhaps consider using a string builder.
 @"
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>$HTMLTitle</title>
    $HTMLCSS
    </head>
    <body>
    <br><br><br><br>
    <h1>VEEAM Backup for Microsoft 365 Report</h1>
    <h3> Summary </h3>
    $($DCVB365Summary)
    <h3> License </h3>
    $DCVB365License
    <h3> SMTP </h3>
    $DCVB365SMTP
    <h3> Notification </h3>
    $DCVB365Notification
    <h3> Web Proxy </h3>
    $DCVB365InternetProxy
    <h3> REST API </h3>
    $DCVB365RestAPI
    <h3> Restore portal </h3>
    $DCVB365RestorePortal
    <h3> Restore operator authentication </h3>
    $DCVB365OperatorAuthentication
    <h3> Repository </h3>
    $DCVB365Repository
    <h3> Object Repository </h3>
    $DCVB365ObjectRepository
    <h3> Organisation </h3>
    $DCVB365Organization
    <h3> Proxy </h3>
    $DCVB365Proxy
    <h3> Backup job </h3>
    $DCVB365BackupJob
    <h3> Backup copy job </h3>
    $DCVB365BackupCopyJob
    <h3> Restore operators </h3>
    $DCVB365RestoreOperator
    <h3> Cloud storage account </h3>
    $DCVB365StorageAccount
    <h3> Encryption key </h3>
    $DCVB365EncryptionKey
    <h3> Teams graph API state </h3>
    $DCVB365TeamsGraphAPIState
    
    </body>
    </html>
"@ | Out-File -FilePath $HTMLReportPath
    Invoke-Item $HTMLReportPath
   
}
#endregion
#Write here all function that need to be displayed in all reports types
$DCVB365Summary                   = Get-DCVB365Summary | ConvertTo-Html -Fragment
$DCVB365Organization              = Get-DCVB365Organization | Sort-object Name | ConvertTo-Html -Fragment
$DCVB365BackupJob                 = Get-DCVB365BackupJob | Sort-object Name | ConvertTo-Html -Fragment
$DCVB365Proxy                     = Get-DCVB365Proxy | Sort-object Name | ConvertTo-Html -Fragment
$DCVB365Repository                = Get-DCVB365Repository | Sort-object Name | ConvertTo-Html -Fragment
$DCVB365License                   = Get-DCVB365License | ConvertTo-Html -Fragment
$DCVB365RestoreOperator           = Get-DCVB365RestoreOperator | ConvertTo-Html -Fragment
$DCVB365RestAPI                   = Get-DCVB365RestAPI  | ConvertTo-Html -Fragment
$DCVB365RestorePortal             = Get-DCVB365RestorePortal | ConvertTo-Html -Fragment
$DCVB365OperatorAuthentication    = Get-DCVB365OperatorAuthentication | ConvertTo-Html -Fragment
$DCVB365InternetProxy             = Get-DCVB365InternetProxy | ConvertTo-Html -Fragment
$DCVB365SMTP                      = Get-DCVB365SMTP | ConvertTo-Html -Fragment
$DCVB365Notification              = Get-DCVB365Notification | ConvertTo-Html -Fragment
$DCVB365ObjectRepository          = Get-DCVB365ObjectRepository | Sort-object Name | ConvertTo-Html -Fragment
$DCVB365BackupCopyJob             = Get-DCVB365BackupCopyJob | Sort-object Name | ConvertTo-Html -Fragment
$DCVB365StorageAccount            = Get-DCVB365StorageAccount | Sort-object Type | ConvertTo-Html -Fragment
$DCVB365EncryptionKey             = Get-DCVB365EncryptionKey | ConvertTo-Html -Fragment
$DCVB365TeamsGraphAPIState        = Get-DCVB365TeamsGraphAPIState | ConvertTo-Html -Fragment
#Create HTML Report.
Get-HTMLReport -Path $HTMLReportPath
Disconnect-VBOServer