1

I am trying to set up Gmail Push Notification to create a watch request for any new email received in the INBOX. So far, this is fine. However, I am trying to create a watch request as described here :

https://developers.google.com/gmail/api/guides/push#getting_gmail_mailbox_updates

I would like to set up a watch request for any email received from a specific email(info@abc.com) address having a subject line "[Important]" and having a PDF attachment.

Any idea if such a watch request can be set up?

Currently, I am reading all the emails from INBOX using imaplib received in the last 24 hours and manually search for emails having the subject line and attachment. However, I believe, this solution is not ideal.

Chris32
  • 4,716
  • 2
  • 18
  • 30
Kiran
  • 8,034
  • 36
  • 110
  • 176
  • 1
    `watch` requests cannot be customized at this level, but you could (1) get Push Notifications for all INBOX, (2) call `history.list` to get the details of the changes and (3) use the reponse body to `history.list` to filter the messages to only the ones coming from a certain email & having certain subject & having PDF attachment. Do you think that would be a good solution for you? If that's the case, I'd post an answer with more details on the corresponding workflow. – Iamblichus May 11 '20 at 11:18
  • Thanks a lot for your answer. Please elaborate, I will explore this. – Kiran May 12 '20 at 11:20

1 Answers1

4

Issue:

The only filter you can apply to Gmail Push Notifications is which label/s to retrieve notifications from, as can be seen here. Because of this, the filtering of messages depending on (1) who sent the message, (2) the email subject and (3) whether the email has a certain PDF attachment cannot be done at this stage, but after receiving the notifications. Luckily, though, there is no need to look for these messages manually, you can code your application to do that for you.

Workflow:

- Step #1. Set notifications for all INBOX and retrieve startHistoryId: As was said before, you have to receive notifications for all INBOX, since there is no more specific filter available. A call to Users: watch, providing INBOX in the labelIds field and the topic you created in topicName, will effectively configure the notifications. The response to watch has this shape:

{
  historyId: 1234567890
  expiration: 1431990098200
}

Where historyId refers to the mailbox’s current state. Let’s store it somewhere, and call it startHistoryId.

- Step #2. Get INBOX changes: After completing step 1, whenever there is a change in your INBOX, your application will receive a notification message describing the change. Whenever a notification is received, you want to get information about the specific changes made to the INBOX, and to achieve that, you should call history.list().

That is to say, your application should call history.list() every time a notification is received. Now, you want to get changes since last time, and that’s why you should provide the historyId retrieved in step 1 as the parameter startHistoryId. If you want to only retrieve new messages (and not deletions, or label edition/removal), you can set historyTypes to messageAdded. The request could be like this:

{
  userId: “your-email-address”,
  historyTypes: “messageAdded”,
  startHistoryId: “your-start-history-id”
}

As a response, you’ll get something like this:

{
  "history": [
    {
      "id": unsigned long,
      "messages": [
        users.messages Resource
      ],
      "messagesAdded": [
        {
          "message": users.messages Resource
        }
      ]
    }
  ],
  "nextPageToken": string,
  "historyId": unsigned long
}

Here, you should retrieve historyId, which will be used as startHistoryId the next time history.list() is called, and messagesAdded, which contains the IDs of the new messages you want to look for (only ID and threadId seem to be populated).

- Step 3. Filtering messages: Now you have the list of message IDs that have changed since last time (messagesAdded), and you want to know which of them match your criteria. To know that, you’ll have to iterate through all IDs in messagesAdded and call Users.messages: get for each ID. This will return the corresponding message resource. For each message, you’ll have to check whether the criteria are met:

  • Sender email: inside the resource, access the headers (message[“payload”][“headers”]), and loop through them, looking for the one whose name is From. You have to check whether the corresponding value is the email you’re looking for.

  • Subject: as in step (a), access the headers and look for the header whose name is Subject. The corresponding value is the email subject. Check whether it starts with [Important].

  • Attachment: you’ll have to look for the email attachments in message[“payload”][“parts”]. The process is a bit more complicated, but see, for example, this related question.

Reference:

Gmail API: Push Notifications

Iamblichus
  • 18,540
  • 2
  • 11
  • 27