commit b3e627d4ca8d91d8ddc6e960cdb76d47c67e07e2 Author: David Fifield david@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.
tor-commits@lists.torproject.org