Python×GmailAPIで未読メールの本文を取得して既読にする

2018-11-13

今回はPythonでGmailAPIを操作する方法についてまとめる。
今回実装した機能は以下の3つ。

・未読メールの取得
・未読メールを既読にする
・メールの件名と本文の抜き出し

未読メールの取得に関しては、こちらの記事にも以前まとめたが、今回学んだ方法の方がより簡単である。

もくじ

  1. 未読メールを取得
  2. メールを既読にする
  3. メールの件名と本文を抜き出す
  4. ハマったポイント
  5. 参考

未読メールを取得

未読メールを取得するコード自体は、なんとたった一行。

  def get_unread_mail(service):
      results = service.users().messages().list(userId="me", q="is:unread").execute()
      return results

ここでのserviceには、build関数で確率したGmailAPIのエンドポイントが格納されている。
そもそもエンドポイントって何?っていう僕のような人間はこちらの記事がおすすめ。

RESTful APIのURI設計(エンドポイント設計)

resultには、qで指定したクエリに当てはまるメッセージが、IDのリストとして格納されている。
users().message().list()メソッドは、ユーザーのメールボックスの中のメッセージをリスト形式で取り出すメソッドである。
このクエリにis:unreadというパラメーターを指定することによって、未読メールの一覧を取得できる。

他のパラメーターやメソッドについては、ドキュメントを参照。

未読メールの一覧は、IDで渡されるので、get()メソッドを使って内容を取得する必要がある。

  unread_mail_list = get_unread_mail(service)

  for unread_mail in unread_mail_list["messages"]:
      id = unread_mail["id"]
      data = service.users().messages().get(userId="me", id=id, format="raw").execute()

メールを既読にする

メールを既読にするメソッドもシンプルに書ける。

  #メールを既読にする
  def remove_unread(service, id):
      query = {"removeLabelIds": ["UNREAD"]}
      service.users().messages().modify(userId="me", id=id, body=query).execute()

ここでは、users().messages().modify()メソッドを使って、メッセージに付与されているラベルの変更を行っている。
Gmailは、未読のメッセージにはUNREADというラベルが与えられているため、このラベルを取り除いてあげれば、既読扱いになる。
注意点としては、modify()メソッドは、ある程度強力な権限を持ったスコープが必要であるということ。
readonlyのスコープのままでは使用できない。

メールの件名と本文を抜き出す

Gmailでは、本文はBASE64形式で扱われている。
BASE64とは、エンコード形式の一つで、すべてのデータをアルファベット(a~z, A~z)と数字(0~9)、一部の記号(+,/)の64文字で表している。
get()メソッドでは、本文はこのBASE64形式によって渡されるため、利用するためにはUTF-8形式にデコードする必要がある

BASE64形式やそのデコードについてはこちらの記事が分かりやすかった。

base64ってなんぞ??理解のために実装してみた

実際に本文をデコードするためのコードは、こちらのサイトを参考(丸パクリ)した。

PythonでGmailを確認しよう その2

BASE64のデコードについては、まだ理解が浅いので自分のコードは割愛する。

'Insufficient Permission’から抜け出す

今回GmailAPIを使ってみて最も苦しめられたこと。
'Insufficient Permission’から抜け出せない。

メッセージやラベルを削除しようとすると、毎回’Insufficient Permission’というエラーがでて困った。
もちろんスコープはちゃんと変えてるのに。
これ、同じところにハマってる人はきっと多いので書いておく。

原因は、『最初の認証でreadonlyを使うと、その後スコープを変更しても認証は変わらない』ということだった。
要するに、ドキュメントのクイックスタートのコードを始めに動かした後にスコープを書き換えても、期待した動きをしてくれないということ。

解決法は、一度こちらから認証の設定を削除するか、新しいプロジェクトを立ち上げるかのどちらかになる。

完全にトラップに引っかかって先に進めなくなっていたが、この記事に出会って解決できた。ありがとう。


【Python × Gmail API】メールを削除できない

参考

・WEB
RESTful APIのURI設計(エンドポイント設計)

GmailAPIドキュメント

base64ってなんぞ??理解のために実装してみた

base64ってなんぞ??理解のために実装してみた

【Python × Gmail API】メールを削除できない