From: Samuel M. <s.m...@gm...> - 2016-06-08 19:36:41
|
Hi all, Here is a couple of patchs fixing only python code formating in the fetchmailconf.py file. After this series, fetchmailconf.py is compatible with python-2 and python-3. Regards, Samuel Martin (2): fetchmailconf.py: fix tabs/spaces mixup preventing from compiling the pyc module fetchmailconf.py: make fetchmailconf.py python{2,3}-compliant fetchmailconf.py | 2544 +++++++++++++++++++++++++++--------------------------- 1 file changed, 1273 insertions(+), 1271 deletions(-) -- 2.8.3 |
From: Samuel M. <s.m...@gm...> - 2016-06-08 19:36:47
|
This change does: - use repr(...) instead of `...` (see [1]); - fix print call; - fix octal numbers. [1] https://docs.python.org/release/3.0.1/whatsnew/3.0.html#removed-syntax Signed-off-by: Samuel Martin <s.m...@gm...> --- fetchmailconf.py | 94 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/fetchmailconf.py b/fetchmailconf.py index d64556e..697e4f7 100755 --- a/fetchmailconf.py +++ b/fetchmailconf.py @@ -5,6 +5,8 @@ # Matthias Andree <mat...@gm...> # Requires Python with Tkinter, and the following OS-dependent services: # posix, posixpath, socket +from __future__ import print_function + version = "1.57" from Tkinter import * @@ -64,7 +66,7 @@ class Configuration: if self.properties != ConfigurationDefaults.properties: str = str + ("set properties \"%s\"\n" % (self.properties,)); if self.poll_interval > 0: - str = str + "set daemon " + `self.poll_interval` + "\n" + str = str + "set daemon " + repr(self.poll_interval) + "\n" if self.invisible: str = str + ("set invisible\n") for site in self.servers: @@ -145,12 +147,12 @@ class Server: if self.service and self.protocol and self.service != defaultports[self.protocol] and defaultports[self.protocol] and self.service != ianaservices[defaultports[self.protocol]]: res = res + " service " + self.service if self.timeout != ServerDefaults.timeout: - res = res + " timeout " + `self.timeout` + res = res + " timeout " + repr(self.timeout) if self.interval != ServerDefaults.interval: - res = res + " interval " + `self.interval` + res = res + " interval " + repr(self.interval) if self.envelope != ServerDefaults.envelope or self.envskip != ServerDefaults.envskip: if self.envskip: - res = res + " envelope " + `self.envskip` + " " + self.envelope + res = res + " envelope " + repr(self.envskip) + " " + self.envelope else: res = res + " envelope " + self.envelope if self.qvirtual: @@ -189,15 +191,15 @@ class Server: if self.monitor: res = res + " monitor " + str(self.monitor) if self.plugin: - res = res + " plugin " + `self.plugin` + res = res + " plugin " + repr(self.plugin) if self.plugout: - res = res + " plugout " + `self.plugout` + res = res + " plugout " + repr(self.plugout) if self.principal: - res = res + " principal " + `self.principal` + res = res + " principal " + repr(self.principal) if self.esmtpname: - res = res + " esmtpname " + `self.esmtpname` + res = res + " esmtpname " + repr(self.esmtpname) if self.esmtppassword: - res = res + " esmtppassword " + `self.esmtppassword` + res = res + " esmtppassword " + repr(self.esmtppassword) if self.interface or self.monitor or self.principal or self.plugin or self.plugout: if folded: res = res + "\n" @@ -230,7 +232,7 @@ class User: elif os.environ.has_key("LOGNAME"): self.remote = os.environ["LOGNAME"] else: - print "Can't get your username!" + print("Can't get your username!") sys.exit(1) self.localnames = [self.remote,]# Local names self.password = None # Password for mail account access @@ -316,13 +318,13 @@ class User: def __repr__(self): res = " " - res = res + "user " + `self.remote` + " there "; + res = res + "user " + repr(self.remote) + " there "; if self.password: - res = res + "with password " + `self.password` + " " + res = res + "with password " + repr(self.password) + " " if self.localnames: res = res + "is" for x in self.localnames: - res = res + " " + `x` + res = res + " " + repr(x) res = res + " here" if (self.keep != UserDefaults.keep or self.flush != UserDefaults.flush @@ -362,35 +364,35 @@ class User: if self.idle != UserDefaults.idle: res = res + flag2str(self.idle, 'idle') if self.limit != UserDefaults.limit: - res = res + " limit " + `self.limit` + res = res + " limit " + repr(self.limit) if self.warnings != UserDefaults.warnings: - res = res + " warnings " + `self.warnings` + res = res + " warnings " + repr(self.warnings) if self.fetchlimit != UserDefaults.fetchlimit: - res = res + " fetchlimit " + `self.fetchlimit` + res = res + " fetchlimit " + repr(self.fetchlimit) if self.fetchsizelimit != UserDefaults.fetchsizelimit: - res = res + " fetchsizelimit " + `self.fetchsizelimit` + res = res + " fetchsizelimit " + repr(self.fetchsizelimit) if self.fastuidl != UserDefaults.fastuidl: - res = res + " fastuidl " + `self.fastuidl` + res = res + " fastuidl " + repr(self.fastuidl) if self.batchlimit != UserDefaults.batchlimit: - res = res + " batchlimit " + `self.batchlimit` + res = res + " batchlimit " + repr(self.batchlimit) if self.ssl and self.ssl != UserDefaults.ssl: res = res + flag2str(self.ssl, 'ssl') if self.sslkey and self.sslkey != UserDefaults.sslkey: - res = res + " sslkey " + `self.sslkey` + res = res + " sslkey " + repr(self.sslkey) if self.sslcert and self.sslcert != UserDefaults.sslcert: - res = res + " sslcert " + `self.sslcert` + res = res + " sslcert " + repr(self.sslcert) if self.sslproto and self.sslproto != UserDefaults.sslproto: - res = res + " sslproto " + `self.sslproto` + res = res + " sslproto " + repr(self.sslproto) if self.sslcertck and self.sslcertck != UserDefaults.sslcertck: res = res + flag2str(self.sslcertck, 'sslcertck') if self.sslcertpath and self.sslcertpath != UserDefaults.sslcertpath: - res = res + " sslcertpath " + `self.sslcertpath` + res = res + " sslcertpath " + repr(self.sslcertpath) if self.sslcommonname and self.sslcommonname != UserDefaults.sslcommonname: - res = res + " sslcommonname " + `self.sslcommonname` + res = res + " sslcommonname " + repr(self.sslcommonname) if self.sslfingerprint and self.sslfingerprint != UserDefaults.sslfingerprint: - res = res + " sslfingerprint " + `self.sslfingerprint` + res = res + " sslfingerprint " + repr(self.sslfingerprint) if self.expunge != UserDefaults.expunge: - res = res + " expunge " + `self.expunge` + res = res + " expunge " + repr(self.expunge) res = res + "\n" trimmed = self.smtphunt; if trimmed != [] and trimmed[len(trimmed) - 1] == "localhost": @@ -417,7 +419,7 @@ class User: res = res + "\n" for fld in ('smtpaddress', 'preconnect', 'postconnect', 'mda', 'bsmtp', 'properties'): if getattr(self, fld): - res = res + " %s %s\n" % (fld, `getattr(self, fld)`) + res = res + " %s %s\n" % (fld, repr(getattr(self, fld))) if self.lmtp != UserDefaults.lmtp: res = res + flag2str(self.lmtp, 'lmtp') if self.antispam != UserDefaults.antispam: @@ -904,15 +906,15 @@ class ConfigurationEdit(Frame, MyWidget): # Pre-1.5.2 compatibility... except os.error: pass - oldumask = os.umask(077) + oldumask = os.umask(0o77) fm = open(self.outfile, 'w') os.umask(oldumask) if fm: # be paranoid if fm != sys.stdout: - os.chmod(self.outfile, 0600) + os.chmod(self.outfile, 0o600) fm.write("# Configuration created %s by fetchmailconf %s\n" % (time.ctime(time.time()), version)) - fm.write(`self.configuration`) + fm.write(repr(self.configuration)) if self.outfile: fm.close() self.destruct() @@ -1988,15 +1990,15 @@ def copy_instance(toclass, fromdict): if 'typemap' in class_sig: class_sig.remove('typemap') if tuple(class_sig) != tuple(dict_keys): - print "Fields don't match what fetchmailconf expected:" -# print "Class signature: " + `class_sig` -# print "Dictionary keys: " + `dict_keys` + print("Fields don't match what fetchmailconf expected:") +# print("Class signature: " + repr(class_sig)) +# print("Dictionary keys: " + repr(dict_keys)) diff = setdiff(class_sig, common) if diff: - print "Not matched in class `" + toclass.__class__.__name__ + "' signature: " + `diff` + print("Not matched in class `" + toclass.__class__.__name__ + "' signature: " + repr(diff)) diff = setdiff(dict_keys, common) if diff: - print "Not matched in dictionary keys: " + `diff` + print("Not matched in dictionary keys: " + repr(diff)) sys.exit(1) else: for x in fromdict.keys(): @@ -2028,7 +2030,7 @@ def copy_instance(toclass, fromdict): if __name__ == '__main__': if not os.environ.has_key("DISPLAY"): - print "fetchmailconf must be run under X" + print("fetchmailconf must be run under X") sys.exit(1) fetchmail_icon = """ @@ -2068,7 +2070,7 @@ gUSiYASJpMEHhilJTEnhAlGoQqYAZQ1AiqEMZ0jDGtqQImhwwA13yMMevoQAGvGhEAWHGMOAAAA7 # The base64 data in the string above was generated by the following procedure: # # import base64 -# print base64.encodestring(open("fetchmail.gif", "rb").read()) +# print(base64.encodestring(open("fetchmail.gif", "rb").read())) # # Process options @@ -2081,22 +2083,22 @@ gUSiYASJpMEHhilJTEnhAlGoQqYAZQ1AiqEMZ0jDGtqQImhwwA13yMMevoQAGvGhEAWHGMOAAAA7 elif (switch == '-f'): rcfile = val elif (switch == '-h' or switch == '--help'): - print """ + print(""" Usage: fetchmailconf {[-d] [-f fetchmailrc]|-h|--help|-V|--version} -d - dump configuration (for debugging) -f fmrc - read alternate fetchmailrc file --help, -h - print this help text and quit --version, -V - print fetchmailconf version and quit -""" +""") sys.exit(0) elif (switch == '-V' or switch == '--version'): - print "fetchmailconf %s" % version - print """ + print("fetchmailconf %s" % version) + print(""" Copyright (C) 1997 - 2003 Eric S. Raymond Copyright (C) 2005, 2006, 2008, 2009 Matthias Andree fetchmailconf comes with ABSOLUTELY NO WARRANTY. This is free software, you are welcome to redistribute it under certain conditions. Please see the file -COPYING in the source or documentation directory for details.""" +COPYING in the source or documentation directory for details.""") sys.exit(0) # Get client host's FQDN @@ -2119,17 +2121,17 @@ COPYING in the source or documentation directory for details.""" try: s = os.system(cmd) if s != 0: - print "`" + cmd + "' run failure, status " + `s` + print("`" + cmd + "' run failure, status " + repr(s)) raise SystemExit except: - print "Unknown error while running fetchmail --configdump" + print("Unknown error while running fetchmail --configdump") os.remove(tmpfile) sys.exit(1) try: execfile(tmpfile) except: - print "Can't read configuration output of fetchmail --configdump." + print("Can't read configuration output of fetchmail --configdump.") os.remove(tmpfile) sys.exit(1) @@ -2156,7 +2158,7 @@ COPYING in the source or documentation directory for details.""" # We may want to display the configuration and quit if dump: - print "This is a dump of the configuration we read:\n"+`Fetchmailrc` + print("This is a dump of the configuration we read:\n" + repr(Fetchmailrc)) # The theory here is that -f alone sets the rcfile location, # but -d and -f together mean the new configuration should go to stdout. -- 2.8.3 |
From: Samuel M. <s.m...@gm...> - 2016-06-08 19:36:53
|
This whitespace-only change substitutes all leading tabulations with the right number of spaces to get the standard 4-space indentation. This bug was triggered by the Buildroot farms: http://autobuild.buildroot.org/results/700/7009445dd116a1c02db82a351d38db44db8dad16/build-end.log Signed-off-by: Samuel Martin <s.m...@gm...> --- fetchmailconf.py | 2532 +++++++++++++++++++++++++++--------------------------- 1 file changed, 1266 insertions(+), 1266 deletions(-) diff --git a/fetchmailconf.py b/fetchmailconf.py index 2dc02d8..d64556e 100755 --- a/fetchmailconf.py +++ b/fetchmailconf.py @@ -16,416 +16,416 @@ import sys, time, os, string, socket, getopt, tempfile # class Configuration: def __init__(self): - self.poll_interval = 0 # Normally, run in foreground - self.logfile = None # No logfile, initially - self.idfile = os.environ["HOME"] + "/.fetchids" # Default idfile, initially - self.postmaster = None # No last-resort address, initially - self.bouncemail = TRUE # Bounce errors to users - self.spambounce = FALSE # Bounce spam errors - self.softbounce = TRUE # Treat permanent error as temporary - self.properties = None # No exiguous properties - self.invisible = FALSE # Suppress Received line & spoof? - self.syslog = FALSE # Use syslogd for logging? - self.servers = [] # List of included sites - Configuration.typemap = ( - ('poll_interval', 'Int'), - ('logfile', 'String'), - ('idfile', 'String'), - ('postmaster', 'String'), - ('bouncemail', 'Boolean'), - ('spambounce', 'Boolean'), - ('softbounce', 'Boolean'), - ('properties', 'String'), - ('syslog', 'Boolean'), - ('invisible', 'Boolean')) + self.poll_interval = 0 # Normally, run in foreground + self.logfile = None # No logfile, initially + self.idfile = os.environ["HOME"] + "/.fetchids" # Default idfile, initially + self.postmaster = None # No last-resort address, initially + self.bouncemail = TRUE # Bounce errors to users + self.spambounce = FALSE # Bounce spam errors + self.softbounce = TRUE # Treat permanent error as temporary + self.properties = None # No exiguous properties + self.invisible = FALSE # Suppress Received line & spoof? + self.syslog = FALSE # Use syslogd for logging? + self.servers = [] # List of included sites + Configuration.typemap = ( + ('poll_interval', 'Int'), + ('logfile', 'String'), + ('idfile', 'String'), + ('postmaster', 'String'), + ('bouncemail', 'Boolean'), + ('spambounce', 'Boolean'), + ('softbounce', 'Boolean'), + ('properties', 'String'), + ('syslog', 'Boolean'), + ('invisible', 'Boolean')) def __repr__(self): - str = ""; - if self.syslog != ConfigurationDefaults.syslog: - str = str + ("set syslog\n") - elif self.logfile: - str = str + ("set logfile \"%s\"\n" % (self.logfile,)); - if self.idfile != ConfigurationDefaults.idfile: - str = str + ("set idfile \"%s\"\n" % (self.idfile,)); - if self.postmaster != ConfigurationDefaults.postmaster: - str = str + ("set postmaster \"%s\"\n" % (self.postmaster,)); - if self.bouncemail: - str = str + ("set bouncemail\n") - else: - str = str + ("set nobouncemail\n") - if self.spambounce: - str = str + ("set spambounce\n") - else: - str = str + ("set no spambounce\n") - if self.softbounce: - str = str + ("set softbounce\n") - else: - str = str + ("set no softbounce\n") - if self.properties != ConfigurationDefaults.properties: - str = str + ("set properties \"%s\"\n" % (self.properties,)); - if self.poll_interval > 0: - str = str + "set daemon " + `self.poll_interval` + "\n" - if self.invisible: - str = str + ("set invisible\n") - for site in self.servers: - str = str + repr(site) - return str + str = ""; + if self.syslog != ConfigurationDefaults.syslog: + str = str + ("set syslog\n") + elif self.logfile: + str = str + ("set logfile \"%s\"\n" % (self.logfile,)); + if self.idfile != ConfigurationDefaults.idfile: + str = str + ("set idfile \"%s\"\n" % (self.idfile,)); + if self.postmaster != ConfigurationDefaults.postmaster: + str = str + ("set postmaster \"%s\"\n" % (self.postmaster,)); + if self.bouncemail: + str = str + ("set bouncemail\n") + else: + str = str + ("set nobouncemail\n") + if self.spambounce: + str = str + ("set spambounce\n") + else: + str = str + ("set no spambounce\n") + if self.softbounce: + str = str + ("set softbounce\n") + else: + str = str + ("set no softbounce\n") + if self.properties != ConfigurationDefaults.properties: + str = str + ("set properties \"%s\"\n" % (self.properties,)); + if self.poll_interval > 0: + str = str + "set daemon " + `self.poll_interval` + "\n" + if self.invisible: + str = str + ("set invisible\n") + for site in self.servers: + str = str + repr(site) + return str def __delitem__(self, name): - for si in range(len(self.servers)): - if self.servers[si].pollname == name: - del self.servers[si] - break + for si in range(len(self.servers)): + if self.servers[si].pollname == name: + del self.servers[si] + break def __str__(self): - return "[Configuration: " + repr(self) + "]" + return "[Configuration: " + repr(self) + "]" class Server: def __init__(self): - self.pollname = None # Poll label - self.via = None # True name of host - self.active = TRUE # Poll status - self.interval = 0 # Skip interval - self.protocol = 'auto' # Default to auto protocol - self.service = None # Service name to use - self.uidl = FALSE # Don't use RFC1725 UIDLs by default - self.auth = 'any' # Default to password authentication - self.timeout = 300 # 5-minute timeout - self.envelope = 'Received' # Envelope-address header - self.envskip = 0 # Number of envelope headers to skip - self.qvirtual = None # Name prefix to strip - self.aka = [] # List of DNS aka names - self.dns = TRUE # Enable DNS lookup on multidrop - self.localdomains = [] # Domains to be considered local - self.interface = None # IP address and range - self.monitor = None # IP address and range - self.plugin = None # Plugin command for going to server - self.plugout = None # Plugin command for going to listener - self.principal = None # Kerberos principal - self.esmtpname = None # ESMTP 2554 name - self.esmtppassword = None # ESMTP 2554 password - self.tracepolls = FALSE # Add trace-poll info to headers - self.badheader = FALSE # Pass messages with bad headers on? - self.users = [] # List of user entries for site - Server.typemap = ( - ('pollname', 'String'), - ('via', 'String'), - ('active', 'Boolean'), - ('interval', 'Int'), - ('protocol', 'String'), - ('service', 'String'), - ('uidl', 'Boolean'), - ('auth', 'String'), - ('timeout', 'Int'), - ('envelope', 'String'), - ('envskip', 'Int'), - ('qvirtual', 'String'), - # leave aka out - ('dns', 'Boolean'), - # leave localdomains out - ('interface', 'String'), - ('monitor', 'String'), - ('plugin', 'String'), - ('plugout', 'String'), - ('esmtpname', 'String'), - ('esmtppassword', 'String'), - ('principal', 'String'), - ('tracepolls','Boolean'), - ('badheader', 'Boolean')) + self.pollname = None # Poll label + self.via = None # True name of host + self.active = TRUE # Poll status + self.interval = 0 # Skip interval + self.protocol = 'auto' # Default to auto protocol + self.service = None # Service name to use + self.uidl = FALSE # Don't use RFC1725 UIDLs by default + self.auth = 'any' # Default to password authentication + self.timeout = 300 # 5-minute timeout + self.envelope = 'Received' # Envelope-address header + self.envskip = 0 # Number of envelope headers to skip + self.qvirtual = None # Name prefix to strip + self.aka = [] # List of DNS aka names + self.dns = TRUE # Enable DNS lookup on multidrop + self.localdomains = [] # Domains to be considered local + self.interface = None # IP address and range + self.monitor = None # IP address and range + self.plugin = None # Plugin command for going to server + self.plugout = None # Plugin command for going to listener + self.principal = None # Kerberos principal + self.esmtpname = None # ESMTP 2554 name + self.esmtppassword = None # ESMTP 2554 password + self.tracepolls = FALSE # Add trace-poll info to headers + self.badheader = FALSE # Pass messages with bad headers on? + self.users = [] # List of user entries for site + Server.typemap = ( + ('pollname', 'String'), + ('via', 'String'), + ('active', 'Boolean'), + ('interval', 'Int'), + ('protocol', 'String'), + ('service', 'String'), + ('uidl', 'Boolean'), + ('auth', 'String'), + ('timeout', 'Int'), + ('envelope', 'String'), + ('envskip', 'Int'), + ('qvirtual', 'String'), + # leave aka out + ('dns', 'Boolean'), + # leave localdomains out + ('interface', 'String'), + ('monitor', 'String'), + ('plugin', 'String'), + ('plugout', 'String'), + ('esmtpname', 'String'), + ('esmtppassword', 'String'), + ('principal', 'String'), + ('tracepolls','Boolean'), + ('badheader', 'Boolean')) def dump(self, folded): - res = "" - if self.active: res = res + "poll" - else: res = res + "skip" - res = res + (" " + self.pollname) - if self.via: - res = res + (" via " + str(self.via) + "\n"); - if self.protocol != ServerDefaults.protocol: - res = res + " with proto " + self.protocol - if self.service and self.protocol and self.service != defaultports[self.protocol] and defaultports[self.protocol] and self.service != ianaservices[defaultports[self.protocol]]: - res = res + " service " + self.service - if self.timeout != ServerDefaults.timeout: - res = res + " timeout " + `self.timeout` - if self.interval != ServerDefaults.interval: - res = res + " interval " + `self.interval` - if self.envelope != ServerDefaults.envelope or self.envskip != ServerDefaults.envskip: - if self.envskip: - res = res + " envelope " + `self.envskip` + " " + self.envelope - else: - res = res + " envelope " + self.envelope - if self.qvirtual: - res = res + (" qvirtual " + str(self.qvirtual) + "\n"); - if self.auth != ServerDefaults.auth: - res = res + " auth " + self.auth - if self.dns != ServerDefaults.dns or self.uidl != ServerDefaults.uidl: - res = res + " and options" - if self.dns != ServerDefaults.dns: - res = res + flag2str(self.dns, 'dns') - if self.uidl != ServerDefaults.uidl: - res = res + flag2str(self.uidl, 'uidl') - if folded: res = res + "\n " - else: res = res + " " - - if self.aka: - res = res + "aka" - for x in self.aka: - res = res + " " + x - if self.aka and self.localdomains: res = res + " " - if self.localdomains: - res = res + ("localdomains") - for x in self.localdomains: - res = res + " " + x - if (self.aka or self.localdomains): - if folded: - res = res + "\n " - else: - res = res + " " - - if self.tracepolls: - res = res + "tracepolls\n" - - if self.interface: - res = res + " interface " + str(self.interface) - if self.monitor: - res = res + " monitor " + str(self.monitor) - if self.plugin: - res = res + " plugin " + `self.plugin` - if self.plugout: - res = res + " plugout " + `self.plugout` - if self.principal: - res = res + " principal " + `self.principal` - if self.esmtpname: - res = res + " esmtpname " + `self.esmtpname` - if self.esmtppassword: - res = res + " esmtppassword " + `self.esmtppassword` - if self.interface or self.monitor or self.principal or self.plugin or self.plugout: - if folded: - res = res + "\n" - if self.badheader: - res = res + "bad-header accept " - - if res[-1] == " ": res = res[0:-1] - - for user in self.users: - res = res + repr(user) - res = res + "\n" - return res; + res = "" + if self.active: res = res + "poll" + else: res = res + "skip" + res = res + (" " + self.pollname) + if self.via: + res = res + (" via " + str(self.via) + "\n"); + if self.protocol != ServerDefaults.protocol: + res = res + " with proto " + self.protocol + if self.service and self.protocol and self.service != defaultports[self.protocol] and defaultports[self.protocol] and self.service != ianaservices[defaultports[self.protocol]]: + res = res + " service " + self.service + if self.timeout != ServerDefaults.timeout: + res = res + " timeout " + `self.timeout` + if self.interval != ServerDefaults.interval: + res = res + " interval " + `self.interval` + if self.envelope != ServerDefaults.envelope or self.envskip != ServerDefaults.envskip: + if self.envskip: + res = res + " envelope " + `self.envskip` + " " + self.envelope + else: + res = res + " envelope " + self.envelope + if self.qvirtual: + res = res + (" qvirtual " + str(self.qvirtual) + "\n"); + if self.auth != ServerDefaults.auth: + res = res + " auth " + self.auth + if self.dns != ServerDefaults.dns or self.uidl != ServerDefaults.uidl: + res = res + " and options" + if self.dns != ServerDefaults.dns: + res = res + flag2str(self.dns, 'dns') + if self.uidl != ServerDefaults.uidl: + res = res + flag2str(self.uidl, 'uidl') + if folded: res = res + "\n " + else: res = res + " " + + if self.aka: + res = res + "aka" + for x in self.aka: + res = res + " " + x + if self.aka and self.localdomains: res = res + " " + if self.localdomains: + res = res + ("localdomains") + for x in self.localdomains: + res = res + " " + x + if (self.aka or self.localdomains): + if folded: + res = res + "\n " + else: + res = res + " " + + if self.tracepolls: + res = res + "tracepolls\n" + + if self.interface: + res = res + " interface " + str(self.interface) + if self.monitor: + res = res + " monitor " + str(self.monitor) + if self.plugin: + res = res + " plugin " + `self.plugin` + if self.plugout: + res = res + " plugout " + `self.plugout` + if self.principal: + res = res + " principal " + `self.principal` + if self.esmtpname: + res = res + " esmtpname " + `self.esmtpname` + if self.esmtppassword: + res = res + " esmtppassword " + `self.esmtppassword` + if self.interface or self.monitor or self.principal or self.plugin or self.plugout: + if folded: + res = res + "\n" + if self.badheader: + res = res + "bad-header accept " + + if res[-1] == " ": res = res[0:-1] + + for user in self.users: + res = res + repr(user) + res = res + "\n" + return res; def __delitem__(self, name): - for ui in range(len(self.users)): - if self.users[ui].remote == name: - del self.users[ui] - break + for ui in range(len(self.users)): + if self.users[ui].remote == name: + del self.users[ui] + break def __repr__(self): - return self.dump(TRUE) + return self.dump(TRUE) def __str__(self): - return "[Server: " + self.dump(FALSE) + "]" + return "[Server: " + self.dump(FALSE) + "]" class User: def __init__(self): - if os.environ.has_key("USER"): - self.remote = os.environ["USER"] # Remote username - elif os.environ.has_key("LOGNAME"): - self.remote = os.environ["LOGNAME"] - else: - print "Can't get your username!" - sys.exit(1) - self.localnames = [self.remote,]# Local names - self.password = None # Password for mail account access - self.mailboxes = [] # Remote folders to retrieve from - self.smtphunt = [] # Hosts to forward to - self.fetchdomains = [] # Domains to fetch from - self.smtpaddress = None # Append this to MAIL FROM line - self.smtpname = None # Use this for RCPT TO - self.preconnect = None # Connection setup - self.postconnect = None # Connection wrapup - self.mda = None # Mail Delivery Agent - self.bsmtp = None # BSMTP output file - self.lmtp = FALSE # Use LMTP rather than SMTP? - self.antispam = "" # Listener's spam-block code - self.keep = FALSE # Keep messages - self.flush = FALSE # Flush messages - self.limitflush = FALSE # Flush oversized messages - self.fetchall = FALSE # Fetch old messages - self.rewrite = TRUE # Rewrite message headers - self.forcecr = FALSE # Force LF -> CR/LF - self.stripcr = FALSE # Strip CR - self.pass8bits = FALSE # Force BODY=7BIT - self.mimedecode = FALSE # Undo MIME armoring - self.dropstatus = FALSE # Drop incoming Status lines - self.dropdelivered = FALSE # Drop incoming Delivered-To lines - self.idle = FALSE # IDLE after poll - self.limit = 0 # Message size limit - self.warnings = 3600 # Size warning interval (see tunable.h) - self.fetchlimit = 0 # Max messages fetched per batch - self.fetchsizelimit = 100 # Max message sizes fetched per transaction - self.fastuidl = 4 # Do fast uidl 3 out of 4 times - self.batchlimit = 0 # Max message forwarded per batch - self.expunge = 0 # Interval between expunges (IMAP) - self.ssl = 0 # Enable Seccure Socket Layer - self.sslkey = None # SSL key filename - self.sslcert = None # SSL certificate filename - self.sslproto = None # Force SSL? - self.sslcertck = 0 # Enable strict SSL cert checking - self.sslcertpath = None # Path to trusted certificates - self.sslcommonname = None # SSL CommonName to expect - self.sslfingerprint = None # SSL key fingerprint to check - self.properties = None # Extension properties - User.typemap = ( - ('remote', 'String'), - # leave out mailboxes and localnames - ('password', 'String'), - # Leave out smtphunt, fetchdomains - ('smtpaddress', 'String'), - ('smtpname', 'String'), - ('preconnect', 'String'), - ('postconnect', 'String'), - ('mda', 'String'), - ('bsmtp', 'String'), - ('lmtp', 'Boolean'), - ('antispam', 'String'), - ('keep', 'Boolean'), - ('flush', 'Boolean'), - ('limitflush', 'Boolean'), - ('fetchall', 'Boolean'), - ('rewrite', 'Boolean'), - ('forcecr', 'Boolean'), - ('stripcr', 'Boolean'), - ('pass8bits', 'Boolean'), - ('mimedecode', 'Boolean'), - ('dropstatus', 'Boolean'), - ('dropdelivered', 'Boolean'), - ('idle', 'Boolean'), - ('limit', 'Int'), - ('warnings', 'Int'), - ('fetchlimit', 'Int'), - ('fetchsizelimit', 'Int'), - ('fastuidl', 'Int'), - ('batchlimit', 'Int'), - ('expunge', 'Int'), - ('ssl', 'Boolean'), - ('sslkey', 'String'), - ('sslcert', 'String'), - ('sslcertck', 'Boolean'), - ('sslcertpath', 'String'), - ('sslcommonname', 'String'), - ('sslfingerprint', 'String'), - ('properties', 'String')) + if os.environ.has_key("USER"): + self.remote = os.environ["USER"] # Remote username + elif os.environ.has_key("LOGNAME"): + self.remote = os.environ["LOGNAME"] + else: + print "Can't get your username!" + sys.exit(1) + self.localnames = [self.remote,]# Local names + self.password = None # Password for mail account access + self.mailboxes = [] # Remote folders to retrieve from + self.smtphunt = [] # Hosts to forward to + self.fetchdomains = [] # Domains to fetch from + self.smtpaddress = None # Append this to MAIL FROM line + self.smtpname = None # Use this for RCPT TO + self.preconnect = None # Connection setup + self.postconnect = None # Connection wrapup + self.mda = None # Mail Delivery Agent + self.bsmtp = None # BSMTP output file + self.lmtp = FALSE # Use LMTP rather than SMTP? + self.antispam = "" # Listener's spam-block code + self.keep = FALSE # Keep messages + self.flush = FALSE # Flush messages + self.limitflush = FALSE # Flush oversized messages + self.fetchall = FALSE # Fetch old messages + self.rewrite = TRUE # Rewrite message headers + self.forcecr = FALSE # Force LF -> CR/LF + self.stripcr = FALSE # Strip CR + self.pass8bits = FALSE # Force BODY=7BIT + self.mimedecode = FALSE # Undo MIME armoring + self.dropstatus = FALSE # Drop incoming Status lines + self.dropdelivered = FALSE # Drop incoming Delivered-To lines + self.idle = FALSE # IDLE after poll + self.limit = 0 # Message size limit + self.warnings = 3600 # Size warning interval (see tunable.h) + self.fetchlimit = 0 # Max messages fetched per batch + self.fetchsizelimit = 100 # Max message sizes fetched per transaction + self.fastuidl = 4 # Do fast uidl 3 out of 4 times + self.batchlimit = 0 # Max message forwarded per batch + self.expunge = 0 # Interval between expunges (IMAP) + self.ssl = 0 # Enable Seccure Socket Layer + self.sslkey = None # SSL key filename + self.sslcert = None # SSL certificate filename + self.sslproto = None # Force SSL? + self.sslcertck = 0 # Enable strict SSL cert checking + self.sslcertpath = None # Path to trusted certificates + self.sslcommonname = None # SSL CommonName to expect + self.sslfingerprint = None # SSL key fingerprint to check + self.properties = None # Extension properties + User.typemap = ( + ('remote', 'String'), + # leave out mailboxes and localnames + ('password', 'String'), + # Leave out smtphunt, fetchdomains + ('smtpaddress', 'String'), + ('smtpname', 'String'), + ('preconnect', 'String'), + ('postconnect', 'String'), + ('mda', 'String'), + ('bsmtp', 'String'), + ('lmtp', 'Boolean'), + ('antispam', 'String'), + ('keep', 'Boolean'), + ('flush', 'Boolean'), + ('limitflush', 'Boolean'), + ('fetchall', 'Boolean'), + ('rewrite', 'Boolean'), + ('forcecr', 'Boolean'), + ('stripcr', 'Boolean'), + ('pass8bits', 'Boolean'), + ('mimedecode', 'Boolean'), + ('dropstatus', 'Boolean'), + ('dropdelivered', 'Boolean'), + ('idle', 'Boolean'), + ('limit', 'Int'), + ('warnings', 'Int'), + ('fetchlimit', 'Int'), + ('fetchsizelimit', 'Int'), + ('fastuidl', 'Int'), + ('batchlimit', 'Int'), + ('expunge', 'Int'), + ('ssl', 'Boolean'), + ('sslkey', 'String'), + ('sslcert', 'String'), + ('sslcertck', 'Boolean'), + ('sslcertpath', 'String'), + ('sslcommonname', 'String'), + ('sslfingerprint', 'String'), + ('properties', 'String')) def __repr__(self): - res = " " - res = res + "user " + `self.remote` + " there "; - if self.password: - res = res + "with password " + `self.password` + " " - if self.localnames: - res = res + "is" - for x in self.localnames: - res = res + " " + `x` - res = res + " here" - if (self.keep != UserDefaults.keep - or self.flush != UserDefaults.flush - or self.limitflush != UserDefaults.limitflush - or self.fetchall != UserDefaults.fetchall - or self.rewrite != UserDefaults.rewrite - or self.forcecr != UserDefaults.forcecr - or self.stripcr != UserDefaults.stripcr - or self.pass8bits != UserDefaults.pass8bits - or self.mimedecode != UserDefaults.mimedecode - or self.dropstatus != UserDefaults.dropstatus - or self.dropdelivered != UserDefaults.dropdelivered - or self.idle != UserDefaults.idle): - res = res + " options" - if self.keep != UserDefaults.keep: - res = res + flag2str(self.keep, 'keep') - if self.flush != UserDefaults.flush: - res = res + flag2str(self.flush, 'flush') - if self.limitflush != UserDefaults.limitflush: - res = res + flag2str(self.limitflush, 'limitflush') - if self.fetchall != UserDefaults.fetchall: - res = res + flag2str(self.fetchall, 'fetchall') - if self.rewrite != UserDefaults.rewrite: - res = res + flag2str(self.rewrite, 'rewrite') - if self.forcecr != UserDefaults.forcecr: - res = res + flag2str(self.forcecr, 'forcecr') - if self.stripcr != UserDefaults.stripcr: - res = res + flag2str(self.stripcr, 'stripcr') - if self.pass8bits != UserDefaults.pass8bits: - res = res + flag2str(self.pass8bits, 'pass8bits') - if self.mimedecode != UserDefaults.mimedecode: - res = res + flag2str(self.mimedecode, 'mimedecode') - if self.dropstatus != UserDefaults.dropstatus: - res = res + flag2str(self.dropstatus, 'dropstatus') - if self.dropdelivered != UserDefaults.dropdelivered: - res = res + flag2str(self.dropdelivered, 'dropdelivered') - if self.idle != UserDefaults.idle: - res = res + flag2str(self.idle, 'idle') - if self.limit != UserDefaults.limit: - res = res + " limit " + `self.limit` - if self.warnings != UserDefaults.warnings: - res = res + " warnings " + `self.warnings` - if self.fetchlimit != UserDefaults.fetchlimit: - res = res + " fetchlimit " + `self.fetchlimit` - if self.fetchsizelimit != UserDefaults.fetchsizelimit: - res = res + " fetchsizelimit " + `self.fetchsizelimit` - if self.fastuidl != UserDefaults.fastuidl: - res = res + " fastuidl " + `self.fastuidl` - if self.batchlimit != UserDefaults.batchlimit: - res = res + " batchlimit " + `self.batchlimit` - if self.ssl and self.ssl != UserDefaults.ssl: - res = res + flag2str(self.ssl, 'ssl') - if self.sslkey and self.sslkey != UserDefaults.sslkey: - res = res + " sslkey " + `self.sslkey` - if self.sslcert and self.sslcert != UserDefaults.sslcert: - res = res + " sslcert " + `self.sslcert` - if self.sslproto and self.sslproto != UserDefaults.sslproto: - res = res + " sslproto " + `self.sslproto` - if self.sslcertck and self.sslcertck != UserDefaults.sslcertck: - res = res + flag2str(self.sslcertck, 'sslcertck') - if self.sslcertpath and self.sslcertpath != UserDefaults.sslcertpath: - res = res + " sslcertpath " + `self.sslcertpath` - if self.sslcommonname and self.sslcommonname != UserDefaults.sslcommonname: - res = res + " sslcommonname " + `self.sslcommonname` - if self.sslfingerprint and self.sslfingerprint != UserDefaults.sslfingerprint: - res = res + " sslfingerprint " + `self.sslfingerprint` - if self.expunge != UserDefaults.expunge: - res = res + " expunge " + `self.expunge` - res = res + "\n" - trimmed = self.smtphunt; - if trimmed != [] and trimmed[len(trimmed) - 1] == "localhost": - trimmed = trimmed[0:len(trimmed) - 1] - if trimmed != [] and trimmed[len(trimmed) - 1] == hostname: - trimmed = trimmed[0:len(trimmed) - 1] - if trimmed != []: - res = res + " smtphost " - for x in trimmed: - res = res + " " + x - res = res + "\n" - trimmed = self.fetchdomains - if trimmed != [] and trimmed[len(trimmed) - 1] == hostname: - trimmed = trimmed[0:len(trimmed) - 1] - if trimmed != []: - res = res + " fetchdomains " - for x in trimmed: - res = res + " " + x - res = res + "\n" - if self.mailboxes: - res = res + " folder" - for x in self.mailboxes: - res = res + ' "%s"' % x - res = res + "\n" - for fld in ('smtpaddress', 'preconnect', 'postconnect', 'mda', 'bsmtp', 'properties'): - if getattr(self, fld): - res = res + " %s %s\n" % (fld, `getattr(self, fld)`) - if self.lmtp != UserDefaults.lmtp: - res = res + flag2str(self.lmtp, 'lmtp') - if self.antispam != UserDefaults.antispam: - res = res + " antispam " + self.antispam + "\n" - return res; + res = " " + res = res + "user " + `self.remote` + " there "; + if self.password: + res = res + "with password " + `self.password` + " " + if self.localnames: + res = res + "is" + for x in self.localnames: + res = res + " " + `x` + res = res + " here" + if (self.keep != UserDefaults.keep + or self.flush != UserDefaults.flush + or self.limitflush != UserDefaults.limitflush + or self.fetchall != UserDefaults.fetchall + or self.rewrite != UserDefaults.rewrite + or self.forcecr != UserDefaults.forcecr + or self.stripcr != UserDefaults.stripcr + or self.pass8bits != UserDefaults.pass8bits + or self.mimedecode != UserDefaults.mimedecode + or self.dropstatus != UserDefaults.dropstatus + or self.dropdelivered != UserDefaults.dropdelivered + or self.idle != UserDefaults.idle): + res = res + " options" + if self.keep != UserDefaults.keep: + res = res + flag2str(self.keep, 'keep') + if self.flush != UserDefaults.flush: + res = res + flag2str(self.flush, 'flush') + if self.limitflush != UserDefaults.limitflush: + res = res + flag2str(self.limitflush, 'limitflush') + if self.fetchall != UserDefaults.fetchall: + res = res + flag2str(self.fetchall, 'fetchall') + if self.rewrite != UserDefaults.rewrite: + res = res + flag2str(self.rewrite, 'rewrite') + if self.forcecr != UserDefaults.forcecr: + res = res + flag2str(self.forcecr, 'forcecr') + if self.stripcr != UserDefaults.stripcr: + res = res + flag2str(self.stripcr, 'stripcr') + if self.pass8bits != UserDefaults.pass8bits: + res = res + flag2str(self.pass8bits, 'pass8bits') + if self.mimedecode != UserDefaults.mimedecode: + res = res + flag2str(self.mimedecode, 'mimedecode') + if self.dropstatus != UserDefaults.dropstatus: + res = res + flag2str(self.dropstatus, 'dropstatus') + if self.dropdelivered != UserDefaults.dropdelivered: + res = res + flag2str(self.dropdelivered, 'dropdelivered') + if self.idle != UserDefaults.idle: + res = res + flag2str(self.idle, 'idle') + if self.limit != UserDefaults.limit: + res = res + " limit " + `self.limit` + if self.warnings != UserDefaults.warnings: + res = res + " warnings " + `self.warnings` + if self.fetchlimit != UserDefaults.fetchlimit: + res = res + " fetchlimit " + `self.fetchlimit` + if self.fetchsizelimit != UserDefaults.fetchsizelimit: + res = res + " fetchsizelimit " + `self.fetchsizelimit` + if self.fastuidl != UserDefaults.fastuidl: + res = res + " fastuidl " + `self.fastuidl` + if self.batchlimit != UserDefaults.batchlimit: + res = res + " batchlimit " + `self.batchlimit` + if self.ssl and self.ssl != UserDefaults.ssl: + res = res + flag2str(self.ssl, 'ssl') + if self.sslkey and self.sslkey != UserDefaults.sslkey: + res = res + " sslkey " + `self.sslkey` + if self.sslcert and self.sslcert != UserDefaults.sslcert: + res = res + " sslcert " + `self.sslcert` + if self.sslproto and self.sslproto != UserDefaults.sslproto: + res = res + " sslproto " + `self.sslproto` + if self.sslcertck and self.sslcertck != UserDefaults.sslcertck: + res = res + flag2str(self.sslcertck, 'sslcertck') + if self.sslcertpath and self.sslcertpath != UserDefaults.sslcertpath: + res = res + " sslcertpath " + `self.sslcertpath` + if self.sslcommonname and self.sslcommonname != UserDefaults.sslcommonname: + res = res + " sslcommonname " + `self.sslcommonname` + if self.sslfingerprint and self.sslfingerprint != UserDefaults.sslfingerprint: + res = res + " sslfingerprint " + `self.sslfingerprint` + if self.expunge != UserDefaults.expunge: + res = res + " expunge " + `self.expunge` + res = res + "\n" + trimmed = self.smtphunt; + if trimmed != [] and trimmed[len(trimmed) - 1] == "localhost": + trimmed = trimmed[0:len(trimmed) - 1] + if trimmed != [] and trimmed[len(trimmed) - 1] == hostname: + trimmed = trimmed[0:len(trimmed) - 1] + if trimmed != []: + res = res + " smtphost " + for x in trimmed: + res = res + " " + x + res = res + "\n" + trimmed = self.fetchdomains + if trimmed != [] and trimmed[len(trimmed) - 1] == hostname: + trimmed = trimmed[0:len(trimmed) - 1] + if trimmed != []: + res = res + " fetchdomains " + for x in trimmed: + res = res + " " + x + res = res + "\n" + if self.mailboxes: + res = res + " folder" + for x in self.mailboxes: + res = res + ' "%s"' % x + res = res + "\n" + for fld in ('smtpaddress', 'preconnect', 'postconnect', 'mda', 'bsmtp', 'properties'): + if getattr(self, fld): + res = res + " %s %s\n" % (fld, `getattr(self, fld)`) + if self.lmtp != UserDefaults.lmtp: + res = res + flag2str(self.lmtp, 'lmtp') + if self.antispam != UserDefaults.antispam: + res = res + " antispam " + self.antispam + "\n" + return res; def __str__(self): - return "[User: " + repr(self) + "]" + return "[User: " + repr(self) + "]" # # Helper code @@ -433,24 +433,24 @@ class User: # IANA port assignments and bogus 1109 entry ianaservices = {"pop2":109, - "pop3":110, - "1109":1109, - "imap":143, - "smtp":25, - "odmr":366} + "pop3":110, + "1109":1109, + "imap":143, + "smtp":25, + "odmr":366} # fetchmail protocol to IANA service name defaultports = {"auto":None, - "POP2":"pop2", - "POP3":"pop3", - "APOP":"pop3", - "KPOP":"1109", - "IMAP":"imap", - "ETRN":"smtp", - "ODMR":"odmr"} + "POP2":"pop2", + "POP3":"pop3", + "APOP":"pop3", + "KPOP":"1109", + "IMAP":"imap", + "ETRN":"smtp", + "ODMR":"odmr"} authlist = ("any", "password", "gssapi", "kerberos", "ssh", "otp", - "msn", "ntlm") + "msn", "ntlm") listboxhelp = { 'title' : 'List Selection Help', @@ -463,23 +463,23 @@ def flag2str(value, string): # make a string representation of a .fetchmailrc flag or negated flag str = "" if value != None: - str = str + (" ") - if value == FALSE: str = str + ("no ") - str = str + string; + str = str + (" ") + if value == FALSE: str = str + ("no ") + str = str + string; return str class LabeledEntry(Frame): # widget consisting of entry field with caption to left def bind(self, key, action): - self.E.bind(key, action) + self.E.bind(key, action) def focus_set(self): - self.E.focus_set() + self.E.focus_set() def __init__(self, Master, text, textvar, lwidth, ewidth=12): - Frame.__init__(self, Master) - self.L = Label(self, {'text':text, 'width':lwidth, 'anchor':'w'}) - self.E = Entry(self, {'textvar':textvar, 'width':ewidth}) - self.L.pack({'side':'left'}) - self.E.pack({'side':'left', 'expand':'1', 'fill':'x'}) + Frame.__init__(self, Master) + self.L = Label(self, {'text':text, 'width':lwidth, 'anchor':'w'}) + self.E = Entry(self, {'textvar':textvar, 'width':ewidth}) + self.L.pack({'side':'left'}) + self.E.pack({'side':'left', 'expand':'1', 'fill':'x'}) def ButtonBar(frame, legend, ref, alternatives, depth, command): # array of radio buttons, caption to left, picking from a string list @@ -487,20 +487,20 @@ def ButtonBar(frame, legend, ref, alternatives, depth, command): width = (len(alternatives)+1) / depth; Label(bar, text=legend).pack(side=LEFT) for column in range(width): - subframe = Frame(bar) - for row in range(depth): - ind = width * row + column - if ind < len(alternatives): - Radiobutton(subframe, - {'text':alternatives[ind], - 'variable':ref, - 'value':alternatives[ind], - 'command':command}).pack(side=TOP, anchor=W) - else: - # This is just a spacer - Radiobutton(subframe, - {'text':" ",'state':DISABLED}).pack(side=TOP, anchor=W) - subframe.pack(side=LEFT) + subframe = Frame(bar) + for row in range(depth): + ind = width * row + column + if ind < len(alternatives): + Radiobutton(subframe, + {'text':alternatives[ind], + 'variable':ref, + 'value':alternatives[ind], + 'command':command}).pack(side=TOP, anchor=W) + else: + # This is just a spacer + Radiobutton(subframe, + {'text':" ",'state':DISABLED}).pack(side=TOP, anchor=W) + subframe.pack(side=LEFT) bar.pack(side=TOP); return bar @@ -520,142 +520,142 @@ def helpwin(helpdict): scroll.pack(side=RIGHT, fill=BOTH) helpwin.textwidget.insert(END, helpdict['text']); Button(helpwin, text='Done', - command=lambda x=helpwin: x.destroy(), bd=2).pack() + command=lambda x=helpwin: x.destroy(), bd=2).pack() textframe.pack(side=TOP) def make_icon_window(base, image): try: - # Some older pythons will error out on this - icon_image = PhotoImage(data=image) - icon_window = Toplevel() - Label(icon_window, image=icon_image, bg='black').pack() - base.master.iconwindow(icon_window) - # Avoid TkInter brain death. PhotoImage objects go out of - # scope when the enclosing function returns. Therefore - # we have to explicitly link them to something. - base.keepalive.append(icon_image) + # Some older pythons will error out on this + icon_image = PhotoImage(data=image) + icon_window = Toplevel() + Label(icon_window, image=icon_image, bg='black').pack() + base.master.iconwindow(icon_window) + # Avoid TkInter brain death. PhotoImage objects go out of + # scope when the enclosing function returns. Therefore + # we have to explicitly link them to something. + base.keepalive.append(icon_image) except: - pass + pass class ListEdit(Frame): # edit a list of values (duplicates not allowed) with a supplied editor hook def __init__(self, newlegend, list, editor, deletor, master, helptxt): - self.editor = editor - self.deletor = deletor - self.list = list - - # Set up a widget to accept new elements - self.newval = StringVar(master) - newwin = LabeledEntry(master, newlegend, self.newval, '12') - newwin.bind('<Double-1>', self.handleNew) - newwin.bind('<Return>', self.handleNew) - newwin.pack(side=TOP, fill=X, anchor=E) - - # Edit the existing list - listframe = Frame(master) - scroll = Scrollbar(listframe) - self.listwidget = Listbox(listframe, height=0, selectmode='browse') - if self.list: - for x in self.list: - self.listwidget.insert(END, x) - listframe.pack(side=TOP, expand=YES, fill=BOTH) - self.listwidget.config(yscrollcommand=scroll.set) - self.listwidget.pack(side=LEFT, expand=YES, fill=BOTH) - scroll.config(command=self.listwidget.yview) - scroll.pack(side=RIGHT, fill=BOTH) - self.listwidget.config(selectmode=SINGLE, setgrid=TRUE) - self.listwidget.bind('<Double-1>', self.handleList); - self.listwidget.bind('<Return>', self.handleList); - - bf = Frame(master); - if self.editor: - Button(bf, text='Edit', command=self.editItem).pack(side=LEFT) - Button(bf, text='Delete', command=self.deleteItem).pack(side=LEFT) - if helptxt: - self.helptxt = helptxt - Button(bf, text='Help', fg='blue', - command=self.help).pack(side=RIGHT) - bf.pack(fill=X) + self.editor = editor + self.deletor = deletor + self.list = list + + # Set up a widget to accept new elements + self.newval = StringVar(master) + newwin = LabeledEntry(master, newlegend, self.newval, '12') + newwin.bind('<Double-1>', self.handleNew) + newwin.bind('<Return>', self.handleNew) + newwin.pack(side=TOP, fill=X, anchor=E) + + # Edit the existing list + listframe = Frame(master) + scroll = Scrollbar(listframe) + self.listwidget = Listbox(listframe, height=0, selectmode='browse') + if self.list: + for x in self.list: + self.listwidget.insert(END, x) + listframe.pack(side=TOP, expand=YES, fill=BOTH) + self.listwidget.config(yscrollcommand=scroll.set) + self.listwidget.pack(side=LEFT, expand=YES, fill=BOTH) + scroll.config(command=self.listwidget.yview) + scroll.pack(side=RIGHT, fill=BOTH) + self.listwidget.config(selectmode=SINGLE, setgrid=TRUE) + self.listwidget.bind('<Double-1>', self.handleList); + self.listwidget.bind('<Return>', self.handleList); + + bf = Frame(master); + if self.editor: + Button(bf, text='Edit', command=self.editItem).pack(side=LEFT) + Button(bf, text='Delete', command=self.deleteItem).pack(side=LEFT) + if helptxt: + self.helptxt = helptxt + Button(bf, text='Help', fg='blue', + command=self.help).pack(side=RIGHT) + bf.pack(fill=X) def help(self): - helpwin(self.helptxt) + helpwin(self.helptxt) def handleList(self, event): - self.editItem(); + self.editItem(); def handleNew(self, event): - item = self.newval.get() - if item: - entire = self.listwidget.get(0, self.listwidget.index('end')); - if item and (not entire) or (not item in self.listwidget.get(0, self.listwidget.index('end'))): - self.listwidget.insert('end', item) - if self.list != None: self.list.append(item) - if self.editor: - apply(self.editor, (item,)) - self.newval.set('') + item = self.newval.get() + if item: + entire = self.listwidget.get(0, self.listwidget.index('end')); + if item and (not entire) or (not item in self.listwidget.get(0, self.listwidget.index('end'))): + self.listwidget.insert('end', item) + if self.list != None: self.list.append(item) + if self.editor: + apply(self.editor, (item,)) + self.newval.set('') def editItem(self): - select = self.listwidget.curselection() - if not select: - helpwin(listboxhelp) - else: - index = select[0] - if index and self.editor: - label = self.listwidget.get(index); - if self.editor: - apply(self.editor, (label,)) + select = self.listwidget.curselection() + if not select: + helpwin(listboxhelp) + else: + index = select[0] + if index and self.editor: + label = self.listwidget.get(index); + if self.editor: + apply(self.editor, (label,)) def deleteItem(self): - select = self.listwidget.curselection() - if not select: - helpwin(listboxhelp) - else: - index = string.atoi(select[0]) - label = self.listwidget.get(index); - self.listwidget.delete(index) - if self.list != None: - del self.list[index] - if self.deletor != None: - apply(self.deletor, (label,)) + select = self.listwidget.curselection() + if not select: + helpwin(listboxhelp) + else: + index = string.atoi(select[0]) + label = self.listwidget.get(index); + self.listwidget.delete(index) + if self.list != None: + del self.list[index] + if self.deletor != None: + apply(self.deletor, (label,)) def ConfirmQuit(frame, context): ans = Dialog(frame, - title = 'Quit?', - text = 'Really quit ' + context + ' without saving?', - bitmap = 'question', - strings = ('Yes', 'No'), - default = 1) + title = 'Quit?', + text = 'Really quit ' + context + ' without saving?', + bitmap = 'question', + strings = ('Yes', 'No'), + default = 1) return ans.num == 0 def dispose_window(master, legend, help, savelegend='OK'): dispose = Frame(master, relief=RAISED, bd=5) Label(dispose, text=legend).pack(side=TOP,pady=10) Button(dispose, text=savelegend, fg='blue', - command=master.save).pack(side=LEFT) + command=master.save).pack(side=LEFT) Button(dispose, text='Quit', fg='blue', - command=master.nosave).pack(side=LEFT) + command=master.nosave).pack(side=LEFT) Button(dispose, text='Help', fg='blue', - command=lambda x=help: helpwin(x)).pack(side=RIGHT) + command=lambda x=help: helpwin(x)).pack(side=RIGHT) dispose.pack(fill=X) return dispose class MyWidget: # Common methods for Tkinter widgets -- deals with Tkinter declaration def post(self, widgetclass, field): - for x in widgetclass.typemap: - if x[1] == 'Boolean': - setattr(self, x[0], BooleanVar(self)) - elif x[1] == 'String': - setattr(self, x[0], StringVar(self)) - elif x[1] == 'Int': - setattr(self, x[0], IntVar(self)) - source = getattr(getattr(self, field), x[0]) - if source: - getattr(self, x[0]).set(source) + for x in widgetclass.typemap: + if x[1] == 'Boolean': + setattr(self, x[0], BooleanVar(self)) + elif x[1] == 'String': + setattr(self, x[0], StringVar(self)) + elif x[1] == 'Int': + setattr(self, x[0], IntVar(self)) + source = getattr(getattr(self, field), x[0]) + if source: + getattr(self, x[0]).set(source) def fetch(self, widgetclass, field): - for x in widgetclass.typemap: - setattr(getattr(self, field), x[0], getattr(self, x[0]).get()) + for x in widgetclass.typemap: + setattr(getattr(self, field), x[0], getattr(self, x[0]).get()) # # First, code to set the global fetchmail run controls. @@ -708,46 +708,46 @@ In the `Run Controls' panel, you can set the following options that control how fetchmail runs: Poll interval - Number of seconds to wait between polls in the background. - If zero, fetchmail will run in foreground. + Number of seconds to wait between polls in the background. + If zero, fetchmail will run in foreground. Logfile - If empty, emit progress and error messages to stderr. - Otherwise this gives the name of the files to write to. - This field is ignored if the "Log to syslog?" option is on. + If empty, emit progress and error messages to stderr. + Otherwise this gives the name of the files to write to. + This field is ignored if the "Log to syslog?" option is on. Idfile - If empty, store seen-message IDs in .fetchids under user's home - directory. If nonempty, use given file name. + If empty, store seen-message IDs in .fetchids under user's home + directory. If nonempty, use given file name. Postmaster - Who to send multidrop mail to as a last resort if no address can - be matched. Normally empty; in this case, fetchmail treats the - invoking user as the address of last resort unless that user is - root. If that user is root, fetchmail sends to `postmaster'. + Who to send multidrop mail to as a last resort if no address can + be matched. Normally empty; in this case, fetchmail treats the + invoking user as the address of last resort unless that user is + root. If that user is root, fetchmail sends to `postmaster'. Bounces to sender? - If this option is on (the default) error mail goes to the sender. - Otherwise it goes to the postmaster. + If this option is on (the default) error mail goes to the sender. + Otherwise it goes to the postmaster. Send spam bounces? - If this option is on, spam bounces are sent to the sender or - postmaster (depending on the "Bounces to sender?" option. Otherwise, - spam bounces are not sent (the default). + If this option is on, spam bounces are sent to the sender or + postmaster (depending on the "Bounces to sender?" option. Otherwise, + spam bounces are not sent (the default). Use soft bounces? - If this option is on, permanent delivery errors are treated as - temporary, i. e. mail is kept on the upstream server. Useful - during testing and after configuration changes, and on by - default. - If this option is off, permanent delivery errors delete - undeliverable mail from the upstream. + If this option is on, permanent delivery errors are treated as + temporary, i. e. mail is kept on the upstream server. Useful + during testing and after configuration changes, and on by + default. + If this option is off, permanent delivery errors delete + undeliverable mail from the upstream. Invisible - If false (the default) fetchmail generates a Received line into - each message and generates a HELO from the machine it is running on. - If true, fetchmail generates no Received line and HELOs as if it were - the remote site. + If false (the default) fetchmail generates a Received line into + each message and generates a HELO from the machine it is running on. + If true, fetchmail generates no Received line and HELOs as if it were + the remote site. In the `Remote Mail Configurations' panel, you can: @@ -767,155 +767,155 @@ This will take you to a site configuration dialogue. class ConfigurationEdit(Frame, MyWidget): def __init__(self, configuration, outfile, master, onexit): - self.subwidgets = {} - self.configuration = configuration - self.outfile = outfile - self.container = master - self.onexit = onexit - ConfigurationEdit.mode_to_help = { - 'novice':configure_novice_help, 'expert':configure_expert_help - } + self.subwidgets = {} + self.configuration = configuration + self.outfile = outfile + self.container = master + self.onexit = onexit + ConfigurationEdit.mode_to_help = { + 'novice':configure_novice_help, 'expert':configure_expert_help + } def server_edit(self, sitename): - self.subwidgets[sitename] = ServerEdit(sitename, self).edit(self.mode, Toplevel()) + self.subwidgets[sitename] = ServerEdit(sitename, self).edit(self.mode, Toplevel()) def server_delete(self, sitename): - try: - for user in self.subwidgets.keys(): - user.destruct() - del self.configuration[sitename] - except: - pass + try: + for user in self.subwidgets.keys(): + user.destruct() + del self.configuration[sitename] + except: + pass def edit(self, mode): - self.mode = mode - Frame.__init__(self, self.container) - self.master.title('fetchmail ' + self.mode + ' configurator'); - self.master.iconname('fetchmail ' + self.mode + ' configurator'); - self.master.protocol('WM_DELETE_WINDOW', self.nosave) - self.keepalive = [] # Use this to anchor the PhotoImage object - make_icon_window(self, fetchmail_icon) - Pack.config(self) - self.post(Configuration, 'configuration') - - dispose_window(self, - 'Configurator ' + self.mode + ' Controls', - ConfigurationEdit.mode_to_help[self.mode], - 'Save') - - gf = Frame(self, relief=RAISED, bd = 5) - Label(gf, - text='Fetchmail Run Controls', - bd=2).pack(side=TOP, pady=10) - - df = Frame(gf) - - ff = Frame(df) - if self.mode != 'novice': - # Set the postmaster - log = LabeledEntry(ff, ' Postmaster:', self.postmaster, '14') - log.pack(side=RIGHT, anchor=E) - - # Set the poll interval - de = LabeledEntry(ff, ' Poll interval:', self.poll_interval, '14') - de.pack(side=RIGHT, anchor=E) - ff.pack() - - df.pack() - - if self.mode != 'novice': - pf = Frame(gf) - Checkbutton(pf, - {'text':'Bounces to sender?', - 'variable':self.bouncemail, - 'relief':GROOVE}).pack(side=LEFT, anchor=W) - pf.pack(fill=X) - - sb = Frame(gf) - Checkbutton(sb, - {'text':'Send spam bounces?', - 'variable':self.spambounce, - 'relief':GROOVE}).pack(side=LEFT, anchor=W) - sb.pack(fill=X) - - sb = Frame(gf) - Checkbutton(sb, - {'text':'Treat permanent errors as temporary?', - 'variable':self.softbounce, - 'relief':GROOVE}).pack(side=LEFT, anchor=W) - sb.pack(fill=X) - - sf = Frame(gf) - Checkbutton(sf, - {'text':'Log to syslog?', - 'variable':self.syslog, - 'relief':GROOVE}).pack(side=LEFT, anchor=W) - log = LabeledEntry(sf, ' Logfile:', self.logfile, '14') - log.pack(side=RIGHT, anchor=E) - sf.pack(fill=X) - - Checkbutton(gf, - {'text':'Invisible mode?', - 'variable':self.invisible, - 'relief':GROOVE}).pack(side=LEFT, anchor=W) - # Set the idfile - log = LabeledEntry(gf, ' Idfile:', self.idfile, '14') - log.pack(side=RIGHT, anchor=E) - - gf.pack(fill=X) - - # Expert mode allows us to edit multiple sites - lf = Frame(self, relief=RAISED, bd=5) - Label(lf, - text='Remote Mail Server Configurations', - bd=2).pack(side=TOP, pady=10) - ListEdit('New Server:', - map(lambda x: x.pollname, self.configuration.servers), - lambda site, self=self: self.server_edit(site), - lambda site, self=self: self.server_delete(site), - lf, remotehelp) - lf.pack(fill=X) + self.mode = mode + Frame.__init__(self, self.container) + self.master.title('fetchmail ' + self.mode + ' configurator'); + self.master.iconname('fetchmail ' + self.mode + ' configurator'); + self.master.protocol('WM_DELETE_WINDOW', self.nosave) + self.keepalive = [] # Use this to anchor the PhotoImage object + make_icon_window(self, fetchmail_icon) + Pack.config(self) + self.post(Configuration, 'configuration') + + dispose_window(self, + 'Configurator ' + self.mode + ' Controls', + ConfigurationEdit.mode_to_help[self.mode], + 'Save') + + gf = Frame(self, relief=RAISED, bd = 5) + Label(gf, + text='Fetchmail Run Controls', + bd=2).pack(side=TOP, pady=10) + + df = Frame(gf) + + ff = Frame(df) + if self.mode != 'novice': + # Set the postmaster + log = LabeledEntry(ff, ' Postmaster:', self.postmaster, '14') + log.pack(side=RIGHT, anchor=E) + + # Set the poll interval + de = LabeledEntry(ff, ' Poll interval:', self.poll_interval, '14') + de.pack(side=RIGHT, anchor=E) + ff.pack() + + df.pack() + + if self.mode != 'novice': + pf = Frame(gf) + Checkbutton(pf, + {'text':'Bounces to sender?', + 'variable':self.bouncemail, + 'relief':GROOVE}).pack(side=LEFT, anchor=W) + pf.pack(fill=X) + + sb = Frame(gf) + Checkbutton(sb, + {'text':'Send spam bounces?', + 'variable':self.spambounce, + 'relief':GROOVE}).pack(side=LEFT, anchor=W) + sb.pack(fill=X) + + sb = Frame(gf) + Checkbutton(sb, + {'text':'Treat permanent errors as temporary?', + 'variable':self.softbounce, + 'relief':GROOVE}).pack(side=LEFT, anchor=W) + sb.pack(fill=X) + + sf = Frame(gf) + Checkbutton(sf, + {'text':'Log to syslog?', + 'variable':self.syslog, + 'relief':GROOVE}).pack(side=LEFT, anchor=W) + log = LabeledEntry(sf, ' Logfile:', self.logfile, '14') + log.pack(side=RIGHT, anchor=E) + sf.pack(fill=X) + + Checkbutton(gf, + {'text':'Invisible mode?', + 'variable':self.invisible, + 'relief':GROOVE}).pack(side=LEFT, anchor=W) + # Set the idfile + log = LabeledEntry(gf, ' Idfile:', self.idfile, '14') + log.pack(side=RIGHT, anchor=E) + + gf.pack(fill=X) + + # Expert mode allows us to edit multiple sites + lf = Frame(self, relief=RAISED, bd=5) + Label(lf, + text='Remote Mail Server Configurations', + bd=2).pack(side=TOP, pady=10) + ListEdit('New Server:', + map(lambda x: x.pollname, self.configuration.servers), + lambda site, self=self: self.server_edit(site), + lambda site, self=self: self.server_delete(site), + lf, remotehelp) + lf.pack(fill=X) def destruct(self): - for sitename in self.subwidgets.keys(): - self.subwidgets[sitename].destruct() - self.master.destroy() - self.onexit() + for sitename in self.subwidgets.keys(): + self.subwidgets[sitename].destruct() + self.master.destroy() + self.onexit() def nosave(self): - if ConfirmQuit(self, self.mode + " configuration editor"): - self.destruct() + if ConfirmQuit(self, self.mode + " configuration editor"): + self.destruct() def save(self): - for sitename in self.subwidgets.keys(): - self.subwidgets[sitename].save() - self.fetch(Configuration, 'configuration') - fm = None - if not self.outfile: - fm = sys.stdout - elif not os.path.isfile(self.outfile) or Dialog(self, - title = 'Overwrite existing run control file?', - text = 'Really overwrite existing run control file?', - bitmap = 'question', - strings = ('Yes', 'No'), - default = 1).num == 0: - try: - os.rename(self.outfile, self.outfile + "~") - # Pre-1.5.2 compatibility... - except os.error: - pass - oldumask = os.umask(077) - fm = open(self.outfile, 'w') - os.umask(oldumask) - if fm: - # be paranoid - if fm != sys.stdout: - os.chmod(self.outfile, 0600) - fm.write("# Configuration created %s by fetchmailconf %s\n" % (time.ctime(time.time()), version)) - fm.write(`self.configuration`) - if self.outfile: - fm.close() - self.destruct() + for sitename in self.subwidgets.keys(): + self.subwidgets[sitename].save() + self.fetch(Configuration, 'configuration') + fm = None + if not self.outfile: + fm = sys.stdout + elif not os.path.isfile(self.outfile) or Dialog(self, + title = 'Overwrite existing run control file?', + text = 'Really overwrite existing run control file?', + bitmap = 'question', + strings = ('Yes', 'No'), + default = 1).num == 0: + try: + os.rename(self.outfile, self.outfile + "~") + # Pre-1.5.2 compatibility... + except os.error: + pass + oldumask = os.umask(077) + fm = open(self.outfile, 'w') + os.umask(oldumask) + if fm: + # be paranoid + if fm != sys.stdout: + os.chmod(self.outfile, 0600) + fm.write("# Configuration created %s by fetchmailconf %s\n" % (time.ctime(time.time()), version)) + fm.write(`self.configuration`) + if self.outfile: + fm.close() + ... [truncated message content] |
From: Matthias A. <mat...@gm...> - 2016-06-08 19:47:56
|
Am 08.06.2016 um 21:36 schrieb Samuel Martin: > This change does: > - use repr(...) instead of `...` (see [1]); > - fix print call; > - fix octal numbers. > > [1] https://docs.python.org/release/3.0.1/whatsnew/3.0.html#removed-syntax > > Signed-off-by: Samuel Martin <s.m...@gm...> Hi Samuel, thanks for the submission. Out of curiosity and due to the "from __future__ import print_function()", what is the minimum Python 2.x version that this code will be compatible with? Anything older than 2.7? I have essentially purged python < 3.4 from all my work so I've forgotten the old stuff. This is mainly to figure out if I want to merge this on the master branch only, or on the legacy_64 branch as well. Cheers, Matthias |
From: Samuel M. <s.m...@gm...> - 2016-06-08 19:59:57
|
Hi Matthias, On Wed, Jun 8, 2016 at 9:47 PM, Matthias Andree <mat...@gm...> wrote: > Am 08.06.2016 um 21:36 schrieb Samuel Martin: >> This change does: >> - use repr(...) instead of `...` (see [1]); >> - fix print call; >> - fix octal numbers. >> >> [1] https://docs.python.org/release/3.0.1/whatsnew/3.0.html#removed-syntax >> >> Signed-off-by: Samuel Martin <s.m...@gm...> > > Hi Samuel, > > thanks for the submission. > > Out of curiosity and due to the "from __future__ import > print_function()", what is the minimum Python 2.x version that this code > will be compatible with? Anything older than 2.7? According to [1], print_function should be available since python-2.6. To be honest, I did check with python-2.7, but not with python-2.6 (long gone on my machine ;-]) > > I have essentially purged python < 3.4 from all my work so I've > forgotten the old stuff. > > This is mainly to figure out if I want to merge this on the master > branch only, or on the legacy_64 branch as well. I forgot to mention it, these patches have been done on top of the legacy_64 branch. > > Cheers, > Matthias [1] https://docs.python.org/2/library/__future__.html Regards, -- Samuel |
From: Matthias A. <mat...@gm...> - 2016-06-08 20:42:14
|
Am 08.06.2016 um 21:59 schrieb Samuel Martin: > Hi Matthias, > > On Wed, Jun 8, 2016 at 9:47 PM, Matthias Andree <mat...@gm...> wrote: >> Am 08.06.2016 um 21:36 schrieb Samuel Martin: >>> This change does: >>> - use repr(...) instead of `...` (see [1]); >>> - fix print call; >>> - fix octal numbers. >>> >>> [1] https://docs.python.org/release/3.0.1/whatsnew/3.0.html#removed-syntax >>> >>> Signed-off-by: Samuel Martin <s.m...@gm...> >> >> Hi Samuel, >> >> thanks for the submission. >> >> Out of curiosity and due to the "from __future__ import >> print_function()", what is the minimum Python 2.x version that this code >> will be compatible with? Anything older than 2.7? > According to [1], print_function should be available since python-2.6. > To be honest, I did check with python-2.7, but not with python-2.6 > (long gone on my machine ;-]) Just checked, Python 2.6 is no longer supported, so for legacy_64 that change should be acceptable because it paves the way this code can run for a while longer. I've done away with compatibility with older OpenSSL anyways and need TLSv1.2 capable implementations, so why stop there... |
From: Matthias A. <mat...@gm...> - 2016-06-08 20:41:16
|
Am 08.06.2016 um 21:36 schrieb Samuel Martin: > Hi all, > > Here is a couple of patchs fixing only python code formating in the > fetchmailconf.py file. > > After this series, fetchmailconf.py is compatible with python-2 and > python-3. I have applied them to the legacy_64 branch, but it doesn't seem to be fully compatible, it still uses "hash.has_key(k)" when it should use "k in hash", doesn't work with execfile(), doesn't know the new tkinter and tkinter.dialog names, and other issues -- it still needs to run through 2to3.py. (Python 3.4.3 used here.) Also, it doesn't apply to the master branch currently. Needs to be redone there properly. Fetchmailconf.py needs some love for the new SSL options anyways... |