skip to Main Content

hope you are doing good.

I’m trying to use Graph API – Mail module, to send mail Windows PowerShell(not wanted to use SMTP).
But I’m stuck, getting Error 400 – Bad Request Error for the following script.

Able to fetch the access token, getting error at Invoke-RestMethod.

API permission is given, – Mail.Send, Mail.ReadWrite (Delegated).
Using Administrator Account – Azure
Running Script from Local Windows PowerShell.

Glad of any help, Thank you.

Import-Module Microsoft.Graph.Users.Actions
Import-Module Microsoft.Graph.Mail

# Define variables
$tenantId = "tenant_id"
$clientId = "client_id/app_id"
$clientSecret = "client_value"
$senderEmail = "{object_id/user_mail_id}"  # Verified UPN of the user sending the email
$recipientEmail = "recipient_mail"
$subject = "Mail sent using MS Graph API"
$bodyContent = "Hi there, successfully sent mail using Graph API"

# Get an access token
$body = @{
    grant_type    = "client_credentials"
    scope         = "https://graph.microsoft.com/.default"
    client_id     = $clientId
    client_secret = $clientSecret
}

$tokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -Method Post -ContentType "application/x-www-form-urlencoded" -Body $body

$accessToken = $tokenResponse.access_token

# Print the access token
Write-Output "Access Token: $accessToken"

# Create the email message
$emailMessage = @{
    message = @{
        body            = @{
            content     = $bodyContent
            contentType = 'Text'
        }
        subject         = $subject
        toRecipients    = @(
            @{
                emailAddress = @{
                    address = 'recipient_mail_id'
                }
            }
        )
        hasAttachments  = $false
        importance      = 'Normal'
        saveToSentItems = 'true'
    }
}

# Convert the email message to JSON
$emailMessageJson = $emailMessage | ConvertTo-Json

# Print the email message JSON
Write-Output "Email Message JSON: $emailMessageJson"

# Send the email using the /users/{user-id}/sendMail endpoint
$response = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/users/{ObjectID/user_mail_id}/sendMail" -Method Post -Headers @{Authorization = "Bearer $accessToken"; "Content-Type" = "application/json"} -Body $emailMessageJson

# Output the response
$response

I wanted to remove the 400 – Bad Request Error, to make script more secure,
as credentials are given in script.

2

Answers


  1. Chosen as BEST ANSWER

    Hi @SantiagoSquarzon and All,

    Above code works, the problem was with Subscriptions(for me at least).

    We require to have a Subscription(Azure or Office 365) in which Office 365 Exchange Online should be active and working(unfortunately, its was not enabled for me). After enabling, the above code was working fine, I was getting response 202, and mail is not being delivered as it was considered as Spam.

    Let me know if there is any other solution working.

    Thank you.


  2. This is likely to be caused by a typo in the Body of the request. I don’t see other issues with your code that could cause a 400 response from the API.

    If you look at the body used in Example 1: Send a new email using JSON format from the docs, the saveToSentItems key-value pair is outside message not inside. Moreover, saveToSentItems is not a property listed in message resource type properties.

    {
      "message": {
        "subject": "Meet for lunch?",
        "body": {
          "contentType": "Text",
          "content": "The new cafeteria is open."
        },
        "toRecipients": [
          {
            "emailAddress": {
              "address": "[email protected]"
            }
          }
        ],
        "ccRecipients": [
          {
            "emailAddress": {
              "address": "[email protected]"
            }
          }
        ]
      },
      "saveToSentItems": "false"
    }
    

    Whereas you have it inside message, so solution might be:

    $emailMessage = @{
        message = @{
            body            = @{
                content     = $bodyContent
                contentType = 'Text'
            }
            subject         = $subject
            toRecipients    = @(
                @{
                    emailAddress = @{
                        address = 'recipient_mail_id'
                    }
                }
            )
            hasAttachments  = $false
            importance      = 'Normal'
        }
        saveToSentItems = 'true' # <-- Moving this outside the `message` kv pair
    }
    

    Also, as noted in comments, you will need -Depth 4 or more in your ConvertTo-Json to properly convert this object and not get it truncated.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search