[GH-ISSUE #133] Graph authentication fails with HTTP status code 417 in some regions #60

Closed
opened 2026-02-27 20:31:03 +03:00 by kerem · 2 comments
Owner

Originally created by @GruberMarkus on GitHub (Feb 25, 2025).
Original GitHub issue: https://github.com/Set-OutlookSignatures/Set-OutlookSignatures/issues/133

Issue happens in the latest release

  • I confirm that the issue happens in the latest release of Set-OutlookSignatures

Previously solved issues and documentation

  • I have searched through issues, discussions and documentation, but have not found an answer to my issue

Code of Conduct

  • I agree to follow this project's Code of Conduct

What happened?

This only happens in some regions and not consistently within these regions. We are currently only aware that this happens in some regions of Germany, but the problem seems to spread - if you are affected, let us know at set-outlooksignatures@explicitconsulting.at.

While authentication against Graph works fine, the separate authentication against Exchange Online (EXO) fails.


The root cause is not within Set-OutlookSignatures itself, but in Microsoft's infrastructure. Microsoft's servers suddenly randomly incorrectly interpret the HTTP 'Expect' header, returning HTTP error status code 417 instead of a 2xx success code.


Until a new version of Set-OutlookSignatures is released, you can implement the following workaround: In the file 'Set-OutlookSignatures.ps1', search for 'function GraphGetToken'.

Replace the whole function (lines 7089..7584) with the following code:

function GraphGetToken {
    param(
        [switch]$EXO,
        [string]$indent = ''
    )

    try { WatchCatchableExitSignal } catch { }

    if (-not $EXO) {
        Write-Host "$($indent)Graph authentication"

        if ($GraphClientID -ieq 'beea8249-8c98-4c76-92f6-ce3c468a61e6') {
            Write-Host "$($indent)  You use the Entra app provided by the developers. It is recommended to create und use your own Entra app." -ForegroundColor Yellow
            Write-Host "$($indent)    Find a description on how to do this in the file '`.\config\default graph config.ps1`'." -ForegroundColor Yellow
        }
    } else {
        $indent = "$($indent)  "
        Write-Host "$($indent)Graph EXO authentication"
    }

    if ($SimulateAndDeployGraphCredentialFile) {
        Write-Host "$($indent)  Via SimulateAndDeployGraphCredentialFile '$SimulateAndDeployGraphCredentialFile'"

        try {
            try {
                $auth = Import-Clixml -Path $SimulateAndDeployGraphCredentialFile
            } catch {
                Start-Sleep -Seconds 2
                $auth = Import-Clixml -Path $SimulateAndDeployGraphCredentialFile
            }

            $script:AuthorizationToken = $auth.AccessToken

            $script:ExoAuthorizationToken = $auth.AccessTokenExo

            $script:AuthorizationHeader = @{
                Authorization = $auth.AuthHeader
            }

            $script:ExoAuthorizationHeader = @{
                Authorization = $auth.AuthHeaderExo
            }

            $script:AppAuthorizationHeader = @{
                Authorization = $auth.AppAuthHeader
            }

            $script:AppExoAuthorizationHeader = @{
                Authorization = $auth.AppAuthHeaderExo
            }

            return @{
                error             = $false
                AccessToken       = $auth.AccessToken
                AuthHeader        = $auth.authHeader
                AccessTokenExo    = $auth.AccessTokenExo
                AuthHeaderExo     = $auth.AuthHeaderExo
                AppAccessToken    = $auth.AppAccessToken
                AppAuthHeader     = $auth.AppAuthHeader
                AppAccessTokenExo = $auth.AppAccessTokenExo
                AppAuthHeaderExo  = $auth.AppAuthHeaderExo
            }
        } catch {
            return @{
                error             = ($error[0] | Out-String)
                AccessToken       = $null
                AuthHeader        = $null
                AccessTokenExo    = $null
                AuthHeaderExo     = $null
                AppAccessToken    = $null
                AppAuthHeader     = $null
                AppAccessTokenExo = $null
                AppAuthHeaderExo  = $null
            }
        }
    } else {
        if (-not  $script:MsalModulePath) {
            Write-Host "$($indent)  Load MSAL.PS"

            $script:MsalModulePath = (Join-Path -Path $script:tempDir -ChildPath (((New-Guid).guid)))
            Copy-Item -Path ((Join-Path -Path '.' -ChildPath 'bin\MSAL.PS')) -Destination (Join-Path -Path $script:MsalModulePath -ChildPath 'MSAL.PS') -Recurse

            if (-not $IsLinux) {
                Get-ChildItem $script:MsalModulePath -Recurse | Unblock-File
            }

            try { WatchCatchableExitSignal } catch { }

            try {
                Import-Module (Join-Path -Path $script:MsalModulePath -ChildPath 'MSAL.PS') -Force -ErrorAction Stop
            } catch {
                Write-Host $error[0]
                Write-Host "$($indent)    Problem importing MSAL.PS module. Exit." -ForegroundColor Red
                $script:ExitCode = 30
                $script:ExitCodeDescription = 'Problem importing MSAL.PS module.';
                exit
            }
        }

        try { WatchCatchableExitSignal } catch { }

        # On Linux/macOS, unlock keyring/keychain if required
        if (-not [string]::IsNullOrWhitespace($GraphUnlockKeyringKeychainMessageboxText)) {
            if ($IsLinux) {
                $keyringPath = (dbus-send --session --dest=org.freedesktop.secrets --type=method_call --print-reply /org/freedesktop/secrets org.freedesktop.Secret.Service.ReadAlias string:'default' | grep -oP '(?<=object path \")/[^"]+')

                if ($((gdbus call -e -d org.freedesktop.secrets -o $keyringPath -m org.freedesktop.DBus.Properties.Get org.freedesktop.Secret.Collection Locked *>&1) -ine '(<false>,)')) {
                    if ($(Get-Command -Name 'kdialog' -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)) {
                        $null = kdialog `
                            --title $(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' }) `
                            --msgbox "$($GraphUnlockKeyringKeychainMessageboxText)"
                    } elseif ($(Get-Command -Name 'zenity' -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)) {
                        $null = zenity `
                            --info `
                            --title=$(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' }) `
                            --text="$($GraphUnlockKeyringKeychainMessageboxText)"
                    } else {
                        Write-Host "$($indent)  Neither kdialog nor zenity found, so no message box could be shown: $($GraphUnlockKeyringKeychainMessageboxText)"
                    }
                }
            } elseif ($IsMacOS) {
                security unlock-keychain -p 'Set-OutlookSignatures dummy password' *>$null

                if ($LastExitCode -ne 0) {
                    Write-Host $("display alert ""$(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' })"" message ""$($GraphUnlockKeyringKeychainMessageboxText)""  buttons { ""OK"" } default button 1" | osascript *>$1; '')
                }
            }
        }

        try { WatchCatchableExitSignal } catch { }

        try {
            Write-Host "$($indent)  Search for login hint in Graph token cache"

            $script:GraphUser = $null

            $script:msalClientApp = New-MsalClientApplication -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' -AuthenticationBroker | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue

            $script:GraphUser = ($script:msalClientApp | get-msalaccount | Select-Object -First 1).username

            Write-Host "$($indent)    Graph token cache: $($script:msalClientApp.cacheInfo)"
            Write-Host "$($indent)    Result: '$($script:GraphUser)'"
        } catch {
            return @{
                error             = ($error[0] | Out-String)
                AccessToken       = $null
                AuthHeader        = $null
                AccessTokenExo    = $null
                AuthHeaderExo     = $null
                AppAccessToken    = $null
                AppAuthHeader     = $null
                AppAccessTokenExo = $null
                AppAuthHeaderExo  = $null
            }
        }

        try { WatchCatchableExitSignal } catch { }

        # Graph authentication
        Write-Host "$($indent)  Authentication against $(if(-not $EXO) { 'Graph' } else { 'Exchange Online' })"

        try {
            Write-Host "$($indent)    Silent via Integrated Windows Authentication without login hint"

            $script:msalClientApp = New-MsalClientApplication -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue

            $auth = $script:msalClientApp | Get-MsalToken -IntegratedWindowsAuth -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -Timeout (New-TimeSpan -Minutes 1)

            Write-Host "$($indent)      Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'"
        } catch {
            Write-Host "$($indent)      Failed: $($error[0])"

            try { WatchCatchableExitSignal } catch { }

            try {
                Write-Host "$($indent)    Silent via Integrated Windows Authentication with login hint"
                # Required, because IWA without login hint may fail when account enumeration is blocked at OS level

                if (-not ([string]::IsNullOrWhiteSpace($script:GraphUser))) {
                    $script:msalClientApp = New-MsalClientApplication -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue

                    $auth = $script:msalClientApp | Get-MsalToken -IntegratedWindowsAuth -LoginHint $script:GraphUser -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -Timeout (New-TimeSpan -Minutes 1)
                } else {
                    throw 'No login hint found before'
                }

                Write-Host "$($indent)      Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'"
            } catch {
                Write-Host "$($indent)      Failed: $($error[0])"

                try { WatchCatchableExitSignal } catch { }

                try {
                    Write-Host "$($indent)    Silent via Authentication Broker without login hint"

                    $script:msalClientApp = New-MsalClientApplication -AuthenticationBroker -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue

                    $auth = $script:msalClientApp | Get-MsalToken -Silent -AuthenticationBroker -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -ForceRefresh -Timeout (New-TimeSpan -Minutes 1)

                    Write-Host "$($indent)      Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'"
                } catch {
                    Write-Host "$($indent)      Failed: $($error[0])"

                    try { WatchCatchableExitSignal } catch { }

                    try {
                        Write-Host "$($indent)    Silent via Authentication Broker with login hint"

                        if (-not ([string]::IsNullOrWhiteSpace($script:GraphUser))) {
                            $script:msalClientApp = New-MsalClientApplication -AuthenticationBroker -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue

                            $auth = $script:msalClientApp | Get-MsalToken -Silent -AuthenticationBroker -LoginHint $script:GraphUser -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -ForceRefresh -Timeout (New-TimeSpan -Minutes 1)
                        } else {
                            throw 'No login hint found before'
                        }

                        Write-Host "$($indent)      Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'"
                    } catch {
                        Write-Host "$($indent)      Failed: $($error[0])"

                        try {
                            Write-Host "$($indent)    Silent via refresh token, with login hint"

                            if (-not ([string]::IsNullOrWhiteSpace($script:GraphUser))) {
                                $script:msalClientApp = New-MsalClientApplication -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' -RedirectUri 'http://localhost' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue

                                $auth = $script:msalClientApp | Get-MsalToken -Silent -LoginHint $script:GraphUser -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -ForceRefresh -Timeout (New-TimeSpan -Minutes 1)
                            } else {
                                throw 'No login hint found before'
                            }

                            Write-Host "$($indent)      Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'"
                        } catch {
                            Write-Host "$($indent)      Failed: $($error[0])"

                            try { WatchCatchableExitSignal } catch { }

                            # Interactive authentication methods
                            Write-Host "$($indent)    All silent authentication methods failed, switching to interactive authentication methods."

                            if (-not [string]::IsNullOrWhitespace($GraphHtmlMessageboxText)) {
                                if ($IsWindows -and (-not (Test-Path env:SSH_CLIENT))) {
                                    Add-Type -AssemblyName PresentationCore, PresentationFramework, System.Windows.Forms

                                    $window = New-Object System.Windows.Window -Property @{
                                        Width                 = 1
                                        Height                = 1
                                        WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterScreen
                                        ShowActivated         = $false
                                        Topmost               = $true
                                    }

                                    $window.Show()
                                    $window.Hide()

                                    $MessageBoxResult = [System.Windows.MessageBox]::Show($window, "$($GraphHtmlMessageboxText)", $(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' }), [System.Windows.MessageBoxButton]::OKCancel, [System.Windows.MessageBoxImage]::Information, [System.Windows.MessageBoxResult]::None)

                                    $window.Close()

                                    if ($MessageBoxResult -ieq 'Cancel') {
                                        return @{
                                            error             = 'Authentication cancelled by user. Exiting.'
                                            AccessToken       = $null
                                            authHeader        = $null
                                            AccessTokenExo    = $null
                                            authHeaderExo     = $null
                                            AppAccessToken    = $null
                                            AppAuthHeader     = $null
                                            AppAccessTokenExo = $null
                                            AppAuthHeaderExo  = $null
                                        }
                                    }
                                } elseif ($IsLinux -and ((Test-Path env:DISPLAY))) {
                                    if ($(Get-Command -Name 'kdialog' -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)) {
                                        $null = kdialog `
                                            --title $(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' }) `
                                            --msgbox "$($GraphHtmlMessageboxText)"
                                    } elseif ($(Get-Command -Name 'zenity' -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)) {
                                        $null = zenity `
                                            --info `
                                            --title=$(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' }) `
                                            --text="$($GraphHtmlMessageboxText)"
                                    } else {
                                        Write-Host "$($indent)    Neither kdialog nor zenity found, so no message box could be shown: $($GraphHtmlMessageboxText)"
                                    }
                                } elseif ($IsMacOS -and ((Test-Path env:DISPLAY))) {
                                    Write-Host $("display alert ""$(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' })"" message ""$($GraphHtmlMessageboxText)""  buttons { ""OK"" } default button 1" | osascript *>&1; '')
                                }

                                try { WatchCatchableExitSignal } catch { }
                            }

                            $MsalInteractiveParams = @{}

                            if (-not [string]::IsNullOrWhiteSpace($GraphBrowserRedirectSuccess)) {
                                $MsalInteractiveParams.BrowserRedirectSuccess = $GraphBrowserRedirectSuccess
                            }

                            if (-not [string]::IsNullOrWhiteSpace($GraphBrowserRedirectError)) {
                                $MsalInteractiveParams.BrowserRedirectError = $GraphBrowserRedirectError
                            }

                            if (-not [string]::IsNullOrWhiteSpace($GraphHtmlMessageSuccess)) {
                                $MsalInteractiveParams.HtmlMessageSuccess = $GraphHtmlMessageSuccess
                            }

                            if (-not [string]::IsNullOrWhiteSpace($GraphHtmlMessageError)) {
                                $MsalInteractiveParams.HtmlMessageError = $GraphHtmlMessageError
                            }

                            try { WatchCatchableExitSignal } catch { }

                            try {
                                Write-Host "$($indent)    Interactive via Authentication Broker"

                                if (-not $IsWindows) {
                                    throw 'Interactive with Authentication Broker on Linux/macOS only works in the console. Browser is preferred for better user experience.'
                                }

                                $script:msalClientApp = New-MsalClientApplication -AuthenticationBroker -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue

                                Write-Host "$($indent)      Opening authentication broker window and waiting for you to authenticate. Stopping script execution after five minutes."
                                $auth = $script:msalClientApp | Get-MsalToken -Interactive -AuthenticationBroker -LoginHint $(if ($script:GraphUser) { $script:GraphUser } else { '' }) -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -Timeout (New-TimeSpan -Minutes 5) -Prompt 'NoPrompt' -UseEmbeddedWebView:$false @MsalInteractiveParams

                                Write-Host "$($indent)      Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'"
                            } catch {
                                Write-Host "$($indent)      Failed: $($error[0])"

                                try {
                                    Write-Host "$($indent)    Interactive via browser"

                                    $script:msalClientApp = New-MsalClientApplication -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' -RedirectUri 'http://localhost' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue

                                    Write-Host "$($indent)      Opening new browser window and waiting for you to authenticate. Stopping script execution after five minutes."
                                    $auth = $script:msalClientApp | Get-MsalToken -Interactive -LoginHint $(if ($script:GraphUser) { $script:GraphUser } else { '' }) -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -Timeout (New-TimeSpan -Minutes 5) -Prompt 'NoPrompt' -UseEmbeddedWebView:$false @MsalInteractiveParams

                                    Write-Host "$($indent)      Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'"
                                } catch {
                                    Write-Host "$($indent)      Failed: $($error[0])"
                                    Write-Host '$($indent)    No authentication possible'

                                    $auth = $null

                                    return @{
                                        error             = (($error[0] | Out-String) + @"
No authentication possible.
1. Did you follow the Quick Start Guide in '.\docs\README' and configure the Entra ID app correctly?
2. Run Set-OutlookSignatures with the "-Verbose" parameter and check for authentication messages
3. If the "Interactive" message is displayed:
   - When using an Authentication Broker (which is preferred on supported platforms):
     - Does the account picker window show up?
     - Check if authentication happens within five minutes
     - Check if your firewall or anti-malware software blocks Set-OutlookSignatures from creating a temporary listener port for localhost.
     - Check if the correct user account is selected/entered and if the authentication is successful
   - When not using an Authentication Broker (on a system without support for it, or when broker auth failed):
     - Does a browser (the system default browser, if configured) open and ask for authentication?
      - Yes:
       - Check if authentication happens within five minutes
       - Ensure that your browser does not block access to 'http://localhost', errors such as 'connection refused' point to this problem. ('https://localhost' is currently not technically feasible, see 'https://learn.microsoft.com/en-us/entra/msal/dotnet/acquiring-tokens/using-web-browsers' and 'https://learn.microsoft.com/en-us/entra/msal/dotnet/acquiring-tokens/using-web-browsers' for details)
         This is typically due to enforced redirection to HTTPS being applied to localhost. If not configured via policies: edge://net-internals/#hsts or chrome://net-internals/#hsts, delete domain security policies for localhost.
       - Check if your firewall or anti-malware software blocks Set-OutlookSignatures from creating a temporary listener port for localhost.
       - Check if the correct user account is selected/entered and if the authentication is successful
     - No:
       - Check if a default browser is set and if the PowerShell command 'start https://github.com/Set-OutlookSignatures/Set-OutlookSignatures' opens it
       - Make sure that Set-OutlookSignatures is executed in the security context of the currently logged-in user
       - Run Set-OutlookSignatures in a new PowerShell session
       - Check your anti-malware configuration (errors such as 'error sending the request' or 'connection refused' point at a problem there)
       - Make sure that the current PowerShell session allows TLS 1.2+ (see https://github.com/Set-OutlookSignatures/Set-OutlookSignatures/issues/85 for details)
4. Delete the Graph token cache: $($script:msalClientApp.cacheInfo).
"@)
                                        AccessToken       = $null
                                        AuthHeader        = $null
                                        AccessTokenExo    = $null
                                        AuthHeaderExo     = $null
                                        AppAccessToken    = $null
                                        AppAuthHeader     = $null
                                        AppAccessTokenExo = $null
                                        AppAuthHeaderExo  = $null
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        if ($auth) {
            try {
                $script:GraphUser = $auth.account.username

                if (-not $EXO) {
                    $script:AuthorizationHeader = @{
                        Authorization = $auth.CreateAuthorizationHeader()
                    }

                    $script:AuthorizationToken = $auth.AccessToken
                } else {
                    $script:ExoAuthorizationHeader = @{
                        Authorization = $auth.CreateAuthorizationHeader()
                    }

                    $script:ExoAuthorizationToken = $auth.AccessToken
                }

                if (-not $EXO) {
                    $authExo = GraphGetToken -EXO -indent $indent

                    if ($authExo -and ($authExo.error -eq $false)) {
                        return @{
                            error             = $false
                            AccessToken       = $script:AuthorizationToken
                            AuthHeader        = $script:AuthorizationHeader
                            AccessTokenExo    = $script:ExoAuthorizationToken
                            AuthHeaderExo     = $script:ExoAuthorizationHeader
                            AppAccessToken    = $null
                            AppAuthHeader     = $null
                            AppAccessTokenExo = $null
                            AppAuthHeaderExo  = $null
                        }
                    } else {
                        if ($authExo -and ($authExo.error -ne $false)) {
                            throw "No Exchange Online token: $($authExo.error)"
                        } else {
                            throw 'No Exchange Online token'
                        }
                    }
                } else {
                    return @{
                        error             = $false
                        AccessToken       = $null
                        AuthHeader        = $null
                        AccessTokenExo    = $auth.AccessToken
                        AuthHeaderExo     = $script:ExoAuthorizationHeader
                        AppAccessToken    = $null
                        AppAuthHeader     = $null
                        AppAccessTokenExo = $null
                        AppAuthHeaderExo  = $null
                    }
                }
            } catch {
                Write-Host "$($indent)  Error: $($error[0])"

                return @{
                    error             = ($error[0] | Out-String)
                    AccessToken       = $null
                    authHeader        = $null
                    AccessTokenExo    = $null
                    authHeaderExo     = $null
                    AppAccessToken    = $null
                    AppAuthHeader     = $null
                    AppAccessTokenExo = $null
                    AppAuthHeaderExo  = $null
                }
            }
        }
    }
}

The next release of Set-OutlookSignatures will include this fix or an updated version of it.

Originally created by @GruberMarkus on GitHub (Feb 25, 2025). Original GitHub issue: https://github.com/Set-OutlookSignatures/Set-OutlookSignatures/issues/133 ### Issue happens in the latest release - [x] I confirm that the issue happens in the latest release of Set-OutlookSignatures ### Previously solved issues and documentation - [x] I have searched through issues, discussions and documentation, but have not found an answer to my issue ### Code of Conduct - [x] I agree to follow this project's Code of Conduct ### What happened? This only happens in some regions and not consistently within these regions. We are currently only aware that this happens in some regions of Germany, but the problem seems to spread - if you are affected, let us know at set-outlooksignatures@explicitconsulting.at. While authentication against Graph works fine, the separate authentication against Exchange Online (EXO) fails. <br> The root cause is not within Set-OutlookSignatures itself, but in Microsoft's infrastructure. Microsoft's servers suddenly randomly incorrectly interpret the HTTP 'Expect' header, returning HTTP error status code 417 instead of a 2xx success code. <br> Until a new version of Set-OutlookSignatures is released, you can implement the following workaround: In the file '`Set-OutlookSignatures.ps1`', search for '`function GraphGetToken`'. Replace the whole function (lines 7089..7584) with the following code: ``` function GraphGetToken { param( [switch]$EXO, [string]$indent = '' ) try { WatchCatchableExitSignal } catch { } if (-not $EXO) { Write-Host "$($indent)Graph authentication" if ($GraphClientID -ieq 'beea8249-8c98-4c76-92f6-ce3c468a61e6') { Write-Host "$($indent) You use the Entra app provided by the developers. It is recommended to create und use your own Entra app." -ForegroundColor Yellow Write-Host "$($indent) Find a description on how to do this in the file '`.\config\default graph config.ps1`'." -ForegroundColor Yellow } } else { $indent = "$($indent) " Write-Host "$($indent)Graph EXO authentication" } if ($SimulateAndDeployGraphCredentialFile) { Write-Host "$($indent) Via SimulateAndDeployGraphCredentialFile '$SimulateAndDeployGraphCredentialFile'" try { try { $auth = Import-Clixml -Path $SimulateAndDeployGraphCredentialFile } catch { Start-Sleep -Seconds 2 $auth = Import-Clixml -Path $SimulateAndDeployGraphCredentialFile } $script:AuthorizationToken = $auth.AccessToken $script:ExoAuthorizationToken = $auth.AccessTokenExo $script:AuthorizationHeader = @{ Authorization = $auth.AuthHeader } $script:ExoAuthorizationHeader = @{ Authorization = $auth.AuthHeaderExo } $script:AppAuthorizationHeader = @{ Authorization = $auth.AppAuthHeader } $script:AppExoAuthorizationHeader = @{ Authorization = $auth.AppAuthHeaderExo } return @{ error = $false AccessToken = $auth.AccessToken AuthHeader = $auth.authHeader AccessTokenExo = $auth.AccessTokenExo AuthHeaderExo = $auth.AuthHeaderExo AppAccessToken = $auth.AppAccessToken AppAuthHeader = $auth.AppAuthHeader AppAccessTokenExo = $auth.AppAccessTokenExo AppAuthHeaderExo = $auth.AppAuthHeaderExo } } catch { return @{ error = ($error[0] | Out-String) AccessToken = $null AuthHeader = $null AccessTokenExo = $null AuthHeaderExo = $null AppAccessToken = $null AppAuthHeader = $null AppAccessTokenExo = $null AppAuthHeaderExo = $null } } } else { if (-not $script:MsalModulePath) { Write-Host "$($indent) Load MSAL.PS" $script:MsalModulePath = (Join-Path -Path $script:tempDir -ChildPath (((New-Guid).guid))) Copy-Item -Path ((Join-Path -Path '.' -ChildPath 'bin\MSAL.PS')) -Destination (Join-Path -Path $script:MsalModulePath -ChildPath 'MSAL.PS') -Recurse if (-not $IsLinux) { Get-ChildItem $script:MsalModulePath -Recurse | Unblock-File } try { WatchCatchableExitSignal } catch { } try { Import-Module (Join-Path -Path $script:MsalModulePath -ChildPath 'MSAL.PS') -Force -ErrorAction Stop } catch { Write-Host $error[0] Write-Host "$($indent) Problem importing MSAL.PS module. Exit." -ForegroundColor Red $script:ExitCode = 30 $script:ExitCodeDescription = 'Problem importing MSAL.PS module.'; exit } } try { WatchCatchableExitSignal } catch { } # On Linux/macOS, unlock keyring/keychain if required if (-not [string]::IsNullOrWhitespace($GraphUnlockKeyringKeychainMessageboxText)) { if ($IsLinux) { $keyringPath = (dbus-send --session --dest=org.freedesktop.secrets --type=method_call --print-reply /org/freedesktop/secrets org.freedesktop.Secret.Service.ReadAlias string:'default' | grep -oP '(?<=object path \")/[^"]+') if ($((gdbus call -e -d org.freedesktop.secrets -o $keyringPath -m org.freedesktop.DBus.Properties.Get org.freedesktop.Secret.Collection Locked *>&1) -ine '(<false>,)')) { if ($(Get-Command -Name 'kdialog' -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)) { $null = kdialog ` --title $(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' }) ` --msgbox "$($GraphUnlockKeyringKeychainMessageboxText)" } elseif ($(Get-Command -Name 'zenity' -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)) { $null = zenity ` --info ` --title=$(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' }) ` --text="$($GraphUnlockKeyringKeychainMessageboxText)" } else { Write-Host "$($indent) Neither kdialog nor zenity found, so no message box could be shown: $($GraphUnlockKeyringKeychainMessageboxText)" } } } elseif ($IsMacOS) { security unlock-keychain -p 'Set-OutlookSignatures dummy password' *>$null if ($LastExitCode -ne 0) { Write-Host $("display alert ""$(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' })"" message ""$($GraphUnlockKeyringKeychainMessageboxText)"" buttons { ""OK"" } default button 1" | osascript *>$1; '') } } } try { WatchCatchableExitSignal } catch { } try { Write-Host "$($indent) Search for login hint in Graph token cache" $script:GraphUser = $null $script:msalClientApp = New-MsalClientApplication -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' -AuthenticationBroker | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue $script:GraphUser = ($script:msalClientApp | get-msalaccount | Select-Object -First 1).username Write-Host "$($indent) Graph token cache: $($script:msalClientApp.cacheInfo)" Write-Host "$($indent) Result: '$($script:GraphUser)'" } catch { return @{ error = ($error[0] | Out-String) AccessToken = $null AuthHeader = $null AccessTokenExo = $null AuthHeaderExo = $null AppAccessToken = $null AppAuthHeader = $null AppAccessTokenExo = $null AppAuthHeaderExo = $null } } try { WatchCatchableExitSignal } catch { } # Graph authentication Write-Host "$($indent) Authentication against $(if(-not $EXO) { 'Graph' } else { 'Exchange Online' })" try { Write-Host "$($indent) Silent via Integrated Windows Authentication without login hint" $script:msalClientApp = New-MsalClientApplication -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue $auth = $script:msalClientApp | Get-MsalToken -IntegratedWindowsAuth -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -Timeout (New-TimeSpan -Minutes 1) Write-Host "$($indent) Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'" } catch { Write-Host "$($indent) Failed: $($error[0])" try { WatchCatchableExitSignal } catch { } try { Write-Host "$($indent) Silent via Integrated Windows Authentication with login hint" # Required, because IWA without login hint may fail when account enumeration is blocked at OS level if (-not ([string]::IsNullOrWhiteSpace($script:GraphUser))) { $script:msalClientApp = New-MsalClientApplication -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue $auth = $script:msalClientApp | Get-MsalToken -IntegratedWindowsAuth -LoginHint $script:GraphUser -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -Timeout (New-TimeSpan -Minutes 1) } else { throw 'No login hint found before' } Write-Host "$($indent) Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'" } catch { Write-Host "$($indent) Failed: $($error[0])" try { WatchCatchableExitSignal } catch { } try { Write-Host "$($indent) Silent via Authentication Broker without login hint" $script:msalClientApp = New-MsalClientApplication -AuthenticationBroker -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue $auth = $script:msalClientApp | Get-MsalToken -Silent -AuthenticationBroker -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -ForceRefresh -Timeout (New-TimeSpan -Minutes 1) Write-Host "$($indent) Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'" } catch { Write-Host "$($indent) Failed: $($error[0])" try { WatchCatchableExitSignal } catch { } try { Write-Host "$($indent) Silent via Authentication Broker with login hint" if (-not ([string]::IsNullOrWhiteSpace($script:GraphUser))) { $script:msalClientApp = New-MsalClientApplication -AuthenticationBroker -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue $auth = $script:msalClientApp | Get-MsalToken -Silent -AuthenticationBroker -LoginHint $script:GraphUser -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -ForceRefresh -Timeout (New-TimeSpan -Minutes 1) } else { throw 'No login hint found before' } Write-Host "$($indent) Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'" } catch { Write-Host "$($indent) Failed: $($error[0])" try { Write-Host "$($indent) Silent via refresh token, with login hint" if (-not ([string]::IsNullOrWhiteSpace($script:GraphUser))) { $script:msalClientApp = New-MsalClientApplication -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' -RedirectUri 'http://localhost' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue $auth = $script:msalClientApp | Get-MsalToken -Silent -LoginHint $script:GraphUser -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -ForceRefresh -Timeout (New-TimeSpan -Minutes 1) } else { throw 'No login hint found before' } Write-Host "$($indent) Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'" } catch { Write-Host "$($indent) Failed: $($error[0])" try { WatchCatchableExitSignal } catch { } # Interactive authentication methods Write-Host "$($indent) All silent authentication methods failed, switching to interactive authentication methods." if (-not [string]::IsNullOrWhitespace($GraphHtmlMessageboxText)) { if ($IsWindows -and (-not (Test-Path env:SSH_CLIENT))) { Add-Type -AssemblyName PresentationCore, PresentationFramework, System.Windows.Forms $window = New-Object System.Windows.Window -Property @{ Width = 1 Height = 1 WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterScreen ShowActivated = $false Topmost = $true } $window.Show() $window.Hide() $MessageBoxResult = [System.Windows.MessageBox]::Show($window, "$($GraphHtmlMessageboxText)", $(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' }), [System.Windows.MessageBoxButton]::OKCancel, [System.Windows.MessageBoxImage]::Information, [System.Windows.MessageBoxResult]::None) $window.Close() if ($MessageBoxResult -ieq 'Cancel') { return @{ error = 'Authentication cancelled by user. Exiting.' AccessToken = $null authHeader = $null AccessTokenExo = $null authHeaderExo = $null AppAccessToken = $null AppAuthHeader = $null AppAccessTokenExo = $null AppAuthHeaderExo = $null } } } elseif ($IsLinux -and ((Test-Path env:DISPLAY))) { if ($(Get-Command -Name 'kdialog' -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)) { $null = kdialog ` --title $(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' }) ` --msgbox "$($GraphHtmlMessageboxText)" } elseif ($(Get-Command -Name 'zenity' -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)) { $null = zenity ` --info ` --title=$(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' }) ` --text="$($GraphHtmlMessageboxText)" } else { Write-Host "$($indent) Neither kdialog nor zenity found, so no message box could be shown: $($GraphHtmlMessageboxText)" } } elseif ($IsMacOS -and ((Test-Path env:DISPLAY))) { Write-Host $("display alert ""$(if ($BenefactorCircleLicenseFile) { 'Set-OutlookSignatures Benefactor Circle' } else { 'Set-OutlookSignatures' })"" message ""$($GraphHtmlMessageboxText)"" buttons { ""OK"" } default button 1" | osascript *>&1; '') } try { WatchCatchableExitSignal } catch { } } $MsalInteractiveParams = @{} if (-not [string]::IsNullOrWhiteSpace($GraphBrowserRedirectSuccess)) { $MsalInteractiveParams.BrowserRedirectSuccess = $GraphBrowserRedirectSuccess } if (-not [string]::IsNullOrWhiteSpace($GraphBrowserRedirectError)) { $MsalInteractiveParams.BrowserRedirectError = $GraphBrowserRedirectError } if (-not [string]::IsNullOrWhiteSpace($GraphHtmlMessageSuccess)) { $MsalInteractiveParams.HtmlMessageSuccess = $GraphHtmlMessageSuccess } if (-not [string]::IsNullOrWhiteSpace($GraphHtmlMessageError)) { $MsalInteractiveParams.HtmlMessageError = $GraphHtmlMessageError } try { WatchCatchableExitSignal } catch { } try { Write-Host "$($indent) Interactive via Authentication Broker" if (-not $IsWindows) { throw 'Interactive with Authentication Broker on Linux/macOS only works in the console. Browser is preferred for better user experience.' } $script:msalClientApp = New-MsalClientApplication -AuthenticationBroker -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue Write-Host "$($indent) Opening authentication broker window and waiting for you to authenticate. Stopping script execution after five minutes." $auth = $script:msalClientApp | Get-MsalToken -Interactive -AuthenticationBroker -LoginHint $(if ($script:GraphUser) { $script:GraphUser } else { '' }) -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -Timeout (New-TimeSpan -Minutes 5) -Prompt 'NoPrompt' -UseEmbeddedWebView:$false @MsalInteractiveParams Write-Host "$($indent) Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'" } catch { Write-Host "$($indent) Failed: $($error[0])" try { Write-Host "$($indent) Interactive via browser" $script:msalClientApp = New-MsalClientApplication -ClientId $GraphClientID -AzureCloudInstance $CloudEnvironmentEnvironmentName -TenantId 'organizations' -RedirectUri 'http://localhost' | Enable-MsalTokenCacheOnDisk -PassThru -WarningAction SilentlyContinue Write-Host "$($indent) Opening new browser window and waiting for you to authenticate. Stopping script execution after five minutes." $auth = $script:msalClientApp | Get-MsalToken -Interactive -LoginHint $(if ($script:GraphUser) { $script:GraphUser } else { '' }) -AzureCloudInstance $CloudEnvironmentEnvironmentName -Scopes $(if (-not $EXO) { "$($CloudEnvironmentGraphApiEndpoint)/.default" }else { "$($CloudEnvironmentExchangeOnlineEndpoint)/.default" }) -Timeout (New-TimeSpan -Minutes 5) -Prompt 'NoPrompt' -UseEmbeddedWebView:$false @MsalInteractiveParams Write-Host "$($indent) Success: '$(($script:msalClientApp | get-msalaccount | Select-Object -First 1).username)'" } catch { Write-Host "$($indent) Failed: $($error[0])" Write-Host '$($indent) No authentication possible' $auth = $null return @{ error = (($error[0] | Out-String) + @" No authentication possible. 1. Did you follow the Quick Start Guide in '.\docs\README' and configure the Entra ID app correctly? 2. Run Set-OutlookSignatures with the "-Verbose" parameter and check for authentication messages 3. If the "Interactive" message is displayed: - When using an Authentication Broker (which is preferred on supported platforms): - Does the account picker window show up? - Check if authentication happens within five minutes - Check if your firewall or anti-malware software blocks Set-OutlookSignatures from creating a temporary listener port for localhost. - Check if the correct user account is selected/entered and if the authentication is successful - When not using an Authentication Broker (on a system without support for it, or when broker auth failed): - Does a browser (the system default browser, if configured) open and ask for authentication? - Yes: - Check if authentication happens within five minutes - Ensure that your browser does not block access to 'http://localhost', errors such as 'connection refused' point to this problem. ('https://localhost' is currently not technically feasible, see 'https://learn.microsoft.com/en-us/entra/msal/dotnet/acquiring-tokens/using-web-browsers' and 'https://learn.microsoft.com/en-us/entra/msal/dotnet/acquiring-tokens/using-web-browsers' for details) This is typically due to enforced redirection to HTTPS being applied to localhost. If not configured via policies: edge://net-internals/#hsts or chrome://net-internals/#hsts, delete domain security policies for localhost. - Check if your firewall or anti-malware software blocks Set-OutlookSignatures from creating a temporary listener port for localhost. - Check if the correct user account is selected/entered and if the authentication is successful - No: - Check if a default browser is set and if the PowerShell command 'start https://github.com/Set-OutlookSignatures/Set-OutlookSignatures' opens it - Make sure that Set-OutlookSignatures is executed in the security context of the currently logged-in user - Run Set-OutlookSignatures in a new PowerShell session - Check your anti-malware configuration (errors such as 'error sending the request' or 'connection refused' point at a problem there) - Make sure that the current PowerShell session allows TLS 1.2+ (see https://github.com/Set-OutlookSignatures/Set-OutlookSignatures/issues/85 for details) 4. Delete the Graph token cache: $($script:msalClientApp.cacheInfo). "@) AccessToken = $null AuthHeader = $null AccessTokenExo = $null AuthHeaderExo = $null AppAccessToken = $null AppAuthHeader = $null AppAccessTokenExo = $null AppAuthHeaderExo = $null } } } } } } } } if ($auth) { try { $script:GraphUser = $auth.account.username if (-not $EXO) { $script:AuthorizationHeader = @{ Authorization = $auth.CreateAuthorizationHeader() } $script:AuthorizationToken = $auth.AccessToken } else { $script:ExoAuthorizationHeader = @{ Authorization = $auth.CreateAuthorizationHeader() } $script:ExoAuthorizationToken = $auth.AccessToken } if (-not $EXO) { $authExo = GraphGetToken -EXO -indent $indent if ($authExo -and ($authExo.error -eq $false)) { return @{ error = $false AccessToken = $script:AuthorizationToken AuthHeader = $script:AuthorizationHeader AccessTokenExo = $script:ExoAuthorizationToken AuthHeaderExo = $script:ExoAuthorizationHeader AppAccessToken = $null AppAuthHeader = $null AppAccessTokenExo = $null AppAuthHeaderExo = $null } } else { if ($authExo -and ($authExo.error -ne $false)) { throw "No Exchange Online token: $($authExo.error)" } else { throw 'No Exchange Online token' } } } else { return @{ error = $false AccessToken = $null AuthHeader = $null AccessTokenExo = $auth.AccessToken AuthHeaderExo = $script:ExoAuthorizationHeader AppAccessToken = $null AppAuthHeader = $null AppAccessTokenExo = $null AppAuthHeaderExo = $null } } } catch { Write-Host "$($indent) Error: $($error[0])" return @{ error = ($error[0] | Out-String) AccessToken = $null authHeader = $null AccessTokenExo = $null authHeaderExo = $null AppAccessToken = $null AppAuthHeader = $null AppAccessTokenExo = $null AppAuthHeaderExo = $null } } } } } ``` The next release of Set-OutlookSignatures will include this fix or an updated version of it.
kerem closed this issue 2026-02-27 20:31:03 +03:00
Author
Owner

@GruberMarkus commented on GitHub (Feb 28, 2025):

See updated function in the first posting (https://github.com/Set-OutlookSignatures/Set-OutlookSignatures/issues/133#issue-2877725178).

<!-- gh-comment-id:2691168968 --> @GruberMarkus commented on GitHub (Feb 28, 2025): See updated function in the first posting (https://github.com/Set-OutlookSignatures/Set-OutlookSignatures/issues/133#issue-2877725178).
Author
Owner

@GruberMarkus commented on GitHub (Mar 6, 2025):

Resolved in release v4.18.0, closing issue.

<!-- gh-comment-id:2704346455 --> @GruberMarkus commented on GitHub (Mar 6, 2025): Resolved in release v4.18.0, closing issue.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/Set-OutlookSignatures-Set-OutlookSignatures#60
No description provided.