# 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) > ![](https://hackmd.io/_uploads/r1nsZFr-o.png) - 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 > ![](https://hackmd.io/_uploads/SkikgnU-o.png) #### 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 ![](https://hackmd.io/_uploads/S1Ll6irZi.png) ### 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 ![](https://hackmd.io/_uploads/ryLJ8nB-i.png) ### 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 ![](https://hackmd.io/_uploads/H1yMxaHWo.png) ### 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**) ![](https://hackmd.io/_uploads/SkJExn8bs.png) ## Error handling ### 1. "Error 403: access_denied" when getting Authorization Code ![](https://hackmd.io/_uploads/rynj8sB-s.png) **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` ![](https://hackmd.io/_uploads/H1VitjBWi.png) After adding the testing user, and choosing the authorization account again, click **Continue** after seeing: ![](https://hackmd.io/_uploads/SyorqoBZs.png) And keep clicking **Continue** Finally copy and save the **Authorization Code** that shows in the browser ![](https://hackmd.io/_uploads/Hk6j5or-j.png) ### 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`