title: Getting email message after IMAP IDLE command exists response
body: <p>Is it safe to use the total number of messages in the exists response as a way to then get the uid?</p>
  
  <blockquote>
    <p>7.3.1. EXISTS Response</p>
    
    <p>Contents:   none</p>
  
  <pre><code>  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.
  </code></pre>
    
    <p>Example:    S: * 23 EXISTS</p>
  </blockquote>
  
  <p>In app output</p>
  
  <pre><code>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'
  </code></pre>
  
  <p>Modified version of twisted's IMAP Client Protocol</p>
  
  <pre><code>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
  </code></pre>