High Volume Email - Send email Oauth

Lorenzo Cavagna 0 Reputation points
2025-01-20T16:11:01.92+00:00

Hello,

Based on this documentation: https://learn.microsoft.com/en-us/exchange/mail-flow-best-practices/high-volume-mails-m365

I'm trying to connect and send email using Oauth authentication using certificate, as explained here: https://learn.microsoft.com/en-us/exchange/mail-flow-best-practices/oauth-high-volume-mails-m365

The code to retreive the JWT token to authenticate is retreived with:

#Authenticate on Exchange to Send Email
$tenantIdEXO = ""
$appIdEXO = ""
$thumbprintEXO = ""
$resourceEXO = "https://outlook.office.com/.default"
$authUrlEXO = "https://login.microsoftonline.com/$tenantIdEXO/oauth2/token"

# Create a certificate object
$certEXO = Get-Item -Path Cert:\CurrentUser\My\$thumbprintEXO

function Get-AccessTokenEXO {
    # Construct the JWT token
    $currentTimeEXO = [System.DateTime]::UtcNow
    $expiryTimeEXO = $currentTimeEXO.AddMinutes(60)  # Token valid for 1 hour
    $jwtHeaderEXO = @{
        alg = "RS256"
        typ = "JWT"
        x5t = [System.Convert]::ToBase64String($certEXO.GetCertHash())
    }
    $jwtPayloadEXO = @{
        iss = $appIdEXO
        sub = $appIdEXO
        aud = $authUrlEXO
        nbf = [System.Math]::Floor($currentTimeEXO.Subtract((Get-Date "1970-01-01 00:00:00").ToUniversalTime()).TotalSeconds)
        exp = [System.Math]::Floor($expiryTimeEXO.Subtract((Get-Date "1970-01-01 00:00:00").ToUniversalTime()).TotalSeconds)
    }
    $jwtHeaderBase64EXO = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(($jwtHeaderEXO | ConvertTo-Json)))
    $jwtPayloadBase64EXO = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(($jwtPayloadEXO | ConvertTo-Json)))
    $signatureInputEXO = "$jwtHeaderBase64EXO.$jwtPayloadBase64EXO"
    $rsaEXO = $certEXO.PrivateKey
    $signatureBytesEXO = $rsaEXO.SignData([System.Text.Encoding]::UTF8.GetBytes($signatureInputEXO), [System.Security.Cryptography.HashAlgorithmName]::SHA256, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1)
    $jwtSignatureBase64EXO = [System.Convert]::ToBase64String($signatureBytesEXO)
    $jwtTokenEXO = "$jwtHeaderBase64EXO.$jwtPayloadBase64EXO.$jwtSignatureBase64EXO"

    # Construct the token request payload
    $tokenRequestEXO = @{
        client_id = $appIdEXO
        scope = $resourceEXO
        client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
        client_assertion = $jwtTokenEXO
        grant_type = "client_credentials"
    }

    # Send a POST request to Azure AD to obtain the access token
    $responseEXO = Invoke-RestMethod -Uri $authUrlEXO -Method Post -ContentType "application/x-www-form-urlencoded" -Body $tokenRequestEXO

    # Extract the access token and expiry time
    $global:accessTokenEXO = $responseEXO.access_token
    $global:tokenExpiryTimeEXO = $currentTimeEXO.AddSeconds($responseEXO.expires_in)
}

function Get-ValidAccessTokenEXO {
    $currentTimeEXO = [System.DateTime]::UtcNow
    if ($null -eq $global:accessTokenEXO -or $currentTimeEXO -ge $global:tokenExpiryTimeEXO) {
        Get-AccessTokenEXO
    }
}

# Initial token retrieval
Get-AccessTokenEXO

And the token is retreived successfully using App Registration. The issue comes when I try to send an email. I'm trying to use this documentation: https://blog.icewolf.ch/archive/2022/12/20/exchange-online-other-ways-of-testing-imap-oauth2-client-credential/ (for SMTP instead) but I receive:
Exception calling "AuthenticateAsClient" with "4" argument(s): "Cannot determine the frame size or a corrupted frame was received."

I want to securely send Internal email using HVE, but I lost after these errors.

Microsoft Exchange Online
Exchange Server Development
Exchange Server Development
Exchange Server: A family of Microsoft client/server messaging and collaboration software.Development: The process of researching, productizing, and refining new or existing technologies.
564 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.