受け取ったメールをトリガーとしてdiscord botを起動するプログラム
現在,PythonでImapによりメール受信をトリガーとして別ファイルのDiscord Botを実行するプログラムを書いています.1日中メールを監視させておきたいのですが,しばらくすると接続エラーと思われるエラーが出てきました,その度に,そのエラーをキャプチャして再起動させるようコードを追加していったのですが,次々に新たなエラーが長時間放置していると発生します.一回目から三回目にかけて,エラーを吐き出すまでの時間は長くなっていたように思います.
プログラムはコマンドプロンプトからstart /b cmd /c ImapMail.pyで実行しています.
原因と対応についてご教授願います.
一回目のエラー(3時間程)
Traceback (most recent call last): File "C:\python\ImapMail.py", line 17, in <module> MailCheck() File "C:\python\ImapMail.py", line 10, in MailCheck gmail.select('inbox') File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 747, in select typ, dat = self._simple_command(name, mailbox) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1205, in _simple_command return self._command_complete(name, self._command(name, *args)) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1022, in _command_complete typ, data = self._get_tagged_response(tag, expect_bye=logout) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1148, in _get_tagged_response self._get_response() File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1050, in _get_response resp = self._get_line() File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1158, in _get_line line = self.readline() File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 314, in readline line = self.file.readline(_MAXLINE + 1) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\socket.py", line 669, in readinto return self._sock.recv_into(b) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\ssl.py", line 1241, in recv_into return self.read(nbytes, buffer) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\ssl.py", line 1099, in read return self._sslobj.read(len, buffer) TimeoutError: [WinError 10060] 接続済みの呼び出し先が一定の時間を過ぎても正しく応答しなかったため、接続できませんでした。または接続済みのホストが応答しなかったため、確 立された接続は失敗しました。
二回目のエラー(5時間程)
Traceback (most recent call last): File "C:\python\ImapMail.py", line 17, in <module> MailCheck() File "C:\python\ImapMail.py", line 10, in MailCheck gmail.select('inbox') File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 747, in select typ, dat = self._simple_command(name, mailbox) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1205, in _simple_command return self._command_complete(name, self._command(name, *args)) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1022, in _command_complete typ, data = self._get_tagged_response(tag, expect_bye=logout) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1148, in _get_tagged_response self._get_response() File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1050, in _get_response resp = self._get_line() File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1158, in _get_line line = self.readline() File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 314, in readline line = self.file.readline(_MAXLINE + 1) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\socket.py", line 669, in readinto return self._sock.recv_into(b) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\ssl.py", line 1241, in recv_into return self.read(nbytes, buffer) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\ssl.py", line 1099, in read return self._sslobj.read(len, buffer) ConnectionResetError: [WinError 10054] 既存の接続はリモート ホストに強制的に切断されました。
三回目(最終)のエラー(少なくとも7時間)
Traceback (most recent call last): File "C:\python\ImapMail.py", line 5, in <module> gmail = imaplib.IMAP4_SSL('imap.gmail.com') File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1297, in __init__ IMAP4.__init__(self, host, port) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 198, in __init__ self.open(host, port) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1310, in open IMAP4.open(self, host, port) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 303, in open self.sock = self._create_socket() File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 1300, in _create_socket sock = IMAP4._create_socket(self) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\imaplib.py", line 293, in _create_socket return socket.create_connection((host, self.port)) File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\socket.py", line 787, in create_connection for res in getaddrinfo(host, port, 0, SOCK_STREAM): File "C:\Users\Owner\AppData\Local\Programs\Python\Python38\lib\socket.py", line 918, in getaddrinfo for res in _socket.getaddrinfo(host, port, family, type, proto, flags): socket.gaierror: [Errno 11001] getaddrinfo failed
二回目のエラーを受けて書いたコード(三回目のエラーを吐き出しています)
Python
1import imaplib,TakagisanBot,time,os 2 3user = 'Gmailアドレス' 4password = 'パスワード' 5gmail = imaplib.IMAP4_SSL('imap.gmail.com') 6gmail.login(user, password) 7print('Run') 8 9def MailCheck(): 10 gmail.select('inbox') 11 action, [data] = gmail.search(None, 'UNSEEN') 12 for num in data.split(): 13 gmail.store(num, '+FLAGS', r'\SEEN') 14 os.system('TakagisanBot.py') 15try: 16 while True: 17 MailCheck() 18 time.sleep(5) 19except KeyboardInterrupt: 20 print('Bye') 21 gmail.close() 22 gmail.logout() 23except TimeoutError: 24 os.system('ImapMail.py') 25except ConnectionResetError: 26 os.system('ImapMail.py')
試したこと
エラーを吐く前はメールを送るとBotが起動し,正常な処理を行います.エラーを吐いてからメールを送ると起動せず,既読もつかなかったため,MailCheck()自体が動いてないようです.
環境
MacBook AirにBootCampで導入したWindows10 HomeにおいてPython 3.8.2をコマンドプロンプトからstart /b cmd /c ImapMail.pyにより実行しています.
追記
御意見を受けまして,コードに修正を加えてみました.エラーが出てこないかどうかを確認するため現在試験的に実行し,放置しています.
1.再帰的に呼び出されないよう,TakagisanBot.py側にチェック処理を入れ,チェックの結果を基にTakagisanBot.pyがTakagisan()を実行するという形にしました.
2.ログインが重複しないよう,TakagisanBot.pyからimportさせることでログイン処理を一回のみの実行にしています.
3.5秒のループが短いのではということですが,このプログラムの目的がメールでサクッとbotを起動させることなのでなるべく短い間隔でチェックを行いたいため,現段階では5秒で保持しています.
これはマズイなど,修正したことで問題が発生していましたらご指摘いただければと思います.
python
1#TakagisanBot.py 2import discord 3import random 4import Dice #自作 5import ResDice #自作 6import re 7import jaconv 8import sys 9import ImapMail #自作 10import time 11from datetime import datetime 12 13client = discord.Client() 14 15def NOW(): 16 print(datetime.now()) 17 18def Takagisan():#bot起動&それ以降の処理 19 @client.event 20 async def on_ready(): 21 NOW() 22 print("準備おっけー!") 23 print(client.user.name) 24 print(client.user.id) 25 print("で入るよ~.") 26 27 sidlist=[] 28 29 @client.event 30 async def on_message(message): 31 #bot処理 32 client.run('')#bot起動 33while True:#チェック処理ループです 34 if ImapMail.Check(): 35 Takagisan() 36 elif ImapMail.Check() is None: 37 pass 38 else: 39 ImapMail.Check() 40 time.sleep(5)
python
1#ImapMail.py 2import imaplib,psutil 3 4user = '' 5password = '' 6gmail = imaplib.IMAP4_SSL('imap.gmail.com') 7gmail.login(user, password) 8print('Run') 9 10def MailCheck(): 11 gmail.select('inbox') 12 action, [data] = gmail.search(None, 'UNSEEN') 13 for num in data.split(): 14 gmail.store(num, '+FLAGS', r'\SEEN') 15 return True 16 17def ProcessCheck(Program): 18 return Program in (p.name() for p in psutil.process_iter()) 19 20def Check(): 21 if ProcessCheck('TakagisanBot.py'): 22 return None 23 elif MailCheck(): 24 return True 25 else: 26 return False