我在我的服务器上运行此脚本,以便在新邮件到达时发送推送通知。它工作得很好,但有时脚本会因下面的错误而崩溃。我不知道它为什么会崩溃,我不能自己重现它。当它失败时,它不会进入except部分。
我试过了:except self.abort:
except M.abort:
except M.error:
知道为什么会崩溃吗?
对于短期解决方案,是否可以终止所有线程并从except
部分重新启动脚本?
.......
import socket, ssl, json, struct, re
import imaplib2, time
from threading import *
# enter gmail login details here
USER="YOUR.NAME@gmail.com"
PASSWORD="YOUR-GMAIL-PASSWORD"
# enter device token here
deviceToken = 'XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX '
deviceToken = deviceToken.replace(' ','').decode('hex')
currentBadgeNum = -1
def getUnseen():
(resp, data) = M.status("INBOX", '(UNSEEN)')
print data
return int(re.findall("UNSEEN (\d)*\)", data[0])[0])
def sendPushNotification(badgeNum):
global currentBadgeNum, deviceToken
if badgeNum != currentBadgeNum:
currentBadgeNum = badgeNum
thePayLoad = {
'aps': {
# 'alert':'Hello world!',
'sound':'',
'badge': badgeNum,
},
'test_data': { 'foo': 'bar' },
}
theCertfile = 'certfile.pem'
theHost = ('gateway.sandbox.push.apple.com', 2195)
data = json.dumps(thePayLoad)
theFormat = '!BH32sH%ds' % len(data)
theNotification = struct.pack(theFormat, 0, 32, deviceToken, len(data), data)
ssl_sock = ssl.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), certfile=theCertfile)
ssl_sock.connect(theHost)
ssl_sock.write(theNotification)
ssl_sock.close()
print "Sent Push alert."
# This is the threading object that does all the waiting on
# the event
class Idler(object):
def __init__(self, conn):
self.thread = Thread(target=self.idle)
self.M = conn
self.event = Event()
def start(self):
self.thread.start()
def stop(self):
# This is a neat trick to make thread end. Took me a
# while to figure that one out!
self.event.set()
def join(self):
self.thread.join()
def idle(self):
# Starting an unending loop here
while True:
# This is part of the trick to make the loop stop
# when the stop() command is given
if self.event.isSet():
return
self.needsync = False
# A callback method that gets called when a new
# email arrives. Very basic, but that's good.
def callback(args):
if not self.event.isSet():
self.needsync = True
self.event.set()
# Do the actual idle call. This returns immediately,
# since it's asynchronous.
self.M.idle(callback=callback)
# This waits until the event is set. The event is
# set by the callback, when the server 'answers'
# the idle call and the callback function gets
# called.
self.event.wait()
# Because the function sets the needsync variable,
# this helps escape the loop without doing
# anything if the stop() is called. Kinda neat
# solution.
if self.needsync:
self.event.clear()
self.dosync()
# The method that gets called when a new email arrives.
def dosync(self):
print "Got an event!"
numUnseen = getUnseen()
sendPushNotification(numUnseen)
try:
# Set the following two lines to your creds and server
print 'starting'
global M
M = imaplib2.IMAP4_SSL("imap.gmail.com")
M.login(USER, PASSWORD)
# We need to get out of the AUTH state, so we just select
# the INBOX.
#M.list()
M.select('INBOX', readonly=True)
numUnseen = getUnseen()
getText()
#print M.status("INBOX", '(UNSEEN)')
# Start the Idler thread
sendPushNotification(numUnseen)
idler = Idler(M)
idler.start()
# Sleep forever, one minute at a time
while True:
time.sleep(60)
except self.abort:
print 'we had a problem, dont worry! Ill fix it!'
idler = Idler(M)
finally:
# Clean up.
idler.stop()
idler.join()
M.close()
# This is important!
M.logout()
.....................
.....................
17:35.99 imap.gmail.com reader last 20 log messages:
17:36.02 imap.gmail.com handler last 20 log messages:
Got an event!
Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/threading.py", line 551, in __bootstrap_inner
self.run()
File "/usr/local/lib/python2.7/threading.py", line 504, in run
self.__target(*self.__args, **self.__kwargs)
File "serverx.py", line 229, in idle
self.dosync()
File "serverx.py", line 235, in dosync
numUnseen = getUnseen()
File "serverx.py", line 150, in getUnseen
(resp, data) = M.status("INBOX", '(UNSEEN)')
File "/home/myuser/lib/python2.7/imaplib2/imaplib2.py", line 1121, in status
return self._simple_command(name, mailbox, names, **kw)
File "/home/myuser/lib/python2.7/imaplib2/imaplib2.py", line 1607, in _simple_command
return self._command_complete(self._command(name, *args), kw)
File "/home/myuser/lib/python2.7/imaplib2/imaplib2.py", line 1305, in _command
raise self.abort('connection closed')
abort: connection closed
答案 0 :(得分:0)
尝试捕捉imaplib2.IMAP4.abort
:
try:
# ...
except imaplib2.IMAP4.abort:
# Oh no! An error!
答案 1 :(得分:0)
我试图解决同样的问题而且我已经成功了。
您需要使用self.M.idle(callback=callback)
包装try-except
,然后在主线程中重新提升它。然后通过重新运行主线程中的代码来重新启动连接来处理异常。
您可以在此答案中找到解决方案的更多详细信息和可能的原因:https://stackoverflow.com/a/50163971/1544154
完整的解决方案在这里:https://www.github.com/Elijas/email-notifier