ChatGPT APIを用いて秘書さん(メール返信判定ツール)を作成してみた。

メールをチェックして返信が必要なメールを教えてくれる秘書がいたら便利ですよね。

そこで、ChatGPT APIを用いて、メールの返信が必要か判定してSlackに通知するツールを作成してみました。

※ より判定の精度が上がるプロンプトを作成出来たら、コメントで教えて頂けますととても嬉しいです！

今回のツールは常に稼働中にした方が良いので、AWSのインスタンスにのせます。

この記事で使用するインスタンスのインスタンスイメージはubuntuです。

手順は以下です。
1.  Gmailのアプリパスワードを取得する
1. Slack APIのダッシュボードで botを作成して、スコープを設定してBot User OAuth Tokenを取得する
1. インスタンスでメール返信判定ツールを実行中にする

# 1. Gmailのアプリパスワードを取得する
はじめに、この返信判定ツールでは、ツールがメールを既読にしてしまうので、判定するメールを転送するメールを設定して、転送先のメールアドレスでこちらの設定をすることをおすすめします。

まず、返信を判定するメールの[Googleアカウントの設定のセキュリティ](https://myaccount.google.com/u/6/security?rapt=AEjHL4OwRDewn_ihcDMhOp7YdQefoK6Tbk6tixrauTw6_KzzoaTIJ-bA5izTG3VQfKK-V73D0xvTQcpY5onR4ZGQP0FATquuXQ)を開いて、2段階認証を設定します。

2段階認証を設定したら、設定ページの検索欄で、アプリパスワードと検索して、[アプリパスワードの設定ページ](https://myaccount.google.com/u/3/apppasswords?rapt=AEjHL4OcQi6WUucLAW0d1ENnZ3LKXeRBGkjDiJylaIgtFAmqEx2yjQT18dGHM2mKc1YA5vgW2XlqijJA4KVeMUERmhCb-wc3Vw&pageId=none)にいきます。

アプリパスワードの設定ページで、アプリを作成します。
その他を押して、好きな名前を入れて、作成を押します。すると、16桁のアプリパスワードが発行されるので、こちらをメモします。

これで、⒈Gmailのアプリパスワードを取得するは完了です。

# 2. Slack APIのダッシュボードで botを作成して、スコープを設定してBot User OAuth Tokenを取得する
まず、 botのアプリを作成します。
メール返信判定ツールの通知を受け取りたいチャンネルのあるワークスペースにログインしてから、[Slack  APIのダッシュボード](https://api.slack.com/apps)にアクセスして、ページの上の方にある緑の「Create New App」のボタンを押します。
開いたメニューで、from scratchの方を選択します。アプリ名は好きな名前、ワークスペースは通知を受け取るチャンネルのあるワークスペースにして、Create Appを押します。

アプリが出来たら、左のメニューからOAuth & Permissionsを押します。
OAuth & Permissionsのページが開いたら、Bot Token Scopesのところまで下にスクロールして、以下のスコープを設定します。

必要なスコープ
chat:write

スコープを設定したら、上にスクロールして、OAuth Tokens for Your Workspaceからアプリをワークスペースにインストールします。
アプリをインストールしたら、OAuth Tokens for Your Workspaceの欄にBot User OAuth Tokenが生成されるので、こちらをコピーしてメモします。

ついでに、作成したbotをbotから通知を送るチャンネルに追加しておきます。

これで、2. Slack APIのダッシュボードで botを作成して、スコープを設定してBot User OAuth Tokenを取得する、は完了です！

# 3. インスタンスでメール返信判定ツールを実行中にする
まず、インスタンスにSSH接続します。

インスタンスのコンソールが開いたら以下をインストールします。

aptのアップデート
```
sudo apt update
```

pipのインストール
```
sudo apt install python3-pip
```

slack sdkのインストール
```
sudo pip install slack-sdk
```

openaiのインストール
```
sudo pip install openai
```

次にpythonのファイルを保存するディレクトリを作成します。
```
mkdir ディレクトリ名
```

作成したディレクトリに移動します。
```
cd ディレクトリ名
```

作成したディレクトリでファイルを作成します。
```
nano ファイル名
```

作成したファイルの中に下記のbotのコードを入れて、ctrl oでファイルを保存して、ctrl xでファイルを閉じます。

コードには、以下を入れてください。
EMAIL_ADDRESSは、⒈で設定したメールアドレス
EMAIL_PASSWORD は、⒈で取得したアプリパスワード
SLACK_BOT_TOKEN は、⒉で取得したトークン
SLACK_CHANNEL_ID は、ツールが通知を送るチャンネル。テストというチャンネルであれば、#テスト。botを指定したチャンネルに入れておく。
openai.api_key は、openaiのキー

```Python
import imaplib
import email
from email.header import decode_header
import base64
import openai
import os
import time
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

# Email settings
EMAIL_ADDRESS = "YOUR_EMAIL_ADDRESS"
EMAIL_PASSWORD = "YOUR_EMAIL_PASSWORD"

# Slack settings
SLACK_BOT_TOKEN = "YOUR_SLACK_BOT_TOKEN"
SLACK_CHANNEL_ID = "YOUR_SLACK_CHANNEL_ID"

# OpenAI API Key
openai.api_key = "your_openai_api_key"



def process_email(email_body):
    truncated_email_body = email_body[:1000]
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "下記のメールを返信が「必要」か「不要」か一言で答える。必要な場合「必要」、不要の場合「不要」と答える。"},
            {"role": "user", "content": truncated_email_body},
        ]
    )

    t = response["choices"][0]["message"]["content"]
    print(t)
    return response["choices"][0]["message"]["content"]

def send_slack_message(title, body):
    client = WebClient(token=SLACK_BOT_TOKEN)
    try:
        response = client.chat_postMessage(
            channel=SLACK_CHANNEL_ID,
            text=f"タイトル: {title}\n本文: {body}\n返信が必要なメールです。"
        )
    except SlackApiError as e:
        print(f"Error sending message: {e}")

def check_new_emails():
    # Connect to IMAP server
    mail = imaplib.IMAP4_SSL("imap.gmail.com")
    mail.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
    mail.select("inbox")

    _, search_data = mail.search(None, "UNSEEN")
    for num in search_data[0].split():
        _, msg_data = mail.fetch(num, "(RFC822)")
        for response_part in msg_data:
            if isinstance(response_part, tuple):
                msg = email.message_from_bytes(response_part[1])
                subject, encoding = decode_header(msg["Subject"])[0]
                if isinstance(subject, bytes):
                    subject = subject.decode(encoding)

                if msg.is_multipart():
                    for part in msg.walk():
                        content_type = part.get_content_type()
                        content_disposition = str(part.get("Content-Disposition"))
                        try:
                            body = part.get_payload(decode=True).decode()
                        except:
                            pass
                        if content_type == "text/plain" and "attachment" not in content_disposition:
                            email_body = body
                            break
                else:
                    email_body = msg.get_payload(decode=True).decode()

                email_decision = process_email(email_body)

                if "必要" in email_decision:
                    send_slack_message(subject, email_body)

    # Logout and close the connection to the IMAP server
    mail.logout()


if __name__ == "__main__":
    while True:
        try:
            check_new_emails()
            print("Checked for new emails.")
        except Exception as e:
            print(f"Error while checking emails: {e}")
        time.sleep(600)  # Check for new emails every 10 minutes (600 seconds)
```

一度、上手くファイルが作成されているか下記のコマンドで確認します。
```
find ~
```

上手くファイルが作成されていたら、screenを作成します。
```
screen -S スクリーン名
```

screen内でpythonで作成したファイルを実行します。
```
python3 ファイル名.py
```

ここまで出来たら10分おきにメールがチェックされますので、「返信して」などの返信が必要となるメールを先程設定したメールアドレスに送ってみて下さい。
メールがチェックされ以下のようにSlackに通知があれば、成功です！
![IMG_8202.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287642/0a206bfb-70cb-238c-f040-d85d2c11658e.jpeg)


# 最後に
これで誰にでも秘書を使えるようになりますね。
未だに私はGPT4がウェイティングなので、ドジっ子秘書を雇ってしまった感じになっていますが、これはこれでいいです。
また何か作ってみます。