commit 2721c1e44997020be3d3e405dc252cc20c08487e Author: David Fifield david@bamsoftware.com Date: Sat Jun 29 17:14:40 2013 -0700
Don't process email registrations older than 30 minutes old.
Based on a patch by Sukhbir. See #8285. --- ChangeLog | 6 +++++ facilitator/facilitator-email-poller | 42 +++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/ChangeLog b/ChangeLog index edd92a0..29d4bdb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,6 +31,12 @@ "client" and "relay" parameters. It serves the one given client and then stops. Patch by Arlo Breault. Fixes bug 9006.
+ o facilitator-email-poller ignores messages received a long time ago. + This is to fix the situation where facilitator-email-poller stops + running for some reason, comes back after some hours, and then + flushes a lot of no-longer-relevant registrations out to proxies. + Patch by Sukhbir Singh and David Fifield. Fixes bug 8285. + Changes in version 1.1 o Programs that use certificate pins now take a --disable-pin option that causes pins to be ignored. diff --git a/facilitator/facilitator-email-poller b/facilitator/facilitator-email-poller index 614cdc9..f520033 100755 --- a/facilitator/facilitator-email-poller +++ b/facilitator/facilitator-email-poller @@ -1,6 +1,9 @@ #!/usr/bin/env python
+import calendar +import datetime import email +import email.utils import getopt import imaplib import math @@ -24,6 +27,9 @@ DEFAULT_EMAIL_ADDRESS = "flashproxyreg.a@gmail.com" DEFAULT_LOG_FILENAME = "facilitator-email-poller.log"
POLL_INTERVAL = 60 +# Ignore message older than this many seconds old, or newer than this many +# seconds in the future. +REGISTRATION_AGE_LIMIT = 30 * 60
FACILITATOR_ADDR = ("127.0.0.1", 9002)
@@ -207,6 +213,39 @@ if options.privdrop_username is not None: if options.imaplib_debug: imaplib.Debug = 4
+def message_get_date(msg): + """Get the datetime when the message was received by reading the X-Received + header, relative to UTC. Returns None on error.""" + x_received = msg["X-Received"] + if x_received is None: + log(u"X-Received is missing") + return None + try: + _, date_str = x_received.rsplit(";", 1) + date_str = date_str.strip() + except ValueError: + log(u"can't parse X-Received %s" % repr(x_received)) + return None + date_tuple = email.utils.parsedate_tz(date_str) + if date_tuple is None: + log(u"can't parse X-Received date string %s" % repr(date_str)) + return None + timestamp_utc = calendar.timegm(date_tuple[:8] + (0,)) - date_tuple[9] + return datetime.datetime.utcfromtimestamp(timestamp_utc) + +def message_ok(msg): + date = message_get_date(msg) + if date is not None: + now = datetime.datetime.utcnow() + age = time.mktime(now.utctimetuple()) - time.mktime(date.utctimetuple()) + if age > REGISTRATION_AGE_LIMIT: + log(u"message dated %s UTC is too old: %d seconds" % (date, age)) + return False + if -age > REGISTRATION_AGE_LIMIT: + log(u"message dated %s UTC is from the future: %d seconds" % (date, -age)) + return False + return True + def handle_message(msg): try: if fac.put_reg_base64(msg.get_payload()): @@ -279,7 +318,8 @@ def imap_loop(imap):
try: msg = email.message_from_string(msg_text) - handle_message(msg) + if message_ok(msg): + handle_message(msg) except Exception, e: log("Error processing message, deleting anyway: %s" % str(e))