Using Gmail API to send an email using Invoke-WebRequest in Powershell Using Gmail API to send an email using Invoke-WebRequest in Powershell powershell powershell

Using Gmail API to send an email using Invoke-WebRequest in Powershell


Any reasons not to use Send-MailMessage ?. If not you can try this example:

$From = "YourEmail@gmail.com"$To = "AnotherEmail@YourDomain.com"$Cc = "YourBoss@YourDomain.com"$Attachment = "C:\temp\Some random file.txt"$Subject = "Email Subject"$Body = "Insert body text here"$SMTPServer = "smtp.gmail.com"$SMTPPort = "587"Send-MailMessage -From $From -to $To -Cc $Cc -Subject $Subject `    -Body $Body -SmtpServer $SMTPServer -port $SMTPPort -UseSsl `    -Credential (Get-Credential) -Attachments $Attachment


After working on this for awhile I finally found the missing piece. I was not converting my Base64 encoded string (my mail message) to JSON and I wasn't including it in the Invoke-RestMethod properly.

I finally found the missing piece here: https://github.com/thinkAmi/PowerShell_misc/blob/master/gmail_api/gmail_sender.ps1.Here is the snippet that pointed me in the right direction.

$body = @{ "raw" = $raw; } | ConvertTo-Json$uri = "https://www.googleapis.com/gmail/v1/users/me/messages/send?access_token=$AccessToken"$result = Invoke-RestMethod $uri -Method POST -ErrorAction Stop -Body $body -ContentType "application/json"

Once I had that I was able to cobble together a solution for sending through the Gmail API using Powershell.

I found some very helpful code on this SO question (the code can be found here) that helped me get the correct OAuth access tokens.

Here is a working solution (it needs to be cleaned up):

Function Encode-Base64Url([string]$MsgIn) {    $InputBytes =  [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($MsgIn))        # "Url-Safe" base64 encodeing    $InputBytes = $InputBytes.Replace('+', '-').Replace('/', '_').Replace("=", "")    return $InputBytes}Add-Type -Path "C:\path\to\AE.Net.Mail.dll" # We are using AE.Net.Mail to create our message. https://github.com/andyedinborough/aenetmailAdd-Type -AssemblyName System.IOAdd-Type -AssemblyName System.Text.Encoding$ToEmail = "someone@somewhere.com"$FromEmail = "a.person@gmail.com"#  From https://gist.github.com/LindaLawton/55115de5e8b366be3969b24884f30a39#  Setup:##  Step 1: create new project on https://console.developers.google.com.#  Step 2: Create oauth credentials type native or other.#          Save the client id and secret. #  Step 3: Enable the api you are intersted in accessing.#          Look up what scopes you need for accssing this api,#  Step 4: Using the client id, and client secret from the ### Inital Authenticate:  Authentication must be done the first time via a webpage create the link you will need.  More then one scope can be added simply by seporating them with a comama#     Place it in a webbrowser. ##    https://accounts.google.com/o/oauth2/auth?client_id={CLIENT ID}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope={SCOPES}&response_type=code#    Change Scopes to https://www.googleapis.com/auth/gmail.send#                     https://www.googleapis.com/auth/gmail.readonly#                     https://mail.google.com/##    Copy the authencation code and run the following script.  #      note: AuthorizationCode can only be used once you will need to save the refresh token returned to you.  $ClientID = "Your Client ID"$secret = "Your Client Secret"$RedirectURI = "urn:ietf:wg:oauth:2.0:oob"$AuthorizationCode = 'Your Authorization Code'$tokenParams = @{      client_id=$ClientID;      client_secret=$secret;      code=$AuthorizationCode;      grant_type='authorization_code';      redirect_uri=$RedirectURI    }$token = Invoke-WebRequest -Uri "https://accounts.google.com/o/oauth2/token" -Method POST -Body $tokenParams | ConvertFrom-Json# Use refresh token to get new access token# The access token is used to access the api by sending the access_token parm with every request. # Access tokens are only valid for an hour, after that you will need to request a new one using your refresh_token$refreshToken = $token.refresh_token  $RefreshTokenParams = @{      client_id=$ClientID;      client_secret=$secret;      refresh_token=$refreshToken;      grant_type='refresh_token';    }$RefreshedToken = Invoke-WebRequest -Uri "https://accounts.google.com/o/oauth2/token" -Method POST -Body $refreshTokenParams | ConvertFrom-Json$AccessToken = $RefreshedToken.access_token# Compose and send an email using the access token$From = New-Object MailAddress($FromEmail)$To = New-Object MailAddress($ToEmail)$Msg = New-Object AE.Net.Mail.MailMessage$Msg.To.Add($To)$Msg.ReplyTo.Add($From) # Important so email doesn't bounce $Msg.From = $From$Msg.Subject = "Sent through the Gmail API using Powershell"$Msg.Body = "Hello, world from Gmail API using Powershell!"$MsgSW = New-Object System.IO.StringWriter$Msg.Save($MsgSW)$EncodedEmail = Encode-Base64Url $MsgSW# Found this gem here: https://github.com/thinkAmi/PowerShell_misc/blob/master/gmail_api/gmail_sender.ps1$Content = @{ "raw" = $EncodedEmail; } | ConvertTo-Json$Result = Invoke-RestMethod -Uri "https://www.googleapis.com/gmail/v1/users/me/messages/send?access_token=$AccessToken" -Method POST -ErrorAction Stop -Body $Content -ContentType "Application/Json"if($Result){    Write-Host $Result}else{    Write-Host "Error sending email"}