目的
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のメールを確認しよう
-- GoogleのAPIを有効にするのに参考にさせていただきました。
Pythonを使ってGmail APIからメールを取得する
-- Gmail APIの使い方を参考にさせていただきました。
ソースコード
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から未読のメッセージを取得し、返信するようにしています。
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ではそれらを返信する際の文字列に変換して返すようにしています。
結果
送信主の名前は消していますが、名前、題名を取得し、返信することができました!
今後について
今後以下の2つを実装していきたいです。
- プッシュ機能を使って自動で未読メールを取得し、送るようにする。
- 「メール」と打つのではなく、ボタンを設置して、そのボタンで未読メールを取得できるようにする。