[tor-commits] [flashproxy/master] Use UIDs to identify messages in FETCH and COPY commands.

dcf at torproject.org dcf at torproject.org
Thu Oct 4 00:34:59 UTC 2012


commit b3e627d4ca8d91d8ddc6e960cdb76d47c67e07e2
Author: David Fifield <david at bamsoftware.com>
Date:   Wed Oct 3 15:01:04 2012 -0700

    Use UIDs to identify messages in FETCH and COPY commands.
    
    Otherwise there is a race condition; what we think of as message 1 could
    change between FETCH and COPY.
---
 facilitator/facilitator-email-poller |   21 ++++++++++++++++++---
 1 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/facilitator/facilitator-email-poller b/facilitator/facilitator-email-poller
index cfae523..9c9b7d4 100755
--- a/facilitator/facilitator-email-poller
+++ b/facilitator/facilitator-email-poller
@@ -5,6 +5,7 @@ import getopt
 import imaplib
 import math
 import os
+import re
 import socket
 import ssl
 import stat
@@ -239,6 +240,17 @@ def handle_message(msg):
     log(u"registering %s" % safe_str(fac.format_addr(client_addr)))
     fac.put_reg(FACILITATOR_ADDR, client_addr)
 
+def imap_get_uid(imap, index):
+    typ, data = imap.fetch(str(index), "(UID)")
+    if data[0] is None:
+        return None
+    assert typ == "OK"
+    # This grepping for the UID is bogus, but imaplib doesn't properly break up
+    # the list of name-value pairs for us.
+    m = re.match(r'^\d+\s+\(.*\bUID\s+(\d+)\b.*\)\s*$', data[0])
+    assert m is not None
+    return m.group(1)
+
 def imap_empty_trash(imap):
     typ, data = imap.select("[Gmail]/Trash")
     imap.store("1:*", "+FLAGS", "\\Deleted")
@@ -266,17 +278,20 @@ def imap_loop(imap):
             while True:
                 # Grab message 1 on each iteration; remaining messages shift down so
                 # the next message we process is also message 1.
-                typ, data = imap.fetch(1, "(BODY[])")
-                if data[0] is None:
+                uid = imap_get_uid(imap, "1")
+                if uid is None:
                     break
 
+                typ, data = imap.uid("FETCH", uid, "(BODY[])")
+                assert typ == "OK"
+
                 try:
                     msg = email.message_from_string(data[0][1])
                     handle_message(msg)
                 except Exception, e:
                     log("Error processing message, deleting anyway: %s" % str(e))
 
-                imap.copy(1, "[Gmail]/Trash")
+                imap.uid("COPY", uid, "[Gmail]/Trash")
                 # Attempting to delete from All Mail here would have no effect.
                 # Messages disappear from All Mail when they are deleted from Trash
                 # in the next step.





More information about the tor-commits mailing list