Pythonを使ってGmailの未読メールを取得するLine Botを作った！

# 目的
Line BotでGmailからメールを取得し、未読のメッセージをの送信主、題名をLineに送る。

# 開発環境
* Flask==1.1.1
* line-bot-sdk==1.14.0 
* oauth2client==4.1.3
* httplib2==0.14.0
* google-api-python-client==1.7.11
* google-auth==1.6.3
* google-auth-httplib2==0.0.3
* google-auth-oauthlib==0.4.1

# 参考
[PythonでGmailのメールを確認しよう](https://news.mynavi.jp/article/zeropython-22/)
 -- GoogleのAPIを有効にするのに参考にさせていただきました。
[Pythonを使ってGmail APIからメールを取得する](https://qiita.com/orikei/items/73dc1ccc95d1872ab1cf)
 -- Gmail APIの使い方を参考にさせていただきました。

# ソースコード
```python:main.py
from flask import Flask, request, abort
 
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage, LocationMessage, VideoMessage,
    FollowEvent, UnfollowEvent, PostbackEvent, TemplateSendMessage,
    ButtonsTemplate, CarouselTemplate, CarouselColumn, PostbackTemplateAction
)
from linebot.exceptions import LineBotApiError

import os
import json
import sys
import re

import Gmail 
 
app = Flask(__name__)

YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]

line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)

@app.route("/callback", methods=['POST'])
def callback():
    signature = request.headers['X-Line-Signature']
 
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)
 
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    text = event.message.text
    user_id = event.source.user_id
    if 'メール' in text:
      mail = Gmail.GmailAPI()
      # get the reply message
      messages = mail.process_message()
      # reply
      line_bot_api.reply_message(
            event.reply_token,
            TextSendMessage(text=str(messages))
        )

if __name__ == "__main__":
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)
```
「メール」という文字列が入ったメッセージをBotが受け取ると、Gmailから未読のメッセージを取得し、返信するようにしています。

```python:Gmail.py
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools

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

    def ConnectGmail(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

    def GetMessageList(self):

        # connect to API
        service = self.ConnectGmail()

        MessageList = []

        query = 'is:unread'

        # get all the messages (maximum=20)
        messageIDlist = service.users().messages().list(userId='me',maxResults=20,q=query).execute()

        # if no messages, stop return error
        if messageIDlist['resultSizeEstimate'] == 0: 
            return 'error'
        # Get information about the mails
        for message in messageIDlist['messages']:
            row = {}
            MessageDetail = service.users().messages().get(userId='me',id=message['id']).execute()
            for header in MessageDetail['payload']['headers']:
                # get the senders of the messages
                if header['name'] == 'From':
                    row['from'] = header['value']
                # get the subject of the messages
                elif header['name'] == 'Subject':
                    row['subject'] = header['value']
            MessageList.append(row)
        return MessageList

    def process_message(self):
        messagelist = self.GetMessageList()
        # If there is no messages new, reply 'No message'
        if messagelist == 'error':
            reply = 'No message'
            return reply 

        # make reply message
        reply = ''
        for mlist in messagelist:
            from_name = mlist['from'].split('<')[0] + ':'
            sub = '「' + mlist['subject'] + '」'
            message = '{}\n{}'.format(from_name, sub)
            reply += message 
            reply += '\n\n'
        return reply
```
Gmail APIを使用し、GetMessageListでは未読メールの送信主、題名を取得し、process_messageではそれらを返信する際の文字列に変換して返すようにしています。

# 結果
![Screenshot_20200531-181629905 (1)_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297281/2291f546-e532-d577-90a2-023415dd1ceb.jpeg)
送信主の名前は消していますが、名前、題名を取得し、返信することができました！

# 今後について
今後以下の2つを実装していきたいです。

* プッシュ機能を使って自動で未読メールを取得し、送るようにする。
* 「メール」と打つのではなく、ボタンを設置して、そのボタンで未読メールを取得できるようにする。