PythonでGmailのAPIを通してメールを送信する方法

  • このエントリーをはてなブックマークに追加

Pythonでセキュリティ上安全にGmailを制御するために、Gmail APIを使うのがオススメです。ここではGmail APIの導入方法とPython用ライブラリのインストール方法を説明し、メール送信方法を習得することを目標とします。

こんにちは。wat(@watlablog)です。ここではPythonを使ってGmailの送信を自動化する方法を習得します

Gmail APIを使うと安全にプログラムからGmailを制御できる

Gmail APIとは?

APIApplication Programming Interface)とは、文字通りアプリケーションとプログラミングのインターフェースで、両者をつなぐ役割をするものという意味です。

Gmail APIはGoogleが提供するGmailというメールサービスをプログラム上から簡単に扱うことができるようにするAPIということになりますね。

実はGmail APIはもっと大きな括りで言うと、Google APIの一種ということが出来ます。

僕達が普段何気なく利用しているものも、実はGoogle製のサービスというくらい、Googleには様々なサービスがあります。

そしてそれらGoogleサービスはほとんどがAPIでプログラムから制御できるようになっています。

Gmail APIを使う意味

GmailはWebブラウザから閲覧することができるので、APIでなくても使う方法がいくつかあるそうです(試してはいませんが)。

例えばSMTPやパスワードを使ってメールを制御したり、Selenium等のWebスクレイピング技術を応用して自分のアカウントを開いたり…。

但し、いずれの場合もプログラムコード上に自分のGoogleアカウントの情報を何の暗号化も無しに載せることになりそうでかなり不安です。

Gmail APIを使えばコード上に重要な個人情報を記載することなく、Googleの許可のもとにメールサービスをプログラムから利用可能になります

Gmail APIを利用するためには、APIを自分のGoogleアカウントで有効化しなければなりません。以下より具体的にGmail APIを使うための手順を紹介します。

Gmail APIを使う準備をする

Advertisements

Gmail APIを有効化する

Gmail APIを有効化するために、まずは以下のURLへアクセスします。
※但し、この時点でGoogleアカウントにログインしておきます。

https://developers.google.com/gmail/api

次に、API overviewのページを開きます。

Gmail API-01

様々な言語を選ぶことができますが、ここではPythonを選択します。

Gmail API-02

開いた先のページでEnable the Gmail APIをクリックします。

Gmail API-03

以下のウィンドウが出て来ますが、まず始めに①プロジェクト名(任意の名前)を入力し、Terms of Serviceを読み内容に同意したら②Yesを選択してから③Nextをクリックします。

Gmail API-04

Configure your OAuth clientで認証を行う環境を選択します。プルダウンメニューからWeb系をはじめ色々と選択肢がありますが、今回はPythonファイルをPCで実行するだけなので、desktop appのままにします。

選択が終了したらCREATEをクリックします。

Gmail API-05

次に①DOWNLOAD CLIENT CONFIGURATIONをクリックすると、credentials.jsonというJsonファイルがダウンロードされます。ダウンロードが終了したら②DONEをクリックしてウィンドウを閉じます。

Gmail API-06

credentials.jsonについて

credentialsとは、日本語で資格情報という意味です。このファイルは自分のアカウントの資格情報が記載されているので、他者には見せないように注意しましょう。

Pythonライブラリをインストールする

公式ページにも記載がありますが、Pythonで使うライブラリをpipインストールします。

以下のコードをWindowsであればコマンドプロンプトに打ち込んで実行することでインストール可能です。

PythonでGmailを使うコード

公式のサンプル(ラベル取得)を実行し動作確認をする

いきなりコードをゼロから使い始めるのは難易度が高いので、まずは公式ページに載っているサンプルプログラム(Quickstart)を使って動作確認をしてみましょう。

まずはじめに先ほどダウンロードしたcredentials.jsonをプログラムを実行する.pyファイルと同じ所に置きます

次に、以下のコードを使ってプログラムを実行します。

エラー?→許可が必要なだけでした

プログラムを実行すると、以下のように「このアプリは確認されていません」というメッセージが出て思うように動かないと思います。
※こちらはGoogle Chromeをデフォルトブラウザに設定しているため、プログラムを実行したらChromeの画面が開きました。

どうやら許可を与えなければいけないようなので、表示されたページの下の方にある①詳細を開き、一番下に現れる②リンクを開きます。

Gmail API-07

Googleアカウントを選択すると権限の付与というウィンドウが出て来ますので、これらを全て許可します。

Gmail API-08

サンプルコードの実行結果

気を取り直して、再度プログラムを実行すると以下の結果を得ます。

このサンプルプログラムはmain()関数の下の方で「service.users().labels().list(userId='me').execute()」を実行し、「results.get('labels', [])」でGmailの左側ツリーにある受信ボックスや送信ボックスのラベルをリストで取得しているようです。

main()関数の上の方は認証関係のコードのようで、これは他の操作をする時に参考になりそうですね。

Gmailでメールを送信するコードを書いていく

新しい操作を行うために、上記のサンプルコードをいじりながらメールの送信を行っていきます。

作っていきましょう…とは言っても、公式には既に送信の場合のサンプルコード(送信部のみのdef関数)もありました。なので、基本は以下のページの公式のPythonコードをコピペします。

公式サンプル(送信):https://developers.google.com/gmail/api/guides/sending

しかし、単純なコピペだけでは動かなかったので修正部分を解説していきます。

書いていない所だったり、文法がおかしい所(エラーになる所)を修正して動くようにしてみました。

import文を追加する

公式のサンプルコードを使うためには、以下のライブラリを最初に紹介したコードに追加でimportします。

SCOPEの設定を変える

Gmail APIを使った送信のサンプルコードにはmain()の修正に関して記述がありませんが、始めに、SCOPEを変更します。
SCOPEとは、アプリの認証を行うためにユーザに要求する権限です。

以下の公式ページにSCOPEの使い方が書いてあるので、これを参考にします。
SCOPE:https://developers.google.com/gmail/api/auth/scopes?hl=ja

Send messages only.」と書いてある「~.send」を選択して以下のように元コードを変更しました。

SCOPEの設定にはフルアクセス系の要求もありますが、先ほどの公式ページに書いてあるように、「可能な限り絞り込んだスコープを選択し、アプリが実際に使わないスコープを要求しないようにする」ことが良いようです。

create_message関数を修正する

次に公式ページに載っているcreate_messageというdef関数をコピペします。この関数は送信する前のメールの中身を作成する関数です。

しかし、そのままでは以下のエラーが発生してしまいました。

TypeError: Object of type bytes is not JSON serializable

どうやら作ったmessageというオブジェクトのタイプが違うようで、以下のコードの最終行でreturnしている変数に.decode()を追加することでエラーが解消しました。

send_message関数を修正する

次は公式からsend_message関数をコピペします。この関数は実際にメールを送信する部分です。

ここはprint文の書き方と最後のexceptの文法がおかしかったので、その部分のみ修正しました(公式の元コードと比べて頂ければと思います(公式は旧式?))。

tryとexceptによる例外処理は「Python小技!whileループ中のキー操作を受け付ける方法」でやって以来使っていませんでしたね。懐かしい。

mail()関数を送信用に修正する

前半で紹介したラベルを取得するコードのmain()関数はほぼそのまま使いますが、「# Call the Gmail API」の部分をメール送信の内容に変更します。

以下のコードは既に紹介したcreate_message関数に渡す引数として、送信元のアドレスsender送信先のアドレスtoタイトルsubject本文message_textを設定し、mailを作成、send_message関数で実際に送信する内容を意味しています。

ここでは自分のアドレスから自分のアドレスにメールを送信しています。

全コード

以下にコピペ用の全コードを示します。ほとんどコピペなので詳細コメント等は書いていません。

再度認証エラーでハマってしまった場合→token.pickleが原因でした

最終的には上記コードでうまくいくのですが、以下のエラーメッセージが出る場合があります。先ほどはAPIを使った新しい操作を行う時に、Webブラウザが立ち上がって操作を「許可」するアクションがありましたが、このメッセージが出る場合はWebブラウザも立ち上がりません。

HttpError 403 when requesting https://www.googleapis.com/gmail/v1/users/me/messages/send?alt=json returned "Insufficient Permission"

結果的には、.pyファイルと同じ階層に作られるtoken.pickleを一度削除してからコードを実行することで解決しました。

pickleは「Python機械学習済モデルをpickleで保存して復元する方法」で一度使った事がありましたが、Python標準ライブラリの1つで、オブジェクトの状態をファイルに保存することができます。

そのため、先ほどラベルの取得コードに限定して得た認証がそのまま残り、今回のメール送信操作に対しての認証が無かったためにエラーとなったと推定できます。

エラー内容を検索しても全然ヒットせず、僕はこの部分にかなりハマりました!
本記事が誰かの解決ページになることを祈り上記内容を記録しておきます!

token.pickleを削除してからコードを実行すると、新たに認証のページが開かれます。先ほどと同様に一度許可してしまえば今後は同一のプロジェクトで聞かれることはなくなります。

Gmail API-09

実行結果

以下が上記コードを実行して実際に自分のアドレスで受信した結果です。
どうやらGoogleさんはプログラム的に送信されたメールを見分けて警告文を出してくれるようです。

result

メールがPythonから送信できたということで、まずは目標達成としましょう。

API reference

以下に参考までに公式リファレンスのリンクを載せます。

Reference:https://developers.google.com/gmail/api/v1/reference/
SCOPE:https://developers.google.com/gmail/api/auth/scopes?hl=ja

まとめ

本記事ではGmail APIを使ってPythonからGmailを制御する方法を学びました。

公式ページではサンプルのコードが豊富にあり、特に大枠のコーディングで困る所はありませんでしたが、ちょっとしたエラーや文法違いを修正する所で時間をとられてしまいました。

GoogleのAPIは様々な機能に「許可」を与えることが必要で、資格情報を意味するcredentials.jsonファイルや状態を記録するtoken.pickleに気を付ける必要がありました。

最終的には修正したサンプルコードでGmailからメールを送信することが出来ました。

APIは正直覚えることが多くあって面倒ですが、なんとかメールを操作できました!Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!

  • このエントリーをはてなブックマークに追加

SNSでもご購読できます。

コメント

コメントを残す

*