Functions/Connect-ExchangeOnlineAdminAccount.ps1

<#
.SYNOPSIS
    This function connects to Exchange Online using admin account credentials or a MSPComplete Endpoint.
.DESCRIPTION
    This function connects to Exchange Online using admin account credentials or a MSPComplete Endpoint.
    It returns whether the connection and logon was successful.
.EXAMPLE
    Connect-ExchangeOnlineAdminAccount -Endpoint $Endpoint
.EXAMPLE
    $Endpoint | Connect-ExchangeOnlineAdminAccount
.EXAMPLE
    Connect-ExchangeOnlineAdminAccount -Username $username -Password $password
#>

function Connect-ExchangeOnlineAdminAccount {
    param (
        # The username of the Exchange Online admin account.
        [Parameter(Mandatory=$true, ParameterSetName="credential")]
        [string]$username,

        # The password of the Exchange Online admin account.
        [Parameter(Mandatory=$true, ParameterSetName="credential")]
        [SecureString]$password,

        # The MSPComplete Endpoint for the Exchange Online admin credentials.
        [Parameter(Mandatory=$true, ParameterSetName="endpoint", ValueFromPipeline=$true)]
        $endpoint,

        # The maximum number of logon attempts. Each logon attempt can take up to 60 seconds.
        [Parameter(Mandatory=$false)]
        [ValidateScript({ $_ -gt 1 })]
        [Int]$maximumAttempts = 5
    )

    # If given endpoint, retrieve username and password
    if ($PSCmdlet.ParameterSetName -eq "endpoint") {
        $exchangeCredential = $endpoint | Get-CredentialFromMSPCompleteEndpoint
        $username = $exchangeCredential.Username
    }

    # Create the Exchange Online credential from the given username and password
    else {
        $exchangeCredential = [PSCredential]::new($username, $password)
    }

    # Store the username used globally
    $Global:ExchangeOnlineUsername = $username

    # Logon to Exchange Online
    $attemptNum = 0
    while ($true) {
        try {
            $exchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange `
                -ConnectionUri "https://outlook.office365.com/powershell-liveid/" `
                -Credential $exchangeCredential -Authentication Basic -AllowRedirection -Name "ExchangeOnline" `
                -ErrorVariable errorOutput

            # Additional Import-Module ensures that imported cmdlets are visible globally
            Import-Module (Import-PSSession -Session $exchangeSession -DisableNameChecking -AllowClobber) -Global
        }
        catch {
            # Set the error output to the exception message
            if ([String]::IsNullOrWhiteSpace($errorOutput)) {
                $errorOutput = $_.Exception.Message
            }

            # Check if error was due to too many runspaces
            if ($errorOutput -like "*Fail to create runspace because you have exceeded your budget to create runspace*") {
                $attemptNum += 1
                if ($attemptNum -ge $maximumAttempts) {
                    return $false
                }
                Write-Information "Encountered throttling when connecting to Exchange Online - waiting 60 seconds before re-attempting to logon. (attempt $($attemptNum + 1)/$($maximumAttempts))"
                Start-Sleep -Seconds 60
                continue
            }

            # Check if error was due to the remote shell going missing
            elseif ($errorOutput -like "*failed because the shell was not found on the server.*") {
                $attemptNum += 1
                if ($attemptNum -ge $maximumAttempts) {
                    return $false
                }
                Write-Information "Encountered an error with the Remote Shell - re-attempting to logon. (attempt $($attemptNum + 1)/$($maximumAttempts))"
                Start-Sleep -Seconds 10
                continue
            }

            # Logon was unsuccessful due to other error
            Write-Error "Failed Exchange Online logon with username '$($username)'.`r`n$($_.Exception.Message)"
            return $false
        }

        # Any other error was present
        if (![String]::IsNullOrWhiteSpace($errorOutput)) {
            Write-Error "Failed Exchange Online logon with username '$($username)'.`r`n$($errorOutput)"
            return $false
        }

        # Logon was successful
        Write-Information "Logon to Exchange Online successful with username '$($username)'."
        return $true
    }
}