Gmail API を使って監視メールチェックを楽にしたい その2

  • #技術ブログ 

あちゃー、また2ヶ月近くブログの更新ほったらかしにしちゃった、、、。
ゴールデンウィーク挟んだししょうがないよねっと、いつも通りの半人前エンジニアのうえピーです。

さてさて、そんな大型連休明けのブログですが、今回は、「Gmail APIを使って監視メールチェックを楽にしたい その1」の続きにしようと思います。

前回は、認証してGmailのラベルを取ってくることに成功しましたので、今回は、監視メールチェックするため、メール本文を取得して標準出力してみようと思います。
今回、作成したプログラムの全量は、最後に掲載しておりますので、躓いたところをピックアップしていきます。

とりあえず、APIリファレンスを見てみましょう。
ふむ、一覧で取れたほうが嬉しいので、多分、Users.messagesのlistで欲しい情報がとれそうですね。
よし、Examplesを参考に、関数書いてみるか。

def printMessages(service, user_id, query=''):
    response = service.users().messages().list(userId=user_id, q=query).execute()
    if 'messages' in response:
        print(response['messages'])
        
    while 'nextPageToken' in response:
        page_token = response['nextPageToken']
        response = service.users().messages().list(userId=user_id, q=query, pageToken=page_token).execute()
        print(response['messages'])

よし、実行っと。
これで、本文取れれば、今日のブログは以上終了ですね。ちょろい仕事っす。
あれ??messagesのリストが返却されるって書いてあるのに、中身はthreadIdとidのみって!!

うーん、まぁね、レスポンスのサイズ考えると、そりゃそうか。
ってことは、idをキーにして、メールの詳細をgetしないといけないわけね。
Users.messagesのgetを使えばいいのかな?
では、またまた、Examplesを参考に、関数を修正っと。

def printMessages(service, user_id, query=''):
    response = service.users().messages().list(userId=user_id, q=query).execute()
    if 'messages' in response:
        #print(response['messages'])
        for message_id in response['messages']:
            #print(message_id['id'])
            message = service.users().messages().get(userId=user_id, id=message_id['id'], format='raw').execute()
            msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
            mime_msg = email.message_from_string(msg_str)
            print(mime_msg)
        
    while 'nextPageToken' in response:
        page_token = response['nextPageToken']
        response = service.users().messages().list(userId=user_id, q=query, pageToken=page_token).execute()
        #print(response['messages'])
        for message_id in response['messages']:
            #print(message_id['id'])
            message = service.users().messages().get(userId=user_id, id=message_id['id'], format='raw').execute()
            msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
            mime_msg = email.message_from_string(msg_str)
            print(mime_msg)

あらら、エラーなっちゃった・・・。

ふーん、bytes渡してっていったじゃんっとおっしゃられている。
そんなの聞いてないし。どうせいつものPython2.Xと3.Xの違いでしょ。Examplesは2.Xってわけね。
bytesに変換するの面倒臭いから、email.messageへの変換諦めてとりあえず、base64デコードしたのを標準出力して終わりにしよ。

def printMessages(service, user_id, query=''):
    response = service.users().messages().list(userId=user_id, q=query).execute()
    if 'messages' in response:
        #print(response['messages'])
        for message_id in response['messages']:
            #print(message_id['id'])
            message = service.users().messages().get(userId=user_id, id=message_id['id'], format='raw').execute()
            msg_str = base64.urlsafe_b64decode(message['raw'])
            print(msg_str)
            #msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
            #mime_msg = email.message_from_string(message['raw'])
            #print(mime_msg)
        
    while 'nextPageToken' in response:
        page_token = response['nextPageToken']
        response = service.users().messages().list(userId=user_id, q=query, pageToken=page_token).execute()
        for message_id in response['messages']:
            message = service.users().messages().get(userId=user_id, id=message_id['id'], format='raw').execute()
            msg_str = base64.urlsafe_b64decode(message['raw'])
            print(msg_str)
            #msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
            #mime_msg = email.message_from_string(message['raw'])
            #print(mime_msg)

よし、出た出た。

ということで、email.messageへの変換はまた来週。ではSee You!!

[ 作成したプログラムの全量 ]

# -*- coding: utf-8 -*-
from __future__ import print_function
import httplib2
import os
import base64
#import email

from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage

try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/gmail-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/gmail.readonly'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Gmail API Python Quickstart'

def get_credentials():
    """Gets valid user credentials from storage.
    If nothing has been stored, or if the stored credentials are invalid,
    the OAuth2 flow is completed to obtain the new credentials.
    Returns:
        Credentials, the obtained credential.
    """
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir,
                                   'gmail-python-quickstart.json')

    store = Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else: # Needed only for compatibility with Python 2.6
            credentials = tools.run(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials

def printLabels(service, user_id):
    results = service.users().labels().list(userId=user_id).execute()
    labels = results.get('labels', [])

    if not labels:
        print('No labels found.')
    else:
      print('Labels:')
      for label in labels:
        print(label['name'])    

def printMessages(service, user_id, query=''):
    response = service.users().messages().list(userId=user_id, q=query).execute()
    if 'messages' in response:
        #print(response['messages'])
        for message_id in response['messages']:
            #print(message_id['id'])
            message = service.users().messages().get(userId=user_id, id=message_id['id'], format='raw').execute()
            msg_str = base64.urlsafe_b64decode(message['raw'])
            print(msg_str)
            #msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
            #mime_msg = email.message_from_string(message['raw'])
            #print(mime_msg)
        
    while 'nextPageToken' in response:
        page_token = response['nextPageToken']
        response = service.users().messages().list(userId=user_id, q=query, pageToken=page_token).execute()
        for message_id in response['messages']:
            message = service.users().messages().get(userId=user_id, id=message_id['id'], format='raw').execute()
            msg_str = base64.urlsafe_b64decode(message['raw'])
            print(msg_str)
            #msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
            #mime_msg = email.message_from_string(message['raw'])
            #print(mime_msg)

def main():
    """Shows basic usage of the Gmail API.
    Creates a Gmail API service object and outputs a list of label names
    of the user's Gmail account.
    """
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('gmail', 'v1', http=http)

    #printLabels(service, 'me')
    printMessages(service, 'me', 'after:2018/06/11 before:2018/06/12 subject:Logwatch')

if __name__ == '__main__':
    main()