Search code examples
powershellmicrosoft-graph-apiazure-automation

Powershell script with automation account and managed identity Unauthorized when sending e-mail


I have been struggling with this script in Azure Automation to send a report to an e-mail but won't work. I have granted the required permission to the servicePrincipal but I get all the time The remote server returned an error: (401) Unauthorized. I even tried to connect with the scopes, but still the same. Then I tried to connect to AzAccount then get the AzAccessToken and then connect to graph using AccessToken but here I got an error

Connect-MgGraph : Cannot bind parameter 'AccessToken'. Cannot convert the "eyJ0
 value of type "System.String" to type "System.Security.SecureString". At line:5 char:30 + Connect-MgGraph -AccessToken $token.Token +

I am getting the output of the variables $inactiveUsers and $htmlReport so the issue is with the e-mail

See the permissions: enter image description here What am I doing wrong ?

# Connect to Microsoft Graph
Connect-MgGraph -Identity

# inactive users with license(s)
$inactiveUsers = Get-MgUser -Filter 'accountEnabled eq false and assignedLicenses/$count ne 0' -ConsistencyLevel eventual -CountVariable licensedUserCount -All -Select UserPrincipalName,DisplayName

# Create a report variable
$userReport = @()

# Build the report
$htmlReport = "<html><body><h2>Disabled users with licenses report</h2><table border='1'><tr><th>User Principal Name</th><th>Display Name</th></tr>"

foreach ($user in $inactiveUsers) {
    $userPrincipalName = $user.UserPrincipalName
    $displayName = $user.DisplayName

    $htmlReport += "<tr><td>$userPrincipalName</td><td>$displayName</td></tr>"

    $userInfo = [PSCustomObject]@{
        UserPrincipalName = $userPrincipalName
        DisplayName = $displayName
    }

    $userReport += $userInfo
}

$htmlReport += "</table></body></html>"

# Send the email
$recipientEmail = "[email protected]"
$subject = "Disabled users with licenses report"

# Construct the email
$emailMessage = @{
    "subject" = $subject
    "body" = @{
        "contentType" = "HTML"
        "content" = $htmlReport
    }
    "toRecipients" = @(@{ "emailAddress" = @{ "address" = $recipientEmail } })
}

# Convert to JSON
$emailJson = $emailMessage | ConvertTo-Json

# Send the email, this part is  not working and I don't know why...
$sendEmailUri = "https://graph.microsoft.com/v1.0/users/[email protected]/sendMail"
$sendEmailParams = @{
    "Uri" = $sendEmailUri
    "Method" = 'POST'
    "Body" = $emailJson
    "Headers" = @{
        "Content-Type" = "application/json"
    }
}

try {
    Invoke-RestMethod @sendEmailParams -ErrorAction Stop
    Write-Host "Email sent successfully."
} catch {
    Write-Error "Error sending email: $_"
}

Solution

  • The error occurred as you are calling Invoke-RestMethod without passing access token as a secure string (ConvertTo-SecureString $graphToken -AsPlainText -Force) in Authorization header.

    To resolve the error, you need to either pass access token as secure string or use Send-MgUserMail as @user2250152 suggested.

    Initially, I granted below permissions to the automation account's service principal like this:

    enter image description here

    Now, I ran below modified script by replacing with Send-MgUserMail and got response:

    Import-Module Microsoft.Graph.Authentication
    Import-Module Microsoft.Graph.Users
    Import-Module Microsoft.Graph.Users.Actions
    
    # Connect to Microsoft Graph
    Connect-MgGraph -Identity
    
    # inactive users with license(s)
    $inactiveUsers = Get-MgUser -Filter 'accountEnabled eq false and assignedLicenses/$count ne 0' -ConsistencyLevel eventual -CountVariable licensedUserCount -All -Select UserPrincipalName,DisplayName
    
    # Create a report variable
    $userReport = @()
    
    # Build the report
    $htmlReport = "<html><body><h2>Disabled users with licenses report</h2><table border='1'><tr><th>User Principal Name</th><th>Display Name</th></tr>"
    
    foreach ($user in $inactiveUsers) {
        $userPrincipalName = $user.UserPrincipalName
        $displayName = $user.DisplayName
    
        $htmlReport += "<tr><td>$userPrincipalName</td><td>$displayName</td></tr>"
    
        $userInfo = [PSCustomObject]@{
            UserPrincipalName = $userPrincipalName
            DisplayName = $displayName
        }
    
        $userReport += $userInfo
    }
    
    $htmlReport += "</table></body></html>"
    
    # Send the email
    $recipientEmail = "[email protected]"
    $subject = "Disabled users with licenses report"
    
    # Construct the email message
    $emailMessage = @{
        "Message" = @{
            "subject" = $subject
            "body" = @{
                "contentType" = "HTML"
                "content" = $htmlReport
            }
            "toRecipients" = @(@{ "emailAddress" = @{ "address" = $recipientEmail } })
        }
        "saveToSentItems" = $true 
    }
    
    # Convert to JSON with a higher depth limit
    $emailJson = $emailMessage | ConvertTo-Json -Depth 5
    
    try {
        Send-MgUserMail -UserId "[email protected]" -BodyParameter $emailJson 
        Write-Output "Email sent successfully."
    }
    catch {
        Write-Error "Error sending email: $_"
    }
    

    Response:

    enter image description here

    To confirm that, I checked the same in user's Sent Items where mail sent successfully like this:

    enter image description here