# Read emails from Gmail API using Node.js and Postman
Example response of API call
https://www.postman.com/collections/6655f0c79fe567dd58fc
Other reading
https://www.labnol.org/google-api-service-account-220405
https://medium.com/@sirajul.anik/understanding-oauth-2-0-179543b18bd
Original packages from google API doc (more complicated solutions)
https://www.npmjs.com/package/googleapis
https://www.npmjs.com/package/@google-cloud/local-auth
Packages that have simple usages than google API docs
https://github.com/SpiderStrategies/node-gmail-api
https://github.com/jaredhanson/passport-google-oauth
## Pre studies
### OAuth 2.0
https://oauth.net/2/
Important flows
- Protocol Flow
- Refreshing an Expired Access Token
- Authorization Code Flow
### Using OAuth 2.0 to Access Google APIs
https://developers.google.com/identity/protocols/oauth2
### Gmail API Overview
https://developers.google.com/gmail/api/guides
## Node.js quickstart
https://developers.google.com/gmail/api/quickstart/nodejs
### Codes implementation examples in JavaScript
#### authenticate
To get an access token using OAuth 2.0 Client ID (Desktop application)
> 
- Change the `scopes` into Gmail API scope
```
const SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'];
```
- Here use a file to store the credential, better to store them as secrets in the config file of the project
## Get Gmail API access token
https://www.daimto.com/how-to-get-a-google-access-token-with-curl/
https://wiki.genexus.com/commwiki/servlet/wiki?50408,Google+OAuth+2.0+process+for+emails%3A+Generation+and+data+collection+by+the+Administrator
### 1. Get Authorization Code
> 
#### Request type
GET
#### Request URL (Need to open it in browser)
```
https://accounts.google.com/o/oauth2/v2/auth?access_type={{access_type}}&scope={{scopes}}&client_id={{client_id}}&redirect_uri={{redirectURL}}&response_type={{response_type}}
```
#### Query strings and their values
| Query string | Value |
| ------------- |:----------------------------------------- |
| access_type | offline |
| scope | https://mail.google.com/ |
| client_id | The created OAuth 2.0 Client ID client id |
| redirect_uri | urn:ietf:wg:oauth:2.0:oob |
| response_type | code |
#### In Postman
For viewing only, since the get code steps need manual work in the browser

### 2. Get refresh token and access token
Use authorization code, only need to run this step at first time, can store and reuse the refresh token.
#### Request type
POST
#### Request URL
```
https://accounts.google.com/o/oauth2/token?code={{authorization_code}}&client_id={{client_id}}&client_secret={{client_secret}}&redirect_uri={{redirect_uri}}&grant_type={{grant_type}}
```
#### Query strings and their values
| Query string | Value |
|:------------- |:------------------------------------------------------------------ |
| code | The Authorization code from step **1. Get Authorization Code** |
| client_id | The created OAuth 2.0 Client ID client id |
| client_secret | The created OAuth 2.0 Client ID client secret |
| redirect_uri | urn:ietf:wg:oauth:2.0:oob |
| grant_type | authorization_code |
#### Response
- Contains both **refresh token** and **access token**
- Save the **refresh token** from the response

### 3. Get access token using the refresh token
#### Request type
POST
#### Request URL (Need to open it in browser)
```
https://accounts.google.com/o/oauth2/token?refresh_token={{refresh_token}}&client_id={{client_id}}&client_secret={{client_secret}}&redirect_uri={{redirect_uri}}&grant_type={{grant_type_refresh_token}}
```
#### Query strings and their values
| Query string | Value |
|:------------- |:------------------------------------------------------------------------- |
| refresh_token | The refresh token from step **2. Get refresh token and access token** |
| client_id | The created OAuth 2.0 Client ID client id |
| client_secret | The created OAuth 2.0 Client ID client secret |
| redirect_uri | urn:ietf:wg:oauth:2.0:oob |
| grant_type | refresh_token |
#### In Postman
Use the **access token** from the response to access Gmail API

### 4. Example usage: Get messages from Gmail
Resources
https://www.postman.com/api-evangelist/workspace/google/collection/35240-0d073c40-6ad8-43d0-8baf-8ee3606819e0?ctx=documentation
https://mailtrap.io/blog/send-emails-with-gmail-api/
#### Request type
GET
#### Request URL
```
https://gmail.googleapis.com/gmail/v1/users/{{user_id}}/messages
```
| user_id |
|:---------------------------------------------------------------------------------------------- |
| The testing user gmail that is saved in **OAuth consent screen**, for example, `abc@gmail.com` |
#### In Postman
Set the Authorization type of the request to **Bearer Token** (which is the access token from step **3. Get access token using the refresh token**)

## Error handling
### 1. "Error 403: access_denied" when getting Authorization Code

**Solution**
https://stackoverflow.com/questions/73062345/error-403-access-denied-when-usign-google-oauth
Add a testing user gmail and save (which will be the test account that accesses the Gmail API), for example, `abc@gmail.com`

After adding the testing user, and choosing the authorization account again, click **Continue** after seeing:

And keep clicking **Continue**
Finally copy and save the **Authorization Code** that shows in the browser

### 2. Seeing **Invalid_grant, Bad Request** when getting refresh token
**Solution**
Do step **1. Get Authorization Code** again to get a new **Authorization Code**, and use the new Authorization Code to get the **refresh token** by doing step **2. Get refresh token and access token**.
###### tags: `api testing` `test automation` `software test`