Holmes開発者ブログ

契約マネジメントシステム「ホームズクラウド」の開発者ブログです

PythonでGmailAPIを使用してメールのタイトルと本文を取得してみた

初めまして、HolmesのNabeです。

今回はPythonからGmail APIを使用してアカウントにアクセスする事でメールのタイトルと本文を取得することができたので、その手順などを共有できればと思います。

環境

開発言語: Python3

ライブラリ: google-api-python-client · PyPI

GmailAPI有効化

APIを使用するに当たって、GmailAPIを有効化する必要があります。APIキーが発行された状態は以下のようになります。

f:id:nabe-holmes:20200319185507p:plain
APIキーが発行された状態(ID・シークレットは加工済み)

画面上部の「JSONをダウンロード」からJSONファイルをダウンロードすると、接続に必要なファイルが生成されます。このファイルをプログラムと同じ階層に設置することでプログラムからAPIを使用することができます。今回のサンプルではcredentials.jsonというファイル名で使用しています。作成するファイルは全て同一ディレクトリに設置してください。

Pythonのコード記載例

ライブラリの準備

前提条件として、いくつかライブラリをインストールする必要があります。requirements.txtに下記のように記載します。

requirements.txt

google-api-python-client==1.7.11
httplib2==0.17.0
oauth2client==4.1.3

下記のコマンドを入力することで、インストールが実行されます。

pip install -r requirements.txt

接続・認証

接続するにあたって必要な認証は下記のコードで実装できます。

gmail_api.py

class GmailAPI:
    def __init__(self):
        # If modifying these scopes, delete the file token.json.
        self._SCOPES = "https://www.googleapis.com/auth/gmail.readonly"

    def connect_gmail(self):
        store = file.Storage("token.json")
        creds = store.get()
        if not creds or creds.invalid:
            flow = client.flow_from_clientsecrets("credentials.json", self._SCOPES)
            creds = tools.run_flow(flow, store)
        service = build("gmail", "v1", http=creds.authorize(Http()))

        return service

取得処理

取得処理は以下のようになります。 先ほど作成したGmailAPIクラスの中に追加で実装する形になります。

gmail_api.py

    def get_message_list(self, DateFrom, DateTo, MessageFrom, MessageTo):

        # APIに接続
        service = self.connect_gmail()

        MessageList = []

        query = ""
        # 検索用クエリを指定する
        if DateFrom != None and DateFrom != "":
            query += "After:" + DateFrom + " "
        if DateTo != None and DateTo != "":
            query += "Before:" + DateTo + " "
        if MessageFrom != None and MessageFrom != "":
            query += "From:" + MessageFrom + " "
        if MessageTo != None and MessageTo != "":
            query += "To:" + MessageTo + " "

        # メールIDの一覧を取得する(最大100件)
        messageIDlist = service.users().messages().list(userId="me", maxResults=100, q=query).execute()
        # 該当するメールが存在しない場合は、処理中断
        if messageIDlist["resultSizeEstimate"] == 0:
            print("Message is not found")
            return MessageList
        # メッセージIDを元に、メールの詳細情報を取得
        for message in messageIDlist["messages"]:
            row = {}
            row["ID"] = message["id"]
            MessageDetail = service.users().messages().get(userId="me", id=message["id"]).execute()
            for header in MessageDetail["payload"]["headers"]:
                # 日付、送信元、件名を取得する
                if header["name"] == "Date":
                    row["Date"] = header["value"]
                elif header["name"] == "From":
                    row["From"] = header["value"]
                elif header["name"] == "To":
                    row["To"] = header["value"]
                elif header["name"] == "Subject":
                    row["Subject"] = header["value"]
            MessageList.append(row)

        return MessageList

タイトルや本文の取得について

取得したデータはメールの情報が大量に入っているため、必要な情報を抜粋してくる必要があります。

メールのタイトル等は特定の場所にあるため決め打ちで取得が可能です。メール本文についてはペイロードの中身を探していく必要があり、メールがテキスト形式かHTML形式かで取得方法が大きく変わってくるので、形式に合わせた場所を参照する必要があります。取得処理のMessageList.append(row)の直前に下記のコードを追加します。

gmail_api.py

# HTMLメール本文を取得する
MessageDetail = service.users().messages().get(userId="me", id=message["id"], format="full").execute()
if MessageDetail["payload"]["mimeType"] == "multipart/alternative":
    for payload_parts in MessageDetail["payload"]["parts"]:
        if payload_parts["mimeType"] == "text/plain":
            for payload_header in payload_parts["headers"]:
                if payload_header["name"] == "Content-Type" and payload_header["value"].lower() == "text/plain; charset=utf-8":
                    row["Body"] = email.message_from_string(str(base64.urlsafe_b64decode(payload_parts["body"]["data"]), "utf-8")).get_payload()

感想

メールの本文の取得についてはメールの形式によって変わるので、どこに記載されているかはデータ構造をデバッグしながら確認したり、いくつかサイトを確認しながら探したため苦戦しましたが、実装自体は思ったより簡単にできたと思います。

参考サイト

キー発行手順は下記ページが参考になりました。

valmore.work

PythonでのAPI使用方法はこちらを参考にしています。

qiita.com

データ構造については下記ページ(英語)に記載されています。

developers.google.com

おわりに

Holmesはエンジニア・デザイナーを募集しています 興味がある方はこちらからご連絡ください! lab.holmescloud.com lab.holmescloud.com