2
2

More than 1 year has passed since last update.

Python Gmailデータ取得

Last updated at Posted at 2022-08-12

前提

以前作成した下記記事の環境からスタート

GCP設定

クレデンシャルを作成
GCPのコンソール上でAPIとサービス > 認証情報
OAuth クライアント IDの作成
アプリケーションの種類:デスクトップ

→ JSONをダウンロードして、appと同じ階層にclient_id.jsonとして作成

アクセス許可

gmail.py

import json
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
import httplib2

SCOPES = 'https://www.googleapis.com/auth/gmail.readonly'
CLIENT_SECRET_FILE = 'client_id.json'
USER_SECRET_FILE = 'credentials-gmail.json'

def create_service():
    store = Storage(USER_SECRET_FILE)
    credentials = store.get()
    if not credentials:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = 'Python Gmail API'
        credentials = tools.run_flow(flow, store, None)
        print('認証結果を保存しました:' + USER_SECRET_FILE)
        print(json.dumps(credentials.to_json()))
    elif credentials.invalid:
        credentials.refresh(httplib2.Http())
        print(json.dumps(credentials.to_json()))
    return credentials

app.py

import os
from flask import Flask
import gmail

app = Flask(__name__)

@app.route("/")
def test ():
    gmail.create_service()
    return "ok"

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))

確認

  1. ターミナルでpython3 app.pyを実行
  2. 別ターミナルでcurl http://localhost:8080を実行
    → Gmailのアクセスを許可するかブラウザが起動する
    → 許可
    credentials-gmail.jsonがappと同じ階層に作成されていればOK!!

コード

先ほど作成したcreate_service関数の下にget_messagesの関数を作成

全体取得

def get_messages():
    credentials = create_service()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('gmail', 'v1', http=http)
    messages = service.users().messages()
    msg_list = messages.list(userId='me', maxResults=1).execute()
    for msg in msg_list['messages']:
        topid = msg['id']
        msg = messages.get(userId='me', id=topid).execute()
        print(msg)

※どんなデータが取得できるか見れる

件名取得

def get_messages():
    credentials = create_service()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('gmail', 'v1', http=http)
    messages = service.users().messages()
    msg_list = messages.list(userId='me', maxResults=1).execute()
    for msg in msg_list['messages']:
        topid = msg['id']
        msg = messages.get(userId='me', id=topid).execute()
    #  件名の取得
    for msg in msg_list['messages']:
        topid = msg['id']
        msg = messages.get(userId='me', id=topid).execute()
        for header in msg['payload']['headers']:
            if header['name'] == "Subject": 
                print(header['value'])

本文取得

def get_messages():
    credentials = create_service()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('gmail', 'v1', http=http)
    messages = service.users().messages()
    msg_list = messages.list(userId='me', maxResults=1).execute()
    for msg in msg_list['messages']:
        topid = msg['id']
        msg = messages.get(userId='me', id=topid).execute()
        # 本文の取得
        if(msg["payload"]["body"]["size"]!=0):
            decoded_bytes = base64.urlsafe_b64decode(
                msg["payload"]["body"]["data"])
            decoded_message = decoded_bytes.decode("UTF-8")
            print(decoded_message)
        else:
            #メールによっては"parts"属性の中に本文がある場合もある
            decoded_bytes = base64.urlsafe_b64decode(
                msg["payload"]["parts"][0]["body"]["data"])
            decoded_message = decoded_bytes.decode("UTF-8")
            print(decoded_message)

要約取得

def get_messages():
    credentials = create_service()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('gmail', 'v1', http=http)
    messages = service.users().messages()
    msg_list = messages.list(userId='me', maxResults=1).execute()
    for msg in msg_list['messages']:
        topid = msg['id']
        msg = messages.get(userId='me', id=topid).execute()
        # 要約の取得
        print(msg['snippet'])

添付ファイル取得(Excel)

downloadフォルダを作成しておく

def get_messages():
    row_list = []
    credentials = create_service()
    http = credentials.authorize(httplib2.Http())
    service = discovery.build('gmail', 'v1', http=http)
    messages = service.users().messages()
    msg_list = messages.list(userId='me', maxResults=1).execute()
    for msg in msg_list['messages']:
        topid = msg['id']
        msg = messages.get(userId='me', id=topid).execute()
        
        for part in msg['payload']['parts']:
            if 'filename' in part and part['filename'] and 'attachmentId' in part['body']:
                msgId = msg['id']
                att_id = part['body']['attachmentId']
                att = service.users().messages().attachments().get(userId='me',messageId=msgId,id=att_id).execute()
                data = att['data']
                file_info = base64.urlsafe_b64decode(data.encode('UTF-8'))
                excel = pd.ExcelFile(file_info)
                sheet = excel.parse("シート1", header=None)
                for row in sheet.iterrows():
                    row_str = ",".join(map(str, row))
                    row_list.append(row_str)
                row_data = '\n'.join(row_list)
                # csvの形になっているか確認
                with open("downloadフォルダ「パスのコピー」/test.csv", mode='w') as f:
                    f.buffer.write(str.encode(row_data))

requirements.txtの追記

flask
oauth2client
google-api-python-client

app.pyの変更
gmail.create_service() → gmail.get_messages()

  • ターミナル1でpython3 app.py
  • ターミナル2でcurl http://localhost:8080
    先ほど作成したdownloadフォルダにtest.csvとして格納されていればOK!

最後に

コード > 全体取得の部分でprint(msg)を見た時、かなり複雑なデータになっているなと感じました。
また、ボットから送られてくるメールだとデータ構造が違うということが起きるので作成したコードでもデータ取得できないことがあります。
メール内にある添付ファイル取得する処理も追記しましたが、これもデータを見てからではないと取れないことがあります。

参考文献

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2