Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gmail の内容を Slack 通知したい #10

Open
laughk opened this issue May 25, 2019 · 17 comments
Open

Gmail の内容を Slack 通知したい #10

laughk opened this issue May 25, 2019 · 17 comments

Comments

@laughk
Copy link
Owner

laughk commented May 25, 2019

(第99回)Python mini Hack-a-thon - connpass

いろいろ調べながら試行錯誤することになりそうなので Issue にしとく
とりあえず以下のことやりたい

  • 色々事情があって、一部自分に飛んでくる mail を家庭 Slack に通知したい
  • Gmail ( GCP? ) の API を上手く使ってよしなにしたい
  • とりあえず Slack には incoming webhook で雑に投げ込めればよい。
@laughk
Copy link
Owner Author

laughk commented May 25, 2019

参考になりそうなリンク

GCP Cloud functions

Gmail Push Notification API をお使いいただくことで、Gmail イベントを Cloud Pub/Sub トピックに送り、Cloud Functions と一緒に呼び出すことができます。

Gmail の API

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

👀 この辺にサンプルがある

https://github.com/gsuitedevs/python-samples/tree/master/gmail

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

💭 quickstart.py は Gmail の label 一覧を表示するやつっぽい

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

初回起動の際に認証を求められた

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

cloud functions に乗っけるスクリプトには CLI モードを有効にしてローカルでデバッグ、行けそうなら cloud functions へデプロイという感じでいいだろうか。

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

この辺をいじればやりたいことができるかも?

https://github.com/gsuitedevs/python-samples/blob/master/gmail/quickstart/quickstart.py#L49-L53

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

Gmail の API にどうアクセスしていくかのイメージが Quickstart だけだと掴めなかったけどここの記事のコードでちょっとイメージできたかも。

ref. Pythonを使ってGmail APIからメールを取得する - Qiita

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

例えば特定の人とのやり取りと取りたい時

    query = '(from OR to OR cc):u****@*******.co.jp'
    results = service.users()\
        .messages()\
        .list(userId='me', q=query)\
        .execute()
    print(results)

結果 (雰囲気)

{
  'messages': [{'id': '16*********', 'threadId': '16************'},
              {'id': '16*********', 'threadId': '16************'},
              {'id': '16*********', 'threadId': '16************'},
              {'id': '16*********', 'threadId': '16************'},
              {'id': '16*********', 'threadId': '16************'},
              {'id': '16*********', 'threadId': '16************'},
              {'id': '16*********', 'threadId': '16************'},
              {'id': '16*********', 'threadId': '16************'},
              {'id': '16*********', 'threadId': '16************'}],
 'resultSizeEstimate': 23
}

ここまでだと、あくまで個別にアクセスするための ID 情報だけが取れるっぽい

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

特定のメッセージのとり方

Users.messages: get | Gmail API | Google Developers

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

message.get したときのレスポンス

Users.messages | Gmail API | Google Developers

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

snippet だとメッセージ本文全体が取れないんだよなー
payload.body からじゃないとダメそう

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

payload.body, base64url って形式で encode されてるみたい

https://developers.google.com/gmail/api/v1/reference/users/messages/attachments#resource

The body data of a MIME message part as a base64url encoded string. May be empty for MIME container types that have no message body or when the body data is sent as a separate attachment. An attachment ID is present if the body data is contained in a separate attachment.

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

なんか文字コード壊れてる... ? なんか上手く decode できない 😭

  • base64 -> bytes 🙆‍♀️
  • bytes -> utf-8 (str) 😵
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/encodings/utf_8_sig.py", line 23, in decode
    (output, consumed) = codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 12-13: invalid continuation byte

ちなみに `.decode('utf-8', 'ignore') してみるも、ほとんどがぐっちゃぐちゃで読めたものではない...

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

なんか文字コード壊れてる... ? なんか上手く decode できない sob

base64url が曲者だったっぽい。
https://github.com/ploopkazoo/python-base64url/blob/master/base64url.py のコードを一部流用させてもらったら行けそうな気配。

body_data に payload.body.data が入ってる前提

before

            try:
                body_64decoded = base64.b64decode(body_data)
                print(f'payload.body.data(64decoded): {body_64decoded}')
            except:
                print(f'payload.body.data(64decoded): (passed)')

            try:
                body_decoded = bytes(body_64decoded).decode()
                print(f'payload.body.data(decoded): {body_decoded}')
            except:
                print(f'payload.body.data(decoded): (passed)')

after

            try:
                body_64decoded = base64.b64decode(base64urldecode(body_data))
                print(f'payload.body.data(64decoded): {body_64decoded}')
            except:
                print(f'payload.body.data(64decoded): (passed)')

            try:
                body_decoded = bytes(body_64decoded).decode()
                print(f'payload.body.data(decoded): {body_decoded}')
            except:
                print(f'payload.body.data(decoded): (passed)')

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

https://github.com/ploopkazoo/python-base64url/blob/master/base64url.py のコードを一部流用させてもらったら行けそうな気配。

公式ライブラリでこのへんやってくれるのがあるらしいので調べて差し替える

@laughk
Copy link
Owner Author

laughk commented May 25, 2019

公式ライブラリでこのへんやってくれるのがあるらしいので調べて差し替える

@HayaoSuzuki が教えてくれた thx!!

https://docs.python.org/ja/3/library/base64.html#base64.urlsafe_b64decode

ref. https://twitter.com/CardinalXaro/status/1132213056098820101

@laughk laughk changed the title pyhack#99 Gmail の内容を Slack 通知したい Jun 22, 2019
@laughk
Copy link
Owner Author

laughk commented Jul 14, 2019

Webhook が最近新しいものが出てきている。

これが結構ややこしい。形式は以下のツールで色々手探りしてる
https://api.slack.com/tools/block-kit-builder

return [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"メールが来てるよ :email:",
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*Subject* {self.subject}\n*from*: {self.from_}\n*date*: {self.date}",
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*本文*\n```{self.body}\n```"
}
},
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant