Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: how to get the subject of an email from gmail API

Using Gmail API, how can I retrieve the subject of an email?

I see it in the raw file but it's qui cumbersome to retrieve it, and I am sure there should be a way to do it directly via the API.

messageraw= service.users().messages().get(userId="me", id=emails["id"], format="raw", metadataHeaders=None).execute()

It is the same question as this one but it has been close even so I can't post a better answer than the one proposed.

like image 225
MagTun Avatar asked Mar 13 '19 14:03

MagTun


People also ask

How do I see the subject line in Gmail?

Open the email message. Click Reply. Click the arrow next to the Reply button, then choose Subject line.


2 Answers

As mentionned in this answer, the subject is in the headers from payload

 "payload": {
    "partId": string,
    "mimeType": string,
    "filename": string,
    "headers": [
      {
        "name": string,
        "value": string
      }
    ],

But this not available if you use format="raw". So you need to use format="full".

Here is a full code:

# source  = https://developers.google.com/gmail/api/quickstart/python?authuser=2


# connect to gmail api 
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request


# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']


def main():

    # create the credential the first time and save it in token.pickle
    creds = None
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server()
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    #create the service 
    service = build('gmail', 'v1', credentials=creds)

    #*************************************
    # ressources for *get* email 
    # https://developers.google.com/resources/api-libraries/documentation/gmail/v1/python/latest/gmail_v1.users.messages.html#get
    # code example for decode https://developers.google.com/gmail/api/v1/reference/users/messages/get 
    #*************************************

    messageheader= service.users().messages().get(userId="me", id=emails["id"], format="full", metadataHeaders=None).execute()
    # print(messageheader)
    headers=messageheader["payload"]["headers"]
    subject= [i['value'] for i in headers if i["name"]=="Subject"]
    print(subject)  

if __name__ == '__main__':
    main()
like image 107
MagTun Avatar answered Oct 10 '22 22:10

MagTun


Since this was the question I landed on, I just wanted to share what I found to solve my own issue.

I am used to work with the email module that gives you a neat interface to interact with messages. In order to parse the message that the gmail api gives you, the following worked for me:

import email
import base64
messageraw = service.users().messages().get(
    userId="me", 
    id=emails["id"], 
    format="raw", 
    metadataHeaders=None
).execute()
email_message = email.message_from_bytes(
    base64.urlsafe_b64decode(messageraw['raw'])
)

You end up with an email.Message object and can access the metadata like email_message['from'].

like image 41
maekke97 Avatar answered Oct 10 '22 23:10

maekke97