Using Powershell To Access Gmail API
Description:
Follow this guide to connect to Gmail API using OAuthv2 working as of 2020-08-26. What I did was:
To Resolve:
-
Delete my current ‘posh’ application and created a new one called ‘powershell’
- Go to Google Project Console
- Create a new project
- Enable the Gmail API by selecting the API and selecting
enable API
, after creating your project. - Click Credentials
- Create OAuth Client ID Credentials
- Select Web Application as product type
- Configure the Authorized Redirect URI to
https://developers.google.com/oauthplayground
must not have a ending/
in the URI - Save your client ID and Secret
- Browse to Oauth Playground
- This saves us time from generating an OAuth request in PowerShell. This is where we will authorize our Project to our Google Account using our provided - Client ID and Client Secret.
- Click the gear in the right-hand corner and select
Use your own OAuth credentials
- Choose
Gmail API v1
and copy therefresh_token
andaccess_token
to notepad
-
Now in my Gmail API script I just use the following snippet to connect to Gmail and read/delete my messages:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
$clientId = "31262ipuu5.apps.googleusercontent.com" $clientSecret = "RRak" $refreshToken = '1//04DXqtu2S' $headers = @{ "Content-Type" = "application/x-www-form-urlencoded" } $body = @{ client_id = $clientId client_secret = $clientSecret refresh_token = $refreshToken grant_type = 'refresh_token' } $params = @{ 'Uri' = 'https://accounts.google.com/o/oauth2/token' 'ContentType' = 'application/x-www-form-urlencoded' 'Method' = 'POST' 'Headers' = $headers 'Body' = $body 'Verbose' = $true } $accessTokenResponse = Invoke-RestMethod @params $accesstoken = $($accessTokenResponse.access_token) $headers = @{ "Content-Type" = "application/json" } $params = @{ 'Uri' = "https://www.googleapis.com/gmail/v1/users/me/messages?access_token=$accesstoken" 'ContentType' = 'application/json' 'Method' = 'GET' 'Headers' = $headers 'Verbose' = $true } $getMessagesResponse = Invoke-RestMethod @params $messages = $($getMessagesResponse.messages)
- So
access_token
only has a one hour use time while therefresh_token
should be good until you change your account’s password, you do this regularly right?
- So
-
Feel free to ignore past this step - keeping here for any readers that need more info:
Older
-
I couldn’t get this working before because I was running into an issue with the fact that I had to open a browser to get the $code variable like this:
- Create
c:/scripts/1.ps1
1 2 3 4 5 6 7 8 9 10
# 1 - fill in $clientId = "883355tlpc.apps.googleusercontent.com" $clientSecret = "fOYop" # 2 - Do this one time, note that you have to run this each time you move past this step, will see about automating somehow # $scopes = "https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/gmail.send" $scopes = "https://mail.google.com/" Start-Process "https://accounts.google.com/o/oauth2/v2/auth?client_id=$clientId&scope=$([string]::Join("%20", $scopes))&access_type=offline&response_type=code&redirect_uri=urn:ietf:wg:oauth:2.0:oob" cmd /c pause
- Create
c:/scripts/2.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
$clientId = "883355tlpc.apps.googleusercontent.com" $clientSecret = "fOYop" $refreshToken = '1//04dniS4GdT9DXqtu2S' $headers = @{ "Content-Type" = "application/x-www-form-urlencoded" } $body = @{ client_id = $clientId client_secret = $clientSecret refresh_token = $refreshToken grant_type = 'refresh_token' } $params = @{ 'Uri' = 'https://accounts.google.com/o/oauth2/token' 'ContentType' = 'application/x-www-form-urlencoded' 'Method' = 'POST' 'Headers' = $headers 'Body' = $body } $accessTokenResponse = Invoke-RestMethod @params $accesstoken = $($accessTokenResponse.access_token) # Write-Output "Access token: " $accesstoken $headers = @{ "Content-Type" = "application/json" } $params = @{ 'Uri' = "https://www.googleapis.com/gmail/v1/users/me/messages?access_token=$accesstoken" 'ContentType' = 'application/json' 'Method' = 'GET' 'Headers' = $headers 'Body' = $body } $getMessagesResponse = Invoke-RestMethod @params $messages = $($getMessagesResponse.messages) Write-Output $messages cmd /c pause
- Create
-
So I would run
c:/scripts/1.ps1
and paste the code from the browser window into$refresh_token
inc:/scripts/2.ps1
.- After this it would work perfectly, but I can’t be logging in interactively if this is going to be a scheduled task!
- What I was missing was the redirect URI and Oauth Playground steps from above.
-
That is all for now, but in summary, once you have the $AccessToken, you can access Gmail API pretty easily:
-
All emails:
Invoke-WebRequest -Uri "https://www.googleapis.com/gmail/v1/users/me/messages?access_token=$accesstoken" -Method Get
-
Individual Email (Where $a = $($message.id) (see above)):
Invoke-WebRequest -Uri ("https://www.googleapis.com/gmail/v1/users/me/messages/$a" + "?access_token=$accesstoken") -Method Get
-
Trash an email (Where $a = $($message.id) (see above)):
Invoke-WebRequest -Uri ("https://www.googleapis.com/gmail/v1/users/me/messages/$a/trash" + "?access_token=$accesstoken") -Method Post
-
Found this on StackExchange. If you just want to get the most recent emails header, you can use this function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Function Get-SubjectLine { #Acquires most recent message ID using access token. $messageIDjson = Invoke-WebRequest -Uri "https://www.googleapis.com/gmail/v1/users/me/messages?access_token=$accessToken" -Method Get | ConvertFrom-Json; #Converts JSON message and thread ids into string. $messageID = ($messageIDjson | Out-String); #Seperates string on first message ID, places messageID into $result. $start = $messageID.indexOf("=") + 1; $end = $messageID.indexOf(";", $start); $length = $end - $start; $result = $messageID.substring($start, $length); #Acquires most recent message, using ID stored in result and access token. $messages = Invoke-WebRequest -Uri ("https://www.googleapis.com/gmail/v1/users/me/messages/$result" + "?access_token=$accessToken") -Method Get | ConvertFrom-Json; return $messages.snippet; }
- I’m sure there are millions of other things you can do once you are at this step. Enjoy!
-
Comments