PythonでGmail APIに触れてみる: メールスレッドを触ってみる

PythonでGmail APIに触れてみる: メールスレッドを触ってみる


PythonでGmail APIに触れてみるシリーズ。前回までメールの本文を見たり添付ファイルを取得する を扱いました。

今回は一歩手前の段階として、メールの検索をしてみましょう。

過去シリーズはこちら

スレッドはメールのやり取りのまとまり

Gmailにはメールの返信をGmail側がみて自動的にグループかしてくれる機能です。メールスレッドはメールのやり取りのまとまりです。

Gmail APIからもこのスレッドの一覧や、そのスレッドの中にあるメールメッセージを取得できます。

なお、スレッド=メールのやりとりのまとまりとしましたが、やり取りがないメール(つまり1件でも)もスレッドとして扱います。スレッドを扱うAPIを使ったからといってメールのやり取りがされている物だけがリストアップされるわけではなく、実際のメッセージの件数などを見に行って確認する必要があります。

スレッドの一覧を取得

スレッドの検索は、users.threads.listを使います。users.messages.listと同じようにuserIdを指定して、検索のときにも使ったラベルの指定でlabelId、やクエリーのqパラメーターで検索条件を指定できます。

スレッドの一覧を取得するとThreadリソースのリストが返ってきます。Threadリソースはidsnippetが含まれています。idはスレッドのIDで、snippetはスレッドの最新のメッセージの冒頭一部が入ってます。大体200文字程度です。

# get_messages_by_label.py
# 受信トレイにあるスレッドの一覧を取得。ここではラベルを指定しています

from googleauth_util import get_cledential

from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]

LABEL_ID = "INBOX"


def main():
    creds = get_cledential(SCOPES)
    try:
        service = build("gmail", "v1", credentials=creds)

        # スレッド一覧を取得
        threads = (
            service.users().threads().list(userId="me", labelIds=LABEL_ID).execute()
        )["threads"]

        # スレッドを表示(10件まで)
        for thread in threads[:10]:
            # スレッドのID
            print(f"ID:{thread['id']}  - {thread['snippet']})")
            print("----------")

    # エラーハンドリング
    except HttpError as error:
        print(f"An error occurred: {error}")


if __name__ == "__main__":
    main()

気を付ける点ですが、users.threads.listのレスポンスは以下になるとドキュメントにあります。注意点がありthreadsのリストに入ってるThreadは、idとsnippetしか含まれていません。

{
  "threads": [
    {
      object (Thread)
    }
  ],
  "nextPageToken": string,
  "resultSizeEstimate": integer
}

threadsリストの中のThreadリソースは以下のような構造です。

{
  "id": string,
  "snippet": string
}

スレッドからメッセージを取得

スレッドのIDが取得できたので、このIDを使ってスレッドの中にあるメッセージを取得します。users.threads.getを使います。

{
  "id": string,
  "snippet": string,
  "historyId": string,
  "messages": [
    {
      object (Message)
    }
  ]
}
# get_messages_by_thread_id.py
# 受信トレイにあるスレッドの一覧を取得し、スレッドに含まれるメッセージの一覧を取得

from googleauth_util import get_cledential

from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]

LABEL_ID = "INBOX"


def main():
    creds = get_cledential(SCOPES)
    try:
        service = build("gmail", "v1", credentials=creds)

        # スレッド一覧を取得
        threads = (
            service.users().threads().list(userId="me", labelIds=LABEL_ID).execute()
        )["threads"]

        # 50件ぐらいに絞って表示
        for thread in threads[:50]:
            thread_id = thread["id"]
            # メッセージ一覧を取得
            messages = (
                service.users().threads().get(userId="me", id=thread_id).execute()
            )["messages"]
            # メッセージが2以上のものがあれば、そのメッセージのIDとタイトルを表示
            if len(messages) > 1:
                print(f"Thread ID:{thread_id} メッセージ数:{len(messages)}")
                for message in messages:
                    print(f"  Message ID:{message['id']}  - {message['snippet']}")
                print("----------")

    # エラーハンドリング
    except HttpError as error:
        print(f"An error occurred: {error}")


if __name__ == "__main__":
    main()

このコードの挙動は、スレッドの一覧から先頭50件を取得し、そのスレッドに含まれるメッセージの一覧を取得して表示します。

メールのやり取りがあるかを判断するために、スレッド内メッセージが複数ある(1より多い)スレッドのみを表示しています。

まとめ

メールスレッドはメールのやり取りをまとめたものです。メールメッセージの一覧を取得するより、よりメールのやり取りを把握するのに適しています。

スレッドに関係するメッセージをすべて見ることができ、情報収集して要約、返信の時にも利用できますね。

次回はメールの下書きを作成する方法を紹介します。

参考

宣伝

所属会社の宣伝です! 自動車プレス金型の機械設計を行う設計事務所で、製品や試作品の3Dモデリングのお仕事も受け付けています。

また製造業の業務、バックオフィスの自動化やその先に繋がるデジタル化、DXに取り組みたい方もご相談承っております。 今回の記事で扱ったGmail等のメールの扱いや、データを抽出して作業の自動化を行いたい方は、ぜひお気軽にお問い合わせください!

付録1: get_cledential関数について

get_cledential関数はGmail APIを使うための認証情報を取得する自作関数です。詳しくは前回の記事をご覧ください。