質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
IMAP

IMAP (Internet Message Access Protocol) とは、メールサーバー上の電子メールデータを操作するためのプロトコルです。

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

コマンドプロンプト

コマンドプロンプト(cmd.exe)はMicrosoftによって提供されているコマンドラインインタプリタです。OS/2・Windows CE・Windows NTで使用可能です。

メール

メールは、コンピュータネットワークを利用し、 情報等を交換する手段のことです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

2回答

8459閲覧

メール受信をトリガーとして別ファイルを起動させるプログラムが接続エラーの連続

zzzTKG

総合スコア7

IMAP

IMAP (Internet Message Access Protocol) とは、メールサーバー上の電子メールデータを操作するためのプロトコルです。

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

コマンドプロンプト

コマンドプロンプト(cmd.exe)はMicrosoftによって提供されているコマンドラインインタプリタです。OS/2・Windows CE・Windows NTで使用可能です。

メール

メールは、コンピュータネットワークを利用し、 情報等を交換する手段のことです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/05/10 05:57

編集2020/05/11 09:14

受け取ったメールをトリガーとして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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zzzTKG

2020/05/10 07:21

自分の理解不足で申し訳ないのですが,提示して頂いたURL先のコードは具体的に何をするものなのでしょうか? プッシュ通知を受け取るために接続することはbanされず,プッシュ通知受信をトリガーにすればよい,ということですか?
hoshi-takanori

2020/05/10 07:47

自分も詳しくないので解説はできません。参考情報としてお示ししただけです。 年寄りの愚痴で申し訳ありませんが、最近の初心者さんは気軽にスクレイピングとかボット開発とかしてて、いい世の中になったと思う一方、過去にはスクレイピングで逮捕された人もいますし、コードをちょっと間違えれば無限に投稿し続ける壊れたボットになることもありうるわけで、自分のパソコンが壊れるだけでなく、他人に迷惑をかける可能性があることを認識して、自分が何をしているのかをきちんと理解した上でコードを書いて欲しいものだと思っております。
zzzTKG

2020/05/10 08:30

そのように仰られるからには解説のできないソースを示すのは如何なものかと思いますが. 因みにこのプログラムは身内でDiscordを使って遊ぶためのものですし,メールアドレスもbotも全てこのためだけに作ったものなので問題はないです.タイムアウトエラーと接続エラーは何が起きているか理解できたものの,三回目のエラーは内容が分からなかったので投稿させて頂きました.自分の理解できないコードは書かないように努めています.
hoshi-takanori

2020/05/10 09:13

discord の件は私が誤解していました。大変失礼しました。
guest

回答2

0

回答では無いのですが、コードを書くので回答欄に書きます。

エラー時に自分自身を再帰的に起動していると、エラーの度にプロセスが増えるので、エラー多発時にとんでもないことになります。

最初、

Python

1while True: 2 try: 3 MailCheck() 4 time.sleep(5) 5 except KeyboardInterrupt: 6 print('Bye') 7 gmail.close() 8 gmail.logout() 9 exit(0) 10 except TimeoutError: 11 time.sleep(60) 12 except ConnectionResetError: 13 time.sleep(60)

と、思ったのですが、Gmailとの後始末をエラー発生箇所別にする必要がありそうなので、

エラーの例外をキャッチせず、エラー発生時にはPythonプログラム自体はエラーで終了するようにして、バッチファイル側で、ループするのが簡単かと思います。

CMD

1:LOOP 2ImapMail.py 3if errorlevel 1 goto LOOP

5秒が短すぎでは?というのは同意ですね。

投稿2020/05/10 13:55

otn

総合スコア85766

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

socket まわりのエラーなので、他の環境では再現が難しいかもしれませんね...

コードの中で無限ループで繰り返していますが、他の Google への接続が残っていて、複数の接続が発生していたりしていないでしょうか?

複数の接続が残っている状態であれば、同じアカウントでの同時接続数オーバー等の理由で、Google から接続拒否されているのかもしれません。

たとえば...

  • ループの待ち時間を現在の5秒から 30秒や1分ぐらいに長くすると状況は変わるでしょうか?

  • 最初にログインしたままでメールのチェックではなく、MailCheck 関数の中で、 Gmail login 〜 mail check 〜 Gmail close の処理を毎回処理させると 状況は変わりますか?

投稿2020/05/10 13:39

CHERRY

総合スコア25216

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問