functions/service/Connect-EXCExchange.ps1

function Connect-EXCExchange {
    <#
    .SYNOPSIS
        A brief description of the Connect-EXCExchange function.
     
    .DESCRIPTION
        A detailed description of the Connect-EXCExchange function.
     
    .PARAMETER MailboxName
        A description of the MailboxName parameter.
     
    .PARAMETER Credentials
        A description of the Credentials parameter.
     
    .EXAMPLE
        PS C:\> Connect-EXCExchange -MailboxName 'value1' -Credentials $Credentials
#>

    [CmdletBinding()]
    param (
        [Parameter(Position = 0, Mandatory = $true)]
        [string]
        $MailboxName,
        
        [Parameter(Position = 1, Mandatory = $False)]
        [System.Management.Automation.PSCredential]
        $Credentials,

        [Parameter(Position = 2, Mandatory = $False)]
        [switch]
        $ModernAuth,
        
        [Parameter(Position = 3, Mandatory = $False)]
        [String]
        $ClientId = "d3590ed6-52b3-4102-aeff-aad2292ab01c",

        [Parameter(Position = 4, Mandatory = $False)]
        [String]
        $redirectUri= "urn:ietf:wg:oauth:2.0:oob",

        [Parameter(Position = 5, Mandatory = $False)]
        [String]
        $CertificateFilePath,
        
        [Parameter(Position = 6, Mandatory = $False)]
        [Security.SecureString]
        $CertificatePassword  
    )
    Begin {
        ## Load Managed API dll
        ###CHECK FOR EWS MANAGED API, IF PRESENT IMPORT THE HIGHEST VERSION EWS DLL, ELSE EXIT
        if (Test-Path ($script:ModuleRoot + "/bin/Microsoft.Exchange.WebServices.dll")) {
            Import-Module ($script:ModuleRoot + "/bin/Microsoft.Exchange.WebServices.dll")
            $Script:EWSDLL = $script:ModuleRoot + "/bin/Microsoft.Exchange.WebServices.dll"
            write-verbose ("Using EWS dll from Local Directory")
        }
        else {

            
            ## Load Managed API dll
            ###CHECK FOR EWS MANAGED API, IF PRESENT IMPORT THE HIGHEST VERSION EWS DLL, ELSE EXIT
            $EWSDLL = (($(Get-ItemProperty -ErrorAction SilentlyContinue -Path Registry::$(Get-ChildItem -ErrorAction SilentlyContinue -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Web Services'|Sort-Object Name -Descending| Select-Object -First 1 -ExpandProperty Name)).'Install Directory') + "Microsoft.Exchange.WebServices.dll")
            if (Test-Path $EWSDLL) {
                Import-Module $EWSDLL
                $Script:EWSDLL = $EWSDLL 
            }
            else {
                "$(get-date -format yyyyMMddHHmmss):"
                "This script requires the EWS Managed API 1.2 or later."
                "Please download and install the current version of the EWS Managed API from"
                "http://go.microsoft.com/fwlink/?LinkId=255472"
                ""
                "Exiting Script."
                exit


            } 
        }
        
        ## Set Exchange Version
        $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2
        
        ## Create Exchange Service Object
        $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)
        
        ## Set Credentials to use two options are availible Option1 to use explict credentials or Option 2 use the Default (logged On) credentials
        
        #Credentials Option 1 using UPN for the windows Account
        #$psCred = Get-Credential
        if ($ModernAuth.IsPresent) {
            Write-Verbose("Using Modern Auth")
            if ([String]::IsNullOrEmpty($ClientId)) {
                $ClientId = "d3590ed6-52b3-4102-aeff-aad2292ab01c"
            }        
            Import-Module ($script:ModuleRoot + "/bin/Microsoft.Identity.Client.dll") -Force    
            if([string]::IsNullOrEmpty($CertificateFilePath)){
                if ($Credentials -eq $null) {                
                    $scope = "https://outlook.office.com/EWS.AccessAsUser.All";
                    $Scopes = New-Object System.Collections.Generic.List[string]
                    $Scopes.Add($Scope)                
                    $pcaConfig = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($ClientId).WithRedirectUri($redirectUri)
                    $token = $pcaConfig.Build().AcquireTokenInteractive($Scopes).WithPrompt([Microsoft.Identity.Client.Prompt]::SelectAccount).WithLoginHint($MailboxName).ExecuteAsync().Result
                    $service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($token.AccessToken)
                }else{
                    $scope = "https://outlook.office.com/EWS.AccessAsUser.All";
                    $Scopes = New-Object System.Collections.Generic.List[string]
                    $Scopes.Add($Scope)                
                    $pcaConfig = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($ClientId).WithAuthority([Microsoft.Identity.Client.AadAuthorityAudience]::AzureAdMultipleOrgs)                
                    $token = $pcaConfig.Build().AcquireTokenByUsernamePassword($Scopes,$Credentials.UserName,$Credentials.Password).ExecuteAsync().Result;
                    $service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($token.AccessToken)
                }
            }
            else{
                $exVal = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
                $certificateObject = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $CertificateFilePath, $CertificatePassword , $exVal
                $domain = $MailboxName.Split("@")[1]
                $Scope = "https://outlook.office365.com/.default"
                $TenantId = (Invoke-WebRequest https://login.windows.net/$domain/v2.0/.well-known/openid-configuration | ConvertFrom-Json).token_endpoint.Split('/')[3]
                $app =  [Microsoft.Identity.Client.ConfidentialClientApplicationBuilder]::Create($ClientId).WithCertificate($certificateObject).WithTenantId($TenantId).Build()
                $Scopes = New-Object System.Collections.Generic.List[string]
                $Scopes.Add($Scope)
                $token = $app.AcquireTokenForClient($Scopes).ExecuteAsync().Result
                $service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.OAuthCredentials($token.AccessToken)
                $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)            
            }
        }
        else {
            Write-Verbose("Using Negotiate Auth")
            if(!$Credentials){$Credentials = Get-Credential}
            $creds = New-Object System.Net.NetworkCredential($Credentials.UserName.ToString(), $Credentials.GetNetworkCredential().password.ToString())
            $service.Credentials = $creds
        }

        #Credentials Option 2
        #service.UseDefaultCredentials = $true
        #$service.TraceEnabled = $true
        ## Choose to ignore any SSL Warning issues caused by Self Signed Certificates
        
        ## Code From http://poshcode.org/624
        ## Create a compilation environment
        $Provider = New-Object Microsoft.CSharp.CSharpCodeProvider
        $Compiler = $Provider.CreateCompiler()
        $Params = New-Object System.CodeDom.Compiler.CompilerParameters
        $Params.GenerateExecutable = $False
        $Params.GenerateInMemory = $True
        $Params.IncludeDebugInformation = $False
        $Params.ReferencedAssemblies.Add("System.DLL") | Out-Null
        
        $TASource = @'
  namespace Local.ToolkitExtensions.Net.CertificatePolicy{
    public class TrustAll : System.Net.ICertificatePolicy {
      public TrustAll() {
      }
      public bool CheckValidationResult(System.Net.ServicePoint sp,
        System.Security.Cryptography.X509Certificates.X509Certificate cert,
        System.Net.WebRequest req, int problem) {
        return true;
      }
    }
  }
'@

        $TAResults = $Provider.CompileAssemblyFromSource($Params, $TASource)
        $TAAssembly = $TAResults.CompiledAssembly
        
        ## We now create an instance of the TrustAll and attach it to the ServicePointManager
        $TrustAll = $TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
        [System.Net.ServicePointManager]::CertificatePolicy = $TrustAll
        
        ## end code from http://poshcode.org/624
        
        ## Set the URL of the CAS (Client Access Server) to use two options are availbe to use Autodiscover to find the CAS URL or Hardcode the CAS to use
        
        #CAS URL Option 1 Autodiscover
        if([string]::IsNullOrEmpty($CertificateFilePath)){
            $service.AutodiscoverUrl($MailboxName, { $true })
        }else{
            $uri=[system.URI] "https://outlook.office365.com/ews/exchange.asmx" 
            $service.Url = $uri 
        }
        #Write-host ("Using CAS Server : " + $Service.url)
        
        #CAS URL Option 2 Hardcoded
        
        #$uri=[system.URI] "https://casservername/ews/exchange.asmx"
        #$service.Url = $uri
        
        ## Optional section for Exchange Impersonation
        
        #$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)
        if (!$service.URL) {
            throw "Error connecting to EWS"
        }
        else {
            return $service
        }
    }
}