使用存在响应中的消息总数作为获取 uid 的方法是否安全?
7.3.1. 存在响应
内容:无
The EXISTS response reports the number of messages in the mailbox. This response occurs as a result of a SELECT or EXAMINE command, and if the size of the mailbox changes (e.g., new messages). The update from the EXISTS response MUST be recorded by the client.
示例:S: * 23 EXISTS
应用内输出
2013-02-02 01:24:42-0500 [IMAP4Client (TLSMemoryBIOProtocol),client] C: '0005 IDLE'
2013-02-02 01:24:42-0500 [IMAP4Client (TLSMemoryBIOProtocol),client] S: '+ idling'
2013-02-02 01:25:17-0500 [IMAP4Client (TLSMemoryBIOProtocol),client] S: '* 6 EXISTS'
2013-02-02 01:25:47-0500 [IMAP4Client (TLSMemoryBIOProtocol),client] S: '* 7 EXISTS'
twisted 的 IMAP 客户端协议的修改版本
class IMAP4Client(imap4.IMAP4Client):
"""
A client with callbacks for greeting messages from an IMAP server and new messages.
"""
greetDeferred = None
def __init__(self, *args, **kw):
# is IDLE active
self.idle_active = False
# do we want to support IDLE
self.idle_enabled = False
imap4.IMAP4Client.__init__(self, *args, **kw)
def serverGreeting(self, caps):
self.serverCapabilities = caps
if self.greetDeferred is not None:
d, self.greetDeferred = self.greetDeferred, None
d.callback(self)
def enable_IDLE(self):
print "Enabling Idle...."
self.idle_enabled = True
if self.queued == []:# if there is no current command
# issue the idle command
cmd = Command("IDLE", continuation = self.idle_continuation)
d = self.sendCommand(cmd)
# THEN mark it active NOT BEFORE as, if IDLE is active when a command is sent (such as the above IDLE command) it stops IDLE by sending the DONE line
self.idle_active = True
d.addCallback(self.idle_done)
return d
else:
pass # IDLE will be enables when queued commands in waiting are done
def lineReceived(self, line):
print "S: %s" % str(repr(line))
return imap4.IMAP4Client.lineReceived(self, line)
def sendLine(self, line):
print "C: %s" % str(repr(line))
return imap4.IMAP4Client.sendLine(self, line)
def idle_continuation(self, *args, **kw):
pass# ignore for now
def sendCommand(self, cmd):
cmd.defer = Deferred()
# checks to see if IDLE command can be enabled when this command is done
cmd.defer.addCallback(self.command_done)
if self.idle_active: # if we are waiting for IDLE
self.sendLine("DONE")
# append it to the queue and wait for the idle deferred callback
self.queued.append(cmd)
return cmd.defer
if self.waiting:
self.queued.append(cmd)
return cmd.defer
t = self.makeTag()
self.tags[t] = cmd
self.sendLine(cmd.format(t))
self.waiting = t
self._lastCmd = cmd
return cmd.defer
def command_done(self, result):
print "A command was finished"
print "Waiting %s" % self.waiting
print self.queued
print "IDLE Enabled %s" % self.idle_enabled
# cannot use if not self.waiting so check if the command queue is empty
empty_queue = (self.queued == [])
if empty_queue and self.idle_enabled: # yay no commands enable IDLE
print "Enabling idle"
self.idle_active = True
# issue the command
self.idle_active = True
cmd = Command("IDLE", continuation = self.idle_continuation)
d = self.sendCommand(cmd)
d.addCallback(self.idle_done)
return d
return result
def idle_done(self, result):
print "IDLE Done"
self.idle_active = False
# twisted's own handling of the command queue should handle sending the next command
# so there is no need to grab the next command as when the OK Response after DONE
# trigger it