commit 26db40e275804d75ecb86b0c1922f0af2a53aa2f Author: Ximin Luo infinity0@gmx.com Date: Thu Nov 21 21:19:26 2013 +0000
email-poller: move main loop inside a main() function - so we can import it without running it, useful for the upcoming help2man stuff --- facilitator/facilitator-email-poller | 254 +++++++++++++++++----------------- 1 file changed, 129 insertions(+), 125 deletions(-)
diff --git a/facilitator/facilitator-email-poller b/facilitator/facilitator-email-poller index 8a5c972..b3b9b14 100755 --- a/facilitator/facilitator-email-poller +++ b/facilitator/facilitator-email-poller @@ -125,110 +125,136 @@ def log(msg): print >> options.log_file, (u"%s %s" % (time.strftime(LOG_DATE_FORMAT), msg)).encode("UTF-8") options.log_file.flush()
-opts, args = getopt.gnu_getopt(sys.argv[1:], "de:hi:l:p:", [ - "debug", - "disable-pin", - "email=", - "help", - "imap=", - "imaplib-debug", - "log=", - "pass=", - "pidfile=", - "privdrop-user=", - "unsafe-logging", -]) -for o, a in opts: - if o == "-d" or o == "--debug": - options.daemonize = False - options.log_filename = None - elif o == "--disable-pin": - options.use_certificate_pin = False - elif o == "-h" or o == "--help": - usage() - sys.exit() - if o == "--imaplib-debug": - options.imaplib_debug = True - elif o == "-l" or o == "--log": - options.log_filename = a - elif o == "-p" or o == "--pass": - options.password_filename = a - elif o == "--pidfile": - options.pid_filename = a - elif o == "--privdrop-user": - options.privdrop_username = a - elif o == "--unsafe-logging": - options.safe_logging = False - -if len(args) != 0: - usage(sys.stderr) - sys.exit(1) - -# Load the email password. -if options.password_filename is None: - print >> sys.stderr, "The --pass option is required." - sys.exit(1) -try: - password_file = open(options.password_filename) -except Exception, e: - print >> sys.stderr, """\ -Failed to open password file "%s": %s.\ -""" % (options.password_filename, str(e)) - sys.exit(1) -try: - if not proc.check_perms(password_file.fileno()): - print >> sys.stderr, "Refusing to run with group- or world-readable password file. Try" - print >> sys.stderr, "\tchmod 600 %s" % options.password_filename +def main(): + opts, args = getopt.gnu_getopt(sys.argv[1:], "de:hi:l:p:", [ + "debug", + "disable-pin", + "email=", + "help", + "imap=", + "imaplib-debug", + "log=", + "pass=", + "pidfile=", + "privdrop-user=", + "unsafe-logging", + ]) + for o, a in opts: + if o == "-d" or o == "--debug": + options.daemonize = False + options.log_filename = None + elif o == "--disable-pin": + options.use_certificate_pin = False + elif o == "-h" or o == "--help": + usage() + sys.exit() + if o == "--imaplib-debug": + options.imaplib_debug = True + elif o == "-l" or o == "--log": + options.log_filename = a + elif o == "-p" or o == "--pass": + options.password_filename = a + elif o == "--pidfile": + options.pid_filename = a + elif o == "--privdrop-user": + options.privdrop_username = a + elif o == "--unsafe-logging": + options.safe_logging = False + + if len(args) != 0: + usage(sys.stderr) + sys.exit(1) + + # Load the email password. + if options.password_filename is None: + print >> sys.stderr, "The --pass option is required." + sys.exit(1) + try: + password_file = open(options.password_filename) + except Exception, e: + print >> sys.stderr, """\ + Failed to open password file "%s": %s.\ + """ % (options.password_filename, str(e)) sys.exit(1) - for (lineno0, line) in enumerate(password_file.readlines()): - line = line.strip("\n") - if not line or line.startswith('#'): continue - # we do this stricter regex match because passwords might have spaces in - res = re.match(r"(?:(\S+)\s)?(\S+@\S+)\s(.+)", line) - if not res: - raise ValueError("could not find email or password on line %s" % (lineno0+1)) - (imap_addr_spec, email_addr, email_password) = res.groups() - imap_addr = parse_addr_spec( - imap_addr_spec or "", DEFAULT_IMAP_HOST, DEFAULT_IMAP_PORT) - break - else: - raise ValueError("no email line found") -except Exception, e: - print >> sys.stderr, """\ -Failed to parse password file "%s": %s. -Syntax is [<imap_host>] <email> <password>. -""" % (options.password_filename, str(e)) - sys.exit(1) -finally: - password_file.close() - -if options.log_filename: - options.log_file = open(options.log_filename, "a") - # Send error tracebacks to the log. - sys.stderr = options.log_file -else: - options.log_file = sys.stdout - -if options.daemonize: - log(u"daemonizing") - pid = os.fork() - if pid != 0: - if options.pid_filename: - f = open(options.pid_filename, "w") - print >> f, pid - f.close() - sys.exit(0) - -if options.privdrop_username is not None: - log(u"dropping privileges to those of user %s" % options.privdrop_username) try: - proc.drop_privs(options.privdrop_username) - except BaseException, e: - print >> sys.stderr, "Can't drop privileges:", str(e) + if not proc.check_perms(password_file.fileno()): + print >> sys.stderr, "Refusing to run with group- or world-readable password file. Try" + print >> sys.stderr, "\tchmod 600 %s" % options.password_filename + sys.exit(1) + for (lineno0, line) in enumerate(password_file.readlines()): + line = line.strip("\n") + if not line or line.startswith('#'): continue + # we do this stricter regex match because passwords might have spaces in + res = re.match(r"(?:(\S+)\s)?(\S+@\S+)\s(.+)", line) + if not res: + raise ValueError("could not find email or password on line %s" % (lineno0+1)) + (imap_addr_spec, email_addr, email_password) = res.groups() + imap_addr = parse_addr_spec( + imap_addr_spec or "", DEFAULT_IMAP_HOST, DEFAULT_IMAP_PORT) + break + else: + raise ValueError("no email line found") + except Exception, e: + print >> sys.stderr, """\ + Failed to parse password file "%s": %s. + Syntax is [<imap_host>] <email> <password>. + """ % (options.password_filename, str(e)) sys.exit(1) + finally: + password_file.close()
-if options.imaplib_debug: - imaplib.Debug = 4 + if options.log_filename: + options.log_file = open(options.log_filename, "a") + # Send error tracebacks to the log. + sys.stderr = options.log_file + else: + options.log_file = sys.stdout + + if options.daemonize: + log(u"daemonizing") + pid = os.fork() + if pid != 0: + if options.pid_filename: + f = open(options.pid_filename, "w") + print >> f, pid + f.close() + sys.exit(0) + + if options.privdrop_username is not None: + log(u"dropping privileges to those of user %s" % options.privdrop_username) + try: + proc.drop_privs(options.privdrop_username) + except BaseException, e: + print >> sys.stderr, "Can't drop privileges:", str(e) + sys.exit(1) + + if options.imaplib_debug: + imaplib.Debug = 4 + + login_limit = RateLimit() + while True: + try: + imap = imap_login(imap_addr, email_addr, email_password) + try: + imap_loop(imap) + except imaplib.IMAP4.error: + imap.close() + imap.logout() + except (imaplib.IMAP4.error, ssl.SSLError, SSL.SSLError, socket.error), e: + # Try again after a disconnection. + log(u"lost server connection: %s" % str(e)) + except KeyboardInterrupt: + break + + # Don't reconnect too fast. + t = login_limit.time_to_wait() + if t > 0: + log(u"waiting %.2f seconds before logging in again" % t) + time.sleep(t) + + log(u"closing") + imap.close() + imap.logout()
def message_get_date(msg): """Get the datetime when the message was received by reading the X-Received @@ -342,7 +368,7 @@ def imap_loop(imap):
time.sleep(POLL_INTERVAL)
-def imap_login(): +def imap_login(imap_addr, email_addr, email_password): """Make an IMAP connection, check the certificate and public key, and log in.""" with keys.temp_cert(keys.PIN_GOOGLE_CA_CERT) as ca_certs_file: imap = IMAP4_SSL_REQUIRED( @@ -375,27 +401,5 @@ class RateLimit(object): self.interval = self.interval * math.exp(-self.DECAY * delta) * self.MULTIPLIER return wait
-login_limit = RateLimit() -while True: - try: - imap = imap_login() - try: - imap_loop(imap) - except imaplib.IMAP4.error: - imap.close() - imap.logout() - except (imaplib.IMAP4.error, ssl.SSLError, SSL.SSLError, socket.error), e: - # Try again after a disconnection. - log(u"lost server connection: %s" % str(e)) - except KeyboardInterrupt: - break - - # Don't reconnect too fast. - t = login_limit.time_to_wait() - if t > 0: - log(u"waiting %.2f seconds before logging in again" % t) - time.sleep(t) - -log(u"closing") -imap.close() -imap.logout() +if __name__ == "__main__": + main()
tor-commits@lists.torproject.org