[Buildroot] [PATCH] package/fetchmail: fix *.pyc compilation
Samuel Martin
s.martin49 at gmail.com
Wed Jun 8 20:08:51 UTC 2016
This change fixes the fetchmailconf.py compilation by adding a couple of
patches making this script compatible with both python-2 and python-3:
- tabs/spaces indentation fixes;
- 2to3 fixes.
Fixes:
http://autobuild.buildroot.org/results/700/7009445dd116a1c02db82a351d38db44db8dad16/build-end.log
...
These fetchmail patches have been sent upstream [1].
[1] https://sourceforge.net/p/fetchmail/mailman/message/35146111/
Signed-off-by: Samuel Martin <s.martin49 at gmail.com>
---
...nf.py-fix-tabs-spaces-mixup-preventing-fr.patch | 3074 ++++++++++++++++++++
...nf.py-make-fetchmailconf.py-python-2-3-co.patch | 279 ++
2 files changed, 3353 insertions(+)
create mode 100644 package/fetchmail/0003-fetchmailconf.py-fix-tabs-spaces-mixup-preventing-fr.patch
create mode 100644 package/fetchmail/0004-fetchmailconf.py-make-fetchmailconf.py-python-2-3-co.patch
diff --git a/package/fetchmail/0003-fetchmailconf.py-fix-tabs-spaces-mixup-preventing-fr.patch b/package/fetchmail/0003-fetchmailconf.py-fix-tabs-spaces-mixup-preventing-fr.patch
new file mode 100644
index 0000000..681a288
--- /dev/null
+++ b/package/fetchmail/0003-fetchmailconf.py-fix-tabs-spaces-mixup-preventing-fr.patch
@@ -0,0 +1,3074 @@
+From db0000ebcb65812e753748198e92d6acc4a9f677 Mon Sep 17 00:00:00 2001
+From: Samuel Martin <s.martin49 at gmail.com>
+Date: Tue, 7 Jun 2016 23:03:53 +0200
+Subject: [PATCH] fetchmailconf.py: fix tabs/spaces mixup preventing from
+ compiling the pyc module
+
+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.martin49 at gmail.com>
+---
+ 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()
++ self.destruct()
+
+ #
+ # Server editing stuff.
+@@ -1063,217 +1063,217 @@ user's options on that site.
+
+ class ServerEdit(Frame, MyWidget):
+ def __init__(self, host, parent):
+- self.parent = parent
+- self.server = None
+- self.subwidgets = {}
+- for site in parent.configuration.servers:
+- if site.pollname == host:
+- self.server = site
+- if (self.server == None):
+- self.server = Server()
+- self.server.pollname = host
+- self.server.via = None
+- parent.configuration.servers.append(self.server)
++ self.parent = parent
++ self.server = None
++ self.subwidgets = {}
++ for site in parent.configuration.servers:
++ if site.pollname == host:
++ self.server = site
++ if (self.server == None):
++ self.server = Server()
++ self.server.pollname = host
++ self.server.via = None
++ parent.configuration.servers.append(self.server)
+
+ def edit(self, mode, master=None):
+- Frame.__init__(self, master)
+- Pack.config(self)
+- self.master.title('Fetchmail host ' + self.server.pollname);
+- self.master.iconname('Fetchmail host ' + self.server.pollname);
+- self.post(Server, 'server')
+- self.makeWidgets(self.server.pollname, mode)
+- self.keepalive = [] # Use this to anchor the PhotoImage object
+- make_icon_window(self, fetchmail_icon)
++ Frame.__init__(self, master)
++ Pack.config(self)
++ self.master.title('Fetchmail host ' + self.server.pollname);
++ self.master.iconname('Fetchmail host ' + self.server.pollname);
++ self.post(Server, 'server')
++ self.makeWidgets(self.server.pollname, mode)
++ self.keepalive = [] # Use this to anchor the PhotoImage object
++ make_icon_window(self, fetchmail_icon)
+ # self.grab_set()
+ # self.focus_set()
+ # self.wait_window()
+- return self
++ return self
+
+ def destruct(self):
+- for username in self.subwidgets.keys():
+- self.subwidgets[username].destruct()
+- del self.parent.subwidgets[self.server.pollname]
+- self.master.destroy()
++ for username in self.subwidgets.keys():
++ self.subwidgets[username].destruct()
++ del self.parent.subwidgets[self.server.pollname]
++ self.master.destroy()
+
+ def nosave(self):
+- if ConfirmQuit(self, 'server option editing'):
+- self.destruct()
++ if ConfirmQuit(self, 'server option editing'):
++ self.destruct()
+
+ def save(self):
+- self.fetch(Server, 'server')
+- for username in self.subwidgets.keys():
+- self.subwidgets[username].save()
+- self.destruct()
++ self.fetch(Server, 'server')
++ for username in self.subwidgets.keys():
++ self.subwidgets[username].save()
++ self.destruct()
+
+ def defaultPort(self):
+- proto = self.protocol.get()
+- # Callback to reset the port number whenever the protocol type changes.
+- # We used to only reset the port if it had a default (zero) value.
+- # This turns out to be a bad idea especially in Novice mode -- if
+- # you set POP3 and then set IMAP, the port invisibly remained 110.
+- # Now we reset unconditionally on the theory that if you're setting
+- # a custom port number you should be in expert mode and playing
+- # close enough attention to notice this...
+- self.service.set(defaultports[proto])
+- if not proto in ("POP3", "APOP", "KPOP"): self.uidl.state = DISABLED
++ proto = self.protocol.get()
++ # Callback to reset the port number whenever the protocol type changes.
++ # We used to only reset the port if it had a default (zero) value.
++ # This turns out to be a bad idea especially in Novice mode -- if
++ # you set POP3 and then set IMAP, the port invisibly remained 110.
++ # Now we reset unconditionally on the theory that if you're setting
++ # a custom port number you should be in expert mode and playing
++ # close enough attention to notice this...
++ self.service.set(defaultports[proto])
++ if not proto in ("POP3", "APOP", "KPOP"): self.uidl.state = DISABLED
+
+ def user_edit(self, username, mode):
+- self.subwidgets[username] = UserEdit(username, self).edit(mode, Toplevel())
++ self.subwidgets[username] = UserEdit(username, self).edit(mode, Toplevel())
+
+ def user_delete(self, username):
+- if self.subwidgets.has_key(username):
+- self.subwidgets[username].destruct()
+- del self.server[username]
++ if self.subwidgets.has_key(username):
++ self.subwidgets[username].destruct()
++ del self.server[username]
+
+ def makeWidgets(self, host, mode):
+- topwin = dispose_window(self, "Server options for querying " + host, serverhelp)
+-
+- leftwin = Frame(self);
+- leftwidth = '25';
+-
+- if mode != 'novice':
+- ctlwin = Frame(leftwin, relief=RAISED, bd=5)
+- Label(ctlwin, text="Run Controls").pack(side=TOP)
+- Checkbutton(ctlwin, text='Poll ' + host + ' normally?', variable=self.active).pack(side=TOP)
+- Checkbutton(ctlwin, text='Pass messages with bad headers?',
+- variable=self.badheader).pack(side=TOP)
+- LabeledEntry(ctlwin, 'True name of ' + host + ':',
+- self.via, leftwidth).pack(side=TOP, fill=X)
+- LabeledEntry(ctlwin, 'Cycles to skip between polls:',
+- self.interval, leftwidth).pack(side=TOP, fill=X)
+- LabeledEntry(ctlwin, 'Server timeout (seconds):',
+- self.timeout, leftwidth).pack(side=TOP, fill=X)
+- Button(ctlwin, text='Help', fg='blue',
+- command=lambda: helpwin(controlhelp)).pack(side=RIGHT)
+- ctlwin.pack(fill=X)
+-
+- # Compute the available protocols from the compile-time options
+- protolist = ['auto']
+- if 'pop2' in feature_options:
+- protolist.append("POP2")
+- if 'pop3' in feature_options:
+- protolist = protolist + ["POP3", "APOP", "KPOP"]
+- if 'sdps' in feature_options:
+- protolist.append("SDPS")
+- if 'imap' in feature_options:
+- protolist.append("IMAP")
+- if 'etrn' in feature_options:
+- protolist.append("ETRN")
+- if 'odmr' in feature_options:
+- protolist.append("ODMR")
+-
+- protwin = Frame(leftwin, relief=RAISED, bd=5)
+- Label(protwin, text="Protocol").pack(side=TOP)
+- ButtonBar(protwin, '',
+- self.protocol, protolist, 2,
+- self.defaultPort)
+- if mode != 'novice':
+- LabeledEntry(protwin, 'On server TCP/IP service:',
+- self.service, leftwidth).pack(side=TOP, fill=X)
+- self.defaultPort()
+- Checkbutton(protwin,
+- text="POP3: track `seen' with client-side UIDLs?",
+- variable=self.uidl).pack(side=TOP)
+- Button(protwin, text='Probe for supported protocols', fg='blue',
+- command=self.autoprobe).pack(side=LEFT)
+- Button(protwin, text='Help', fg='blue',
+- command=lambda: helpwin(protohelp)).pack(side=RIGHT)
+- protwin.pack(fill=X)
+-
+- userwin = Frame(leftwin, relief=RAISED, bd=5)
+- Label(userwin, text="User entries for " + host).pack(side=TOP)
+- ListEdit("New user: ",
+- map(lambda x: x.remote, self.server.users),
+- lambda u, m=mode, s=self: s.user_edit(u, m),
+- lambda u, s=self: s.user_delete(u),
+- userwin, suserhelp)
+- userwin.pack(fill=X)
+-
+- leftwin.pack(side=LEFT, anchor=N, fill=X);
+-
+- if mode != 'novice':
+- rightwin = Frame(self);
+-
+- mdropwin = Frame(rightwin, relief=RAISED, bd=5)
+- Label(mdropwin, text="Multidrop options").pack(side=TOP)
+- LabeledEntry(mdropwin, 'Envelope address header:',
+- self.envelope, '22').pack(side=TOP, fill=X)
+- LabeledEntry(mdropwin, 'Envelope headers to skip:',
+- self.envskip, '22').pack(side=TOP, fill=X)
+- LabeledEntry(mdropwin, 'Name prefix to strip:',
+- self.qvirtual, '22').pack(side=TOP, fill=X)
+- Checkbutton(mdropwin, text="Enable multidrop DNS lookup?",
+- variable=self.dns).pack(side=TOP)
+- Label(mdropwin, text="DNS aliases").pack(side=TOP)
+- ListEdit("New alias: ", self.server.aka, None, None, mdropwin, None)
+- Label(mdropwin, text="Domains to be considered local").pack(side=TOP)
+- ListEdit("New domain: ",
+- self.server.localdomains, None, None, mdropwin, multihelp)
+- mdropwin.pack(fill=X)
+-
+- if os_type in ('linux', 'freebsd'):
+- secwin = Frame(rightwin, relief=RAISED, bd=5)
+- Label(secwin, text="Security").pack(side=TOP)
+- # Don't actually let users set this. KPOP sets it implicitly
+- ButtonBar(secwin, 'Authorization mode:',
+- self.auth, authlist, 2, None).pack(side=TOP)
+- if os_type == 'linux' or os_type == 'freebsd' or 'interface' in dictmembers:
+- LabeledEntry(secwin, 'IP range to check before poll:',
+- self.interface, leftwidth).pack(side=TOP, fill=X)
+- if os_type == 'linux' or os_type == 'freebsd' or 'monitor' in dictmembers:
+- LabeledEntry(secwin, 'Interface to monitor:',
+- self.monitor, leftwidth).pack(side=TOP, fill=X)
+- # Someday this should handle Kerberos 5 too
+- if 'kerberos' in feature_options:
+- LabeledEntry(secwin, 'Principal:',
+- self.principal, '12').pack(side=TOP, fill=X)
+- # ESMTP authentication
+- LabeledEntry(secwin, 'ESMTP name:',
+- self.esmtpname, '12').pack(side=TOP, fill=X)
+- LabeledEntry(secwin, 'ESMTP password:',
+- self.esmtppassword, '12').pack(side=TOP, fill=X)
+- Button(secwin, text='Help', fg='blue',
+- command=lambda: helpwin(sechelp)).pack(side=RIGHT)
+- secwin.pack(fill=X)
+-
+- rightwin.pack(side=LEFT, anchor=N);
++ topwin = dispose_window(self, "Server options for querying " + host, serverhelp)
++
++ leftwin = Frame(self);
++ leftwidth = '25';
++
++ if mode != 'novice':
++ ctlwin = Frame(leftwin, relief=RAISED, bd=5)
++ Label(ctlwin, text="Run Controls").pack(side=TOP)
++ Checkbutton(ctlwin, text='Poll ' + host + ' normally?', variable=self.active).pack(side=TOP)
++ Checkbutton(ctlwin, text='Pass messages with bad headers?',
++ variable=self.badheader).pack(side=TOP)
++ LabeledEntry(ctlwin, 'True name of ' + host + ':',
++ self.via, leftwidth).pack(side=TOP, fill=X)
++ LabeledEntry(ctlwin, 'Cycles to skip between polls:',
++ self.interval, leftwidth).pack(side=TOP, fill=X)
++ LabeledEntry(ctlwin, 'Server timeout (seconds):',
++ self.timeout, leftwidth).pack(side=TOP, fill=X)
++ Button(ctlwin, text='Help', fg='blue',
++ command=lambda: helpwin(controlhelp)).pack(side=RIGHT)
++ ctlwin.pack(fill=X)
++
++ # Compute the available protocols from the compile-time options
++ protolist = ['auto']
++ if 'pop2' in feature_options:
++ protolist.append("POP2")
++ if 'pop3' in feature_options:
++ protolist = protolist + ["POP3", "APOP", "KPOP"]
++ if 'sdps' in feature_options:
++ protolist.append("SDPS")
++ if 'imap' in feature_options:
++ protolist.append("IMAP")
++ if 'etrn' in feature_options:
++ protolist.append("ETRN")
++ if 'odmr' in feature_options:
++ protolist.append("ODMR")
++
++ protwin = Frame(leftwin, relief=RAISED, bd=5)
++ Label(protwin, text="Protocol").pack(side=TOP)
++ ButtonBar(protwin, '',
++ self.protocol, protolist, 2,
++ self.defaultPort)
++ if mode != 'novice':
++ LabeledEntry(protwin, 'On server TCP/IP service:',
++ self.service, leftwidth).pack(side=TOP, fill=X)
++ self.defaultPort()
++ Checkbutton(protwin,
++ text="POP3: track `seen' with client-side UIDLs?",
++ variable=self.uidl).pack(side=TOP)
++ Button(protwin, text='Probe for supported protocols', fg='blue',
++ command=self.autoprobe).pack(side=LEFT)
++ Button(protwin, text='Help', fg='blue',
++ command=lambda: helpwin(protohelp)).pack(side=RIGHT)
++ protwin.pack(fill=X)
++
++ userwin = Frame(leftwin, relief=RAISED, bd=5)
++ Label(userwin, text="User entries for " + host).pack(side=TOP)
++ ListEdit("New user: ",
++ map(lambda x: x.remote, self.server.users),
++ lambda u, m=mode, s=self: s.user_edit(u, m),
++ lambda u, s=self: s.user_delete(u),
++ userwin, suserhelp)
++ userwin.pack(fill=X)
++
++ leftwin.pack(side=LEFT, anchor=N, fill=X);
++
++ if mode != 'novice':
++ rightwin = Frame(self);
++
++ mdropwin = Frame(rightwin, relief=RAISED, bd=5)
++ Label(mdropwin, text="Multidrop options").pack(side=TOP)
++ LabeledEntry(mdropwin, 'Envelope address header:',
++ self.envelope, '22').pack(side=TOP, fill=X)
++ LabeledEntry(mdropwin, 'Envelope headers to skip:',
++ self.envskip, '22').pack(side=TOP, fill=X)
++ LabeledEntry(mdropwin, 'Name prefix to strip:',
++ self.qvirtual, '22').pack(side=TOP, fill=X)
++ Checkbutton(mdropwin, text="Enable multidrop DNS lookup?",
++ variable=self.dns).pack(side=TOP)
++ Label(mdropwin, text="DNS aliases").pack(side=TOP)
++ ListEdit("New alias: ", self.server.aka, None, None, mdropwin, None)
++ Label(mdropwin, text="Domains to be considered local").pack(side=TOP)
++ ListEdit("New domain: ",
++ self.server.localdomains, None, None, mdropwin, multihelp)
++ mdropwin.pack(fill=X)
++
++ if os_type in ('linux', 'freebsd'):
++ secwin = Frame(rightwin, relief=RAISED, bd=5)
++ Label(secwin, text="Security").pack(side=TOP)
++ # Don't actually let users set this. KPOP sets it implicitly
++ ButtonBar(secwin, 'Authorization mode:',
++ self.auth, authlist, 2, None).pack(side=TOP)
++ if os_type == 'linux' or os_type == 'freebsd' or 'interface' in dictmembers:
++ LabeledEntry(secwin, 'IP range to check before poll:',
++ self.interface, leftwidth).pack(side=TOP, fill=X)
++ if os_type == 'linux' or os_type == 'freebsd' or 'monitor' in dictmembers:
++ LabeledEntry(secwin, 'Interface to monitor:',
++ self.monitor, leftwidth).pack(side=TOP, fill=X)
++ # Someday this should handle Kerberos 5 too
++ if 'kerberos' in feature_options:
++ LabeledEntry(secwin, 'Principal:',
++ self.principal, '12').pack(side=TOP, fill=X)
++ # ESMTP authentication
++ LabeledEntry(secwin, 'ESMTP name:',
++ self.esmtpname, '12').pack(side=TOP, fill=X)
++ LabeledEntry(secwin, 'ESMTP password:',
++ self.esmtppassword, '12').pack(side=TOP, fill=X)
++ Button(secwin, text='Help', fg='blue',
++ command=lambda: helpwin(sechelp)).pack(side=RIGHT)
++ secwin.pack(fill=X)
++
++ rightwin.pack(side=LEFT, anchor=N);
+
+ def autoprobe(self):
+- # Note: this only handles case (1) near fetchmail.c:1032
+- # We're assuming people smart enough to set up ssh tunneling
+- # won't need autoprobing.
+- if self.server.via:
+- realhost = self.server.via
+- else:
+- realhost = self.server.pollname
+- greetline = None
+- for protocol in ("IMAP","POP3","POP2"):
+- service = defaultports[protocol]
+- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+- try:
+- sock.connect((realhost, ianaservices[service]))
+- greetline = sock.recv(1024)
+- sock.close()
+- except:
+- pass
+- else:
+- break
+- confwin = Toplevel()
+- if greetline == None:
+- title = "Autoprobe of " + realhost + " failed"
+- confirm = """
++ # Note: this only handles case (1) near fetchmail.c:1032
++ # We're assuming people smart enough to set up ssh tunneling
++ # won't need autoprobing.
++ if self.server.via:
++ realhost = self.server.via
++ else:
++ realhost = self.server.pollname
++ greetline = None
++ for protocol in ("IMAP","POP3","POP2"):
++ service = defaultports[protocol]
++ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
++ try:
++ sock.connect((realhost, ianaservices[service]))
++ greetline = sock.recv(1024)
++ sock.close()
++ except:
++ pass
++ else:
++ break
++ confwin = Toplevel()
++ if greetline == None:
++ title = "Autoprobe of " + realhost + " failed"
++ confirm = """
+ Fetchmailconf didn't find any mailservers active.
+ This could mean the host doesn't support any,
+ or that your Internet connection is down, or
+ that the host is so slow that the probe timed
+ out before getting a response.
+ """
+- else:
+- warnings = ''
+- # OK, now try to recognize potential problems
++ else:
++ warnings = ''
++ # OK, now try to recognize potential problems
+
+- if protocol == "POP2":
+- warnings = warnings + """
++ if protocol == "POP2":
++ warnings = warnings + """
+ It appears you have somehow found a mailserver running only POP2.
+ Congratulations. Have you considered a career in archaeology?
+
+@@ -1286,8 +1286,8 @@ switch --enable-POP2.
+
+ ### POP3 servers start here
+
+- if string.find(greetline, "1.003") > 0 or string.find(greetline, "1.004") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "1.003") > 0 or string.find(greetline, "1.004") > 0:
++ warnings = warnings + """
+ This appears to be an old version of the UC Davis POP server. These are
+ dangerously unreliable (among other problems, they may drop your mailbox
+ on the floor if your connection is interrupted during the session).
+@@ -1296,8 +1296,8 @@ It is strongly recommended that you find a better POP3 server. The fetchmail
+ FAQ includes pointers to good ones.
+
+ """
+- if string.find(greetline, "comcast.net") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "comcast.net") > 0:
++ warnings = warnings + """
+ The Comcast Maillennium POP3 server only returns the first 80K of a long
+ message retrieved with TOP. Its response to RETR is normal, so use the
+ `fetchall' option.
+@@ -1321,8 +1321,8 @@ message retrieved with TOP. Its response to RETR is normal, so use the
+ #
+ # +OK Cubic Circle's v1.31 1998/05/13 POP3 ready <6229000062f95036 at wakko>
+ #
+- if string.find(greetline, "Cubic Circle") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "Cubic Circle") > 0:
++ warnings = warnings + """
+ I see your server is running cucipop. Better make sure the server box
+ isn't a SunOS 4.1.4 machine; cucipop tickles a bug in SunOS realloc()
+ under that version, and doesn't cope with the result gracefully. Newer
+@@ -1332,8 +1332,8 @@ Also, some versions of cucipop don't assert an exclusive lock on your
+ mailbox when it's being queried. This means that if you have more than
+ one fetchmail query running against the same mailbox, bad things can happen.
+ """
+- if string.find(greetline, "David POP3 Server") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "David POP3 Server") > 0:
++ warnings = warnings + """
+ This POP3 server is badly broken. You should get rid of it -- and the
+ brain-dead Microsoft operating system it rode in on.
+
+@@ -1341,20 +1341,20 @@ brain-dead Microsoft operating system it rode in on.
+ # The greeting line on the server known to be buggy is:
+ # +OK POP3 server ready (running FTGate V2, 2, 1, 0 Jun 21 1999 09:55:01)
+ #
+- if string.find(greetline, "FTGate") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "FTGate") > 0:
++ warnings = warnings + """
+ This POP server has a weird bug; it says OK twice in response to TOP.
+ Its response to RETR is normal, so use the `fetchall' option.
+
+ """
+- if string.find(greetline, " geonet.de") > 0:
+- warnings = warnings + """
++ if string.find(greetline, " geonet.de") > 0:
++ warnings = warnings + """
+ You appear to be using geonet. As of late 2002, the TOP command on
+ geonet's POP3 is broken. Use the fetchall option.
+
+ """
+- if string.find(greetline, "OpenMail") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "OpenMail") > 0:
++ warnings = warnings + """
+ You appear to be using some version of HP OpenMail. Many versions of
+ OpenMail do not process the "TOP" command correctly; the symptom is that
+ only the header and first line of each message is retrieved. To work
+@@ -1362,16 +1362,16 @@ around this bug, turn on `fetchall' on all user entries associated with
+ this server.
+
+ """
+- if string.find(greetline, "Escape character is") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "Escape character is") > 0:
++ warnings = warnings + """
+ Your greeting line looks like it was written by a fetid pile of
+ camel dung identified to me as `popa3d written by Solar Designer'.
+ Beware! The UIDL support in this thing is known to be completely broken,
+ and other things probably are too.
+
+ """
+- if string.find(greetline, "MercuryP/NLM v1.48") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "MercuryP/NLM v1.48") > 0:
++ warnings = warnings + """
+ This is not a POP3 server. It has delusions of being one, but after
+ RETR all messages are automatically marked to be deleted. The only
+ way to prevent this is to issue an RSET before leaving the server.
+@@ -1379,8 +1379,8 @@ Fetchmail does this, but we suspect this is probably broken in lots
+ of other ways, too.
+
+ """
+- if string.find(greetline, "POP-Max") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "POP-Max") > 0:
++ warnings = warnings + """
+ The Mail Max POP3 server screws up on mail with attachments. It
+ reports the message size with attachments included, but doesn't
+ download them on a RETR or TOP (this violates the IMAP RFCs). It also
+@@ -1388,14 +1388,14 @@ doesn't implement TOP correctly. You should get rid of it -- and the
+ brain-dead NT server it rode in on.
+
+ """
+- if string.find(greetline, "POP3 Server Ready") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "POP3 Server Ready") > 0:
++ warnings = warnings + """
+ Some server that uses this greeting line has been observed to choke on
+ TOP %d 99999999. Use the fetchall option. if necessary, to force RETR.
+
+ """
+- if string.find(greetline, "QPOP") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "QPOP") > 0:
++ warnings = warnings + """
+ This appears to be a version of Eudora qpopper. That's good. Fetchmail
+ knows all about qpopper. However, be aware that the 2.53 version of
+ qpopper does something odd that causes fetchmail to hang with a socket
+@@ -1404,16 +1404,16 @@ it has been observed with fetchpop. The fix is to upgrade to qpopper
+ 3.0beta or a more recent version. Better yet, switch to IMAP.
+
+ """
+- if string.find(greetline, " sprynet.com") > 0:
+- warnings = warnings + """
++ if string.find(greetline, " sprynet.com") > 0:
++ warnings = warnings + """
+ You appear to be using a SpryNet server. In mid-1999 it was reported that
+ the SpryNet TOP command marks messages seen. Therefore, for proper error
+ recovery in the event of a line drop, it is strongly recommended that you
+ turn on `fetchall' on all user entries associated with this server.
+
+ """
+- if string.find(greetline, "TEMS POP3") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "TEMS POP3") > 0:
++ warnings = warnings + """
+ Your POP3 server has "TEMS" in its header line. At least one such
+ server does not process the "TOP" command correctly; the symptom is
+ that fetchmail hangs when trying to retrieve mail. To work around
+@@ -1421,8 +1421,8 @@ this bug, turn on `fetchall' on all user entries associated with this
+ server.
+
+ """
+- if string.find(greetline, " spray.se") > 0:
+- warnings = warnings + """
++ if string.find(greetline, " spray.se") > 0:
++ warnings = warnings + """
+ Your POP3 server has "spray.se" in its header line. In May 2000 at
+ least one such server did not process the "TOP" command correctly; the
+ symptom is that messages are treated as headerless. To work around
+@@ -1430,8 +1430,8 @@ this bug, turn on `fetchall' on all user entries associated with this
+ server.
+
+ """
+- if string.find(greetline, " usa.net") > 0:
+- warnings = warnings + """
++ if string.find(greetline, " usa.net") > 0:
++ warnings = warnings + """
+ You appear to be using USA.NET's free mail service. Their POP3 servers
+ (at least as of the 2.2 version in use mid-1998) are quite flaky, but
+ fetchmail can compensate. They seem to require that fetchall be switched on
+@@ -1444,15 +1444,15 @@ Therefore, it is strongly recommended that you turn on `fetchall' on all
+ user entries associated with this server.
+
+ """
+- if string.find(greetline, " Novonyx POP3") > 0:
+- warnings = warnings + """
++ if string.find(greetline, " Novonyx POP3") > 0:
++ warnings = warnings + """
+ Your mailserver is running Novonyx POP3. This server, at least as of
+ version 2.17, seems to have problems handling and reporting seen bits.
+ You may have to use the fetchall option.
+
+ """
+- if string.find(greetline, " IMS POP3") > 0:
+- warnings = warnings + """
++ if string.find(greetline, " IMS POP3") > 0:
++ warnings = warnings + """
+ Some servers issuing the greeting line 'IMS POP3' have been known to
+ do byte-stuffing incorrectly. This means that if a message you receive
+ has a . (period) at start of line, fetchmail will become confused and
+@@ -1462,8 +1462,8 @@ probably wedge itself. (This bug was recorded on IMS POP3 0.86.)
+
+ ### IMAP servers start here
+
+- if string.find(greetline, "GroupWise") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "GroupWise") > 0:
++ warnings = warnings + """
+ The Novell GroupWise IMAP server would be better named GroupFoolish;
+ it is (according to the designer of IMAP) unusably broken. Among
+ other things, it doesn't include a required content length in its
+@@ -1475,8 +1475,8 @@ with code as shoddy as GroupWise seems to be, you will probably pay
+ for it with other problems.<p>
+
+ """
+- if string.find(greetline, "InterChange") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "InterChange") > 0:
++ warnings = warnings + """
+
+ The InterChange IMAP server at release levels below 3.61.08 screws up
+ on mail with attachments. It doesn't fetch them if you give it a
+@@ -1487,16 +1487,16 @@ Exchange (quite legally under RFC2062) rejectsit. The InterChange
+ folks claim to have fixed this bug in 3.61.08.
+
+ """
+- if string.find(greetline, "Imail") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "Imail") > 0:
++ warnings = warnings + """
+ We've seen a bug report indicating that this IMAP server (at least as of
+ version 5.0.7) returns an invalid body size for messages with MIME
+ attachments; the effect is to drop the attachments on the floor. We
+ recommend you upgrade to a non-broken IMAP server.
+
+ """
+- if string.find(greetline, "Domino IMAP4") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "Domino IMAP4") > 0:
++ warnings = warnings + """
+ Your IMAP server appears to be Lotus Domino. This server, at least up
+ to version 4.6.2a, has a bug in its generation of MIME boundaries (see
+ the details in the fetchmail FAQ). As a result, even MIME aware MUAs
+@@ -1507,16 +1507,16 @@ POP3 facility is enabled, we recommend you fall back on it.
+
+ ### Checks for protocol variants start here
+
+- closebrak = string.find(greetline, ">")
+- if closebrak > 0 and greetline[closebrak+1] == "\r":
+- warnings = warnings + """
++ closebrak = string.find(greetline, ">")
++ if closebrak > 0 and greetline[closebrak+1] == "\r":
++ warnings = warnings + """
+ It looks like you could use APOP on this server and avoid sending it your
+ password in clear. You should talk to the mailserver administrator about
+ this.
+
+ """
+- if string.find(greetline, "IMAP2bis") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "IMAP2bis") > 0:
++ warnings = warnings + """
+ IMAP2bis servers have a minor problem; they can't peek at messages without
+ marking them seen. If you take a line hit during the retrieval, the
+ interrupted message may get left on the server, marked seen.
+@@ -1529,30 +1529,30 @@ To fix this bug, upgrade to an IMAP4 server. The fetchmail FAQ includes
+ a pointer to an open-source implementation.
+
+ """
+- if string.find(greetline, "IMAP4rev1") > 0:
+- warnings = warnings + """
++ if string.find(greetline, "IMAP4rev1") > 0:
++ warnings = warnings + """
+ I see an IMAP4rev1 server. Excellent. This is (a) the best kind of
+ remote-mail server, and (b) the one the fetchmail author uses. Fetchmail
+ has therefore been extremely well tested with this class of server.
+
+ """
+- if warnings == '':
+- warnings = warnings + """
++ if warnings == '':
++ warnings = warnings + """
+ Fetchmail doesn't know anything special about this server type.
+
+ """
+
+- # Display success window with warnings
+- title = "Autoprobe of " + realhost + " succeeded"
+- confirm = "The " + protocol + " server said:\n\n" + greetline + warnings
+- self.protocol.set(protocol)
+- self.service.set(defaultports[protocol])
+- confwin.title(title)
+- confwin.iconname(title)
+- Label(confwin, text=title).pack()
+- Message(confwin, text=confirm, width=600).pack()
+- Button(confwin, text='Done',
+- command=lambda x=confwin: x.destroy(), bd=2).pack()
++ # Display success window with warnings
++ title = "Autoprobe of " + realhost + " succeeded"
++ confirm = "The " + protocol + " server said:\n\n" + greetline + warnings
++ self.protocol.set(protocol)
++ self.service.set(defaultports[protocol])
++ confwin.title(title)
++ confwin.iconname(title)
++ Label(confwin, text=title).pack()
++ Message(confwin, text=confirm, width=600).pack()
++ Button(confwin, text='Done',
++ command=lambda x=confwin: x.destroy(), bd=2).pack()
+
+ #
+ # User editing stuff
+@@ -1597,193 +1597,193 @@ of sending it to your local system.
+
+ class UserEdit(Frame, MyWidget):
+ def __init__(self, username, parent):
+- self.parent = parent
+- self.user = None
+- for user in parent.server.users:
+- if user.remote == username:
+- self.user = user
+- if self.user == None:
+- self.user = User()
+- self.user.remote = username
+- self.user.localnames = [username]
+- parent.server.users.append(self.user)
++ self.parent = parent
++ self.user = None
++ for user in parent.server.users:
++ if user.remote == username:
++ self.user = user
++ if self.user == None:
++ self.user = User()
++ self.user.remote = username
++ self.user.localnames = [username]
++ parent.server.users.append(self.user)
+
+ def edit(self, mode, master=None):
+- Frame.__init__(self, master)
+- Pack.config(self)
+- self.master.title('Fetchmail user ' + self.user.remote
+- + ' querying ' + self.parent.server.pollname);
+- self.master.iconname('Fetchmail user ' + self.user.remote);
+- self.post(User, 'user')
+- self.makeWidgets(mode, self.parent.server.pollname)
+- self.keepalive = [] # Use this to anchor the PhotoImage object
+- make_icon_window(self, fetchmail_icon)
++ Frame.__init__(self, master)
++ Pack.config(self)
++ self.master.title('Fetchmail user ' + self.user.remote
++ + ' querying ' + self.parent.server.pollname);
++ self.master.iconname('Fetchmail user ' + self.user.remote);
++ self.post(User, 'user')
++ self.makeWidgets(mode, self.parent.server.pollname)
++ self.keepalive = [] # Use this to anchor the PhotoImage object
++ make_icon_window(self, fetchmail_icon)
+ # self.grab_set()
+ # self.focus_set()
+ # self.wait_window()
+- return self
++ return self
+
+ def destruct(self):
+- # Yes, this test can fail -- if you delete the parent window.
+- if self.parent.subwidgets.has_key(self.user.remote):
+- del self.parent.subwidgets[self.user.remote]
+- self.master.destroy()
++ # Yes, this test can fail -- if you delete the parent window.
++ if self.parent.subwidgets.has_key(self.user.remote):
++ del self.parent.subwidgets[self.user.remote]
++ self.master.destroy()
+
+ def nosave(self):
+- if ConfirmQuit(self, 'user option editing'):
+- self.destruct()
++ if ConfirmQuit(self, 'user option editing'):
++ self.destruct()
+
+ def save(self):
+- ok = 0
+- for x in self.user.localnames: ok = ok + (string.find(x, '@') != -1)
+- if ok == 0 or Dialog(self,
+- title = "Really accept an embedded '@' ?",
+- text = "Local names with an embedded '@', such as in foo at bar "
+- "might result in your mail being sent to foo at bar.com "
+- "instead of your local system.\n Are you sure you want "
+- "a local user name with an '@' in it?",
+- bitmap = 'question',
+- strings = ('Yes', 'No'),
+- default = 1).num == 0:
+- self.fetch(User, 'user')
+- self.destruct()
++ ok = 0
++ for x in self.user.localnames: ok = ok + (string.find(x, '@') != -1)
++ if ok == 0 or Dialog(self,
++ title = "Really accept an embedded '@' ?",
++ text = "Local names with an embedded '@', such as in foo at bar "
++ "might result in your mail being sent to foo at bar.com "
++ "instead of your local system.\n Are you sure you want "
++ "a local user name with an '@' in it?",
++ bitmap = 'question',
++ strings = ('Yes', 'No'),
++ default = 1).num == 0:
++ self.fetch(User, 'user')
++ self.destruct()
+
+ def makeWidgets(self, mode, servername):
+- dispose_window(self,
+- "User options for " + self.user.remote + " querying " + servername,
+- userhelp)
+-
+- if mode != 'novice':
+- leftwin = Frame(self);
+- else:
+- leftwin = self
+-
+- secwin = Frame(leftwin, relief=RAISED, bd=5)
+- Label(secwin, text="Authentication").pack(side=TOP)
+- LabeledEntry(secwin, 'Password:',
+- self.password, '12').pack(side=TOP, fill=X)
+- secwin.pack(fill=X, anchor=N)
+-
+- if 'ssl' in feature_options or 'ssl' in dictmembers:
+- sslwin = Frame(leftwin, relief=RAISED, bd=5)
+- Checkbutton(sslwin, text="Use SSL?",
+- variable=self.ssl).pack(side=TOP, fill=X)
+- LabeledEntry(sslwin, 'SSL key:',
+- self.sslkey, '14').pack(side=TOP, fill=X)
+- LabeledEntry(sslwin, 'SSL certificate:',
+- self.sslcert, '14').pack(side=TOP, fill=X)
+- Checkbutton(sslwin, text="Check server SSL certificate?",
+- variable=self.sslcertck).pack(side=TOP, fill=X)
+- LabeledEntry(sslwin, 'SSL trusted certificate directory:',
+- self.sslcertpath, '14').pack(side=TOP, fill=X)
+- LabeledEntry(sslwin, 'SSL CommonName:',
+- self.sslcommonname, '14').pack(side=TOP, fill=X)
+- LabeledEntry(sslwin, 'SSL key fingerprint:',
+- self.sslfingerprint, '14').pack(side=TOP, fill=X)
+- sslwin.pack(fill=X, anchor=N)
+-
+- names = Frame(leftwin, relief=RAISED, bd=5)
+- Label(names, text="Local names").pack(side=TOP)
+- ListEdit("New name: ",
+- self.user.localnames, None, None, names, localhelp)
+- names.pack(fill=X, anchor=N)
+-
+- if mode != 'novice':
+- targwin = Frame(leftwin, relief=RAISED, bd=5)
+- Label(targwin, text="Forwarding Options").pack(side=TOP)
+- Label(targwin, text="Listeners to forward to").pack(side=TOP)
+- ListEdit("New listener:",
+- self.user.smtphunt, None, None, targwin, None)
+- Label(targwin, text="Domains to fetch from (ODMR/ETRN only)").pack(side=TOP)
+- ListEdit("Domains:",
+- self.user.fetchdomains, None, None, targwin, None)
+- LabeledEntry(targwin, 'Use domain on RCPT TO line:',
+- self.smtpaddress, '26').pack(side=TOP, fill=X)
+- LabeledEntry(targwin, 'Set fixed RCPT TO address:',
+- self.smtpname, '26').pack(side=TOP, fill=X)
+- LabeledEntry(targwin, 'Connection setup command:',
+- self.preconnect, '26').pack(side=TOP, fill=X)
+- LabeledEntry(targwin, 'Connection wrapup command:',
+- self.postconnect, '26').pack(side=TOP, fill=X)
+- LabeledEntry(targwin, 'Local delivery agent:',
+- self.mda, '26').pack(side=TOP, fill=X)
+- LabeledEntry(targwin, 'BSMTP output file:',
+- self.bsmtp, '26').pack(side=TOP, fill=X)
+- LabeledEntry(targwin, 'Listener spam-block codes:',
+- self.antispam, '26').pack(side=TOP, fill=X)
+- LabeledEntry(targwin, 'Pass-through properties:',
+- self.properties, '26').pack(side=TOP, fill=X)
+- Checkbutton(targwin, text="Use LMTP?",
+- variable=self.lmtp).pack(side=TOP, fill=X)
+- targwin.pack(fill=X, anchor=N)
+-
+- if mode != 'novice':
+- leftwin.pack(side=LEFT, fill=X, anchor=N)
+- rightwin = Frame(self)
+- else:
+- rightwin = self
+-
+- optwin = Frame(rightwin, relief=RAISED, bd=5)
+- Label(optwin, text="Processing Options").pack(side=TOP)
+- Checkbutton(optwin, text="Suppress deletion of messages after reading",
+- variable=self.keep).pack(side=TOP, anchor=W)
+- Checkbutton(optwin, text="Fetch old messages as well as new",
+- variable=self.fetchall).pack(side=TOP, anchor=W)
+- if mode != 'novice':
+- Checkbutton(optwin, text="Flush seen messages before retrieval",
+- variable=self.flush).pack(side=TOP, anchor=W)
+- Checkbutton(optwin, text="Flush oversized messages before retrieval",
+- variable=self.limitflush).pack(side=TOP, anchor=W)
+- Checkbutton(optwin, text="Rewrite To/Cc/Bcc messages to enable reply",
+- variable=self.rewrite).pack(side=TOP, anchor=W)
+- Checkbutton(optwin, text="Force CR/LF at end of each line",
+- variable=self.forcecr).pack(side=TOP, anchor=W)
+- Checkbutton(optwin, text="Strip CR from end of each line",
+- variable=self.stripcr).pack(side=TOP, anchor=W)
+- Checkbutton(optwin, text="Pass 8 bits even though SMTP says 7BIT",
+- variable=self.pass8bits).pack(side=TOP, anchor=W)
+- Checkbutton(optwin, text="Undo MIME armoring on header and body",
+- variable=self.mimedecode).pack(side=TOP, anchor=W)
+- Checkbutton(optwin, text="Drop Status lines from forwarded messages",
+- variable=self.dropstatus).pack(side=TOP, anchor=W)
+- Checkbutton(optwin, text="Drop Delivered-To lines from forwarded messages",
+- variable=self.dropdelivered).pack(side=TOP, anchor=W)
+- optwin.pack(fill=X)
+-
+- if mode != 'novice':
+- limwin = Frame(rightwin, relief=RAISED, bd=5)
+- Label(limwin, text="Resource Limits").pack(side=TOP)
+- LabeledEntry(limwin, 'Message size limit:',
+- self.limit, '30').pack(side=TOP, fill=X)
+- LabeledEntry(limwin, 'Size warning interval:',
+- self.warnings, '30').pack(side=TOP, fill=X)
+- LabeledEntry(limwin, 'Max messages to fetch per poll:',
+- self.fetchlimit, '30').pack(side=TOP, fill=X)
+- LabeledEntry(limwin, 'Max message sizes to fetch per transaction:',
+- self.fetchsizelimit, '30').pack(side=TOP, fill=X)
+- if self.parent.server.protocol not in ('ETRN', 'ODMR'):
+- LabeledEntry(limwin, 'Use fast UIDL:',
+- self.fastuidl, '30').pack(side=TOP, fill=X)
+- LabeledEntry(limwin, 'Max messages to forward per poll:',
+- self.batchlimit, '30').pack(side=TOP, fill=X)
+- if self.parent.server.protocol not in ('ETRN', 'ODMR'):
+- LabeledEntry(limwin, 'Interval between expunges:',
+- self.expunge, '30').pack(side=TOP, fill=X)
+- Checkbutton(limwin, text="Idle after each poll (IMAP only)",
+- variable=self.idle).pack(side=TOP, anchor=W)
+- limwin.pack(fill=X)
+-
+- if self.parent.server.protocol == 'IMAP':
+- foldwin = Frame(rightwin, relief=RAISED, bd=5)
+- Label(foldwin, text="Remote folders (IMAP only)").pack(side=TOP)
+- ListEdit("New folder:", self.user.mailboxes,
+- None, None, foldwin, None)
+- foldwin.pack(fill=X, anchor=N)
+-
+- if mode != 'novice':
+- rightwin.pack(side=LEFT)
+- else:
+- self.pack()
++ dispose_window(self,
++ "User options for " + self.user.remote + " querying " + servername,
++ userhelp)
++
++ if mode != 'novice':
++ leftwin = Frame(self);
++ else:
++ leftwin = self
++
++ secwin = Frame(leftwin, relief=RAISED, bd=5)
++ Label(secwin, text="Authentication").pack(side=TOP)
++ LabeledEntry(secwin, 'Password:',
++ self.password, '12').pack(side=TOP, fill=X)
++ secwin.pack(fill=X, anchor=N)
++
++ if 'ssl' in feature_options or 'ssl' in dictmembers:
++ sslwin = Frame(leftwin, relief=RAISED, bd=5)
++ Checkbutton(sslwin, text="Use SSL?",
++ variable=self.ssl).pack(side=TOP, fill=X)
++ LabeledEntry(sslwin, 'SSL key:',
++ self.sslkey, '14').pack(side=TOP, fill=X)
++ LabeledEntry(sslwin, 'SSL certificate:',
++ self.sslcert, '14').pack(side=TOP, fill=X)
++ Checkbutton(sslwin, text="Check server SSL certificate?",
++ variable=self.sslcertck).pack(side=TOP, fill=X)
++ LabeledEntry(sslwin, 'SSL trusted certificate directory:',
++ self.sslcertpath, '14').pack(side=TOP, fill=X)
++ LabeledEntry(sslwin, 'SSL CommonName:',
++ self.sslcommonname, '14').pack(side=TOP, fill=X)
++ LabeledEntry(sslwin, 'SSL key fingerprint:',
++ self.sslfingerprint, '14').pack(side=TOP, fill=X)
++ sslwin.pack(fill=X, anchor=N)
++
++ names = Frame(leftwin, relief=RAISED, bd=5)
++ Label(names, text="Local names").pack(side=TOP)
++ ListEdit("New name: ",
++ self.user.localnames, None, None, names, localhelp)
++ names.pack(fill=X, anchor=N)
++
++ if mode != 'novice':
++ targwin = Frame(leftwin, relief=RAISED, bd=5)
++ Label(targwin, text="Forwarding Options").pack(side=TOP)
++ Label(targwin, text="Listeners to forward to").pack(side=TOP)
++ ListEdit("New listener:",
++ self.user.smtphunt, None, None, targwin, None)
++ Label(targwin, text="Domains to fetch from (ODMR/ETRN only)").pack(side=TOP)
++ ListEdit("Domains:",
++ self.user.fetchdomains, None, None, targwin, None)
++ LabeledEntry(targwin, 'Use domain on RCPT TO line:',
++ self.smtpaddress, '26').pack(side=TOP, fill=X)
++ LabeledEntry(targwin, 'Set fixed RCPT TO address:',
++ self.smtpname, '26').pack(side=TOP, fill=X)
++ LabeledEntry(targwin, 'Connection setup command:',
++ self.preconnect, '26').pack(side=TOP, fill=X)
++ LabeledEntry(targwin, 'Connection wrapup command:',
++ self.postconnect, '26').pack(side=TOP, fill=X)
++ LabeledEntry(targwin, 'Local delivery agent:',
++ self.mda, '26').pack(side=TOP, fill=X)
++ LabeledEntry(targwin, 'BSMTP output file:',
++ self.bsmtp, '26').pack(side=TOP, fill=X)
++ LabeledEntry(targwin, 'Listener spam-block codes:',
++ self.antispam, '26').pack(side=TOP, fill=X)
++ LabeledEntry(targwin, 'Pass-through properties:',
++ self.properties, '26').pack(side=TOP, fill=X)
++ Checkbutton(targwin, text="Use LMTP?",
++ variable=self.lmtp).pack(side=TOP, fill=X)
++ targwin.pack(fill=X, anchor=N)
++
++ if mode != 'novice':
++ leftwin.pack(side=LEFT, fill=X, anchor=N)
++ rightwin = Frame(self)
++ else:
++ rightwin = self
++
++ optwin = Frame(rightwin, relief=RAISED, bd=5)
++ Label(optwin, text="Processing Options").pack(side=TOP)
++ Checkbutton(optwin, text="Suppress deletion of messages after reading",
++ variable=self.keep).pack(side=TOP, anchor=W)
++ Checkbutton(optwin, text="Fetch old messages as well as new",
++ variable=self.fetchall).pack(side=TOP, anchor=W)
++ if mode != 'novice':
++ Checkbutton(optwin, text="Flush seen messages before retrieval",
++ variable=self.flush).pack(side=TOP, anchor=W)
++ Checkbutton(optwin, text="Flush oversized messages before retrieval",
++ variable=self.limitflush).pack(side=TOP, anchor=W)
++ Checkbutton(optwin, text="Rewrite To/Cc/Bcc messages to enable reply",
++ variable=self.rewrite).pack(side=TOP, anchor=W)
++ Checkbutton(optwin, text="Force CR/LF at end of each line",
++ variable=self.forcecr).pack(side=TOP, anchor=W)
++ Checkbutton(optwin, text="Strip CR from end of each line",
++ variable=self.stripcr).pack(side=TOP, anchor=W)
++ Checkbutton(optwin, text="Pass 8 bits even though SMTP says 7BIT",
++ variable=self.pass8bits).pack(side=TOP, anchor=W)
++ Checkbutton(optwin, text="Undo MIME armoring on header and body",
++ variable=self.mimedecode).pack(side=TOP, anchor=W)
++ Checkbutton(optwin, text="Drop Status lines from forwarded messages",
++ variable=self.dropstatus).pack(side=TOP, anchor=W)
++ Checkbutton(optwin, text="Drop Delivered-To lines from forwarded messages",
++ variable=self.dropdelivered).pack(side=TOP, anchor=W)
++ optwin.pack(fill=X)
++
++ if mode != 'novice':
++ limwin = Frame(rightwin, relief=RAISED, bd=5)
++ Label(limwin, text="Resource Limits").pack(side=TOP)
++ LabeledEntry(limwin, 'Message size limit:',
++ self.limit, '30').pack(side=TOP, fill=X)
++ LabeledEntry(limwin, 'Size warning interval:',
++ self.warnings, '30').pack(side=TOP, fill=X)
++ LabeledEntry(limwin, 'Max messages to fetch per poll:',
++ self.fetchlimit, '30').pack(side=TOP, fill=X)
++ LabeledEntry(limwin, 'Max message sizes to fetch per transaction:',
++ self.fetchsizelimit, '30').pack(side=TOP, fill=X)
++ if self.parent.server.protocol not in ('ETRN', 'ODMR'):
++ LabeledEntry(limwin, 'Use fast UIDL:',
++ self.fastuidl, '30').pack(side=TOP, fill=X)
++ LabeledEntry(limwin, 'Max messages to forward per poll:',
++ self.batchlimit, '30').pack(side=TOP, fill=X)
++ if self.parent.server.protocol not in ('ETRN', 'ODMR'):
++ LabeledEntry(limwin, 'Interval between expunges:',
++ self.expunge, '30').pack(side=TOP, fill=X)
++ Checkbutton(limwin, text="Idle after each poll (IMAP only)",
++ variable=self.idle).pack(side=TOP, anchor=W)
++ limwin.pack(fill=X)
++
++ if self.parent.server.protocol == 'IMAP':
++ foldwin = Frame(rightwin, relief=RAISED, bd=5)
++ Label(foldwin, text="Remote folders (IMAP only)").pack(side=TOP)
++ ListEdit("New folder:", self.user.mailboxes,
++ None, None, foldwin, None)
++ foldwin.pack(fill=X, anchor=N)
++
++ if mode != 'novice':
++ rightwin.pack(side=LEFT)
++ else:
++ self.pack()
+
+
+ #
+@@ -1793,162 +1793,162 @@ class UserEdit(Frame, MyWidget):
+
+ class Configurator(Frame):
+ def __init__(self, outfile, master, onexit, parent):
+- Frame.__init__(self, master)
+- self.outfile = outfile
+- self.onexit = onexit
+- self.parent = parent
+- self.master.title('fetchmail configurator');
+- self.master.iconname('fetchmail configurator');
+- Pack.config(self)
+- self.keepalive = [] # Use this to anchor the PhotoImage object
+- make_icon_window(self, fetchmail_icon)
+-
+- Message(self, text="""
++ Frame.__init__(self, master)
++ self.outfile = outfile
++ self.onexit = onexit
++ self.parent = parent
++ self.master.title('fetchmail configurator');
++ self.master.iconname('fetchmail configurator');
++ Pack.config(self)
++ self.keepalive = [] # Use this to anchor the PhotoImage object
++ make_icon_window(self, fetchmail_icon)
++
++ Message(self, text="""
+ Use `Novice Configuration' for basic fetchmail setup;
+ with this, you can easily set up a single-drop connection
+ to one remote mail server.
+ """, width=600).pack(side=TOP)
+- Button(self, text='Novice Configuration',
+- fg='blue', command=self.novice).pack()
++ Button(self, text='Novice Configuration',
++ fg='blue', command=self.novice).pack()
+
+- Message(self, text="""
++ Message(self, text="""
+ Use `Expert Configuration' for advanced fetchmail setup,
+ including multiple-site or multidrop connections.
+ """, width=600).pack(side=TOP)
+- Button(self, text='Expert Configuration',
+- fg='blue', command=self.expert).pack()
++ Button(self, text='Expert Configuration',
++ fg='blue', command=self.expert).pack()
+
+- Message(self, text="""
++ Message(self, text="""
+ Or you can just select `Quit' to leave the configurator now and
+ return to the main panel.
+ """, width=600).pack(side=TOP)
+- Button(self, text='Quit', fg='blue', command=self.leave).pack()
+- master.protocol("WM_DELETE_WINDOW", self.leave)
++ Button(self, text='Quit', fg='blue', command=self.leave).pack()
++ master.protocol("WM_DELETE_WINDOW", self.leave)
+
+ def novice(self):
+- self.master.destroy()
+- ConfigurationEdit(Fetchmailrc, self.outfile, Toplevel(), self.onexit).edit('novice')
++ self.master.destroy()
++ ConfigurationEdit(Fetchmailrc, self.outfile, Toplevel(), self.onexit).edit('novice')
+
+ def expert(self):
+- self.master.destroy()
+- ConfigurationEdit(Fetchmailrc, self.outfile, Toplevel(), self.onexit).edit('expert')
++ self.master.destroy()
++ ConfigurationEdit(Fetchmailrc, self.outfile, Toplevel(), self.onexit).edit('expert')
+
+ def leave(self):
+- self.master.destroy()
+- self.onexit()
++ self.master.destroy()
++ self.onexit()
+
+ # Run a command in a scrolling text widget, displaying its output
+
+ class RunWindow(Frame):
+ def __init__(self, command, master, parent):
+- Frame.__init__(self, master)
+- self.master = master
+- self.master.title('fetchmail run window');
+- self.master.iconname('fetchmail run window');
+- Pack.config(self)
+- Label(self,
+- text="Running "+command,
+- bd=2).pack(side=TOP, pady=10)
+- self.keepalive = [] # Use this to anchor the PhotoImage object
+- make_icon_window(self, fetchmail_icon)
+-
+- # This is a scrolling text window
+- textframe = Frame(self)
+- scroll = Scrollbar(textframe)
+- self.textwidget = Text(textframe, setgrid=TRUE)
+- textframe.pack(side=TOP, expand=YES, fill=BOTH)
+- self.textwidget.config(yscrollcommand=scroll.set)
+- self.textwidget.pack(side=LEFT, expand=YES, fill=BOTH)
+- scroll.config(command=self.textwidget.yview)
+- scroll.pack(side=RIGHT, fill=BOTH)
+- textframe.pack(side=TOP)
+-
+- Button(self, text='Quit', fg='blue', command=self.leave).pack()
+-
+- self.update() # Draw widget before executing fetchmail
+-
+- # Always look for a runnable command in the directory we're running in
+- # first. This avoids some obscure version-skew errors that can occur
+- # if you pick up an old fetchmail from the standard system locations.
+- os.environ["PATH"] = os.path.dirname(sys.argv[0]) + ":" + os.environ["PATH"]
+- child_stdout = os.popen(command + " 2>&1 </dev/null", "r")
+- while 1:
+- ch = child_stdout.read(1)
+- if not ch:
+- break
+- self.textwidget.insert(END, ch)
+- self.textwidget.insert(END, "Done.")
+- self.textwidget.see(END);
++ Frame.__init__(self, master)
++ self.master = master
++ self.master.title('fetchmail run window');
++ self.master.iconname('fetchmail run window');
++ Pack.config(self)
++ Label(self,
++ text="Running "+command,
++ bd=2).pack(side=TOP, pady=10)
++ self.keepalive = [] # Use this to anchor the PhotoImage object
++ make_icon_window(self, fetchmail_icon)
++
++ # This is a scrolling text window
++ textframe = Frame(self)
++ scroll = Scrollbar(textframe)
++ self.textwidget = Text(textframe, setgrid=TRUE)
++ textframe.pack(side=TOP, expand=YES, fill=BOTH)
++ self.textwidget.config(yscrollcommand=scroll.set)
++ self.textwidget.pack(side=LEFT, expand=YES, fill=BOTH)
++ scroll.config(command=self.textwidget.yview)
++ scroll.pack(side=RIGHT, fill=BOTH)
++ textframe.pack(side=TOP)
++
++ Button(self, text='Quit', fg='blue', command=self.leave).pack()
++
++ self.update() # Draw widget before executing fetchmail
++
++ # Always look for a runnable command in the directory we're running in
++ # first. This avoids some obscure version-skew errors that can occur
++ # if you pick up an old fetchmail from the standard system locations.
++ os.environ["PATH"] = os.path.dirname(sys.argv[0]) + ":" + os.environ["PATH"]
++ child_stdout = os.popen(command + " 2>&1 </dev/null", "r")
++ while 1:
++ ch = child_stdout.read(1)
++ if not ch:
++ break
++ self.textwidget.insert(END, ch)
++ self.textwidget.insert(END, "Done.")
++ self.textwidget.see(END);
+
+ def leave(self):
+- self.master.destroy()
++ self.master.destroy()
+
+ # Here's where we choose either configuration or launching
+
+ class MainWindow(Frame):
+ def __init__(self, outfile, master=None):
+- Frame.__init__(self, master)
+- self.outfile = outfile
+- self.master.title('fetchmail launcher');
+- self.master.iconname('fetchmail launcher');
+- Pack.config(self)
+- Label(self,
+- text='Fetchmailconf ' + version,
+- bd=2).pack(side=TOP, pady=10)
+- self.keepalive = [] # Use this to anchor the PhotoImage object
+- make_icon_window(self, fetchmail_icon)
+- self.debug = 0
+-
+- ## Test icon display with the following:
+- # icon_image = PhotoImage(data=fetchmail_icon)
+- # Label(self, image=icon_image).pack(side=TOP, pady=10)
+- # self.keepalive.append(icon_image)
+-
+- Message(self, text="""
++ Frame.__init__(self, master)
++ self.outfile = outfile
++ self.master.title('fetchmail launcher');
++ self.master.iconname('fetchmail launcher');
++ Pack.config(self)
++ Label(self,
++ text='Fetchmailconf ' + version,
++ bd=2).pack(side=TOP, pady=10)
++ self.keepalive = [] # Use this to anchor the PhotoImage object
++ make_icon_window(self, fetchmail_icon)
++ self.debug = 0
++
++ ## Test icon display with the following:
++ # icon_image = PhotoImage(data=fetchmail_icon)
++ # Label(self, image=icon_image).pack(side=TOP, pady=10)
++ # self.keepalive.append(icon_image)
++
++ Message(self, text="""
+ Use `Configure fetchmail' to tell fetchmail about the remote
+ servers it should poll (the host name, your username there,
+ whether to use POP or IMAP, and so forth).
+ """, width=600).pack(side=TOP)
+- self.configbutton = Button(self, text='Configure fetchmail',
+- fg='blue', command=self.configure)
+- self.configbutton.pack()
++ self.configbutton = Button(self, text='Configure fetchmail',
++ fg='blue', command=self.configure)
++ self.configbutton.pack()
+
+- Message(self, text="""
++ Message(self, text="""
+ Use `Run fetchmail' to run fetchmail with debugging enabled.
+ This is a good way to test out a new configuration.
+ """, width=600).pack(side=TOP)
+- Button(self, text='Run fetchmail',fg='blue', command=self.test).pack()
++ Button(self, text='Run fetchmail',fg='blue', command=self.test).pack()
+
+- Message(self, text="""
++ Message(self, text="""
+ Use `Run fetchmail' to run fetchmail in foreground.
+ Progress messages will be shown, but not debug messages.
+ """, width=600).pack(side=TOP)
+- Button(self, text='Run fetchmail', fg='blue', command=self.run).pack()
++ Button(self, text='Run fetchmail', fg='blue', command=self.run).pack()
+
+- Message(self, text="""
++ Message(self, text="""
+ Or you can just select `Quit' to exit the launcher now.
+ """, width=600).pack(side=TOP)
+- Button(self, text='Quit', fg='blue', command=self.leave).pack()
++ Button(self, text='Quit', fg='blue', command=self.leave).pack()
+
+ def configure(self):
+- self.configbutton.configure(state=DISABLED)
+- Configurator(self.outfile, Toplevel(),
+- lambda self=self: self.configbutton.configure(state=NORMAL),
+- self)
++ self.configbutton.configure(state=DISABLED)
++ Configurator(self.outfile, Toplevel(),
++ lambda self=self: self.configbutton.configure(state=NORMAL),
++ self)
+ def test(self):
+- cmd = "fetchmail -N -d0 --nosyslog -v"
+- if rcfile:
+- cmd = cmd + " -f " + rcfile
+- RunWindow(cmd, Toplevel(), self)
++ cmd = "fetchmail -N -d0 --nosyslog -v"
++ if rcfile:
++ cmd = cmd + " -f " + rcfile
++ RunWindow(cmd, Toplevel(), self)
+
+ def run(self):
+- cmd = "fetchmail -N -d0"
+- if rcfile:
+- cmd = cmd + " -f " + rcfile
+- RunWindow(cmd, Toplevel(), self)
++ cmd = "fetchmail -N -d0"
++ if rcfile:
++ cmd = cmd + " -f " + rcfile
++ RunWindow(cmd, Toplevel(), self)
+
+ def leave(self):
+- self.quit()
++ self.quit()
+
+ # Functions for turning a dictionary into an instantiated object tree.
+
+@@ -1956,51 +1956,51 @@ def intersect(list1, list2):
+ # Compute set intersection of lists
+ res = []
+ for x in list1:
+- if x in list2:
+- res.append(x)
++ if x in list2:
++ res.append(x)
+ return res
+
+ def setdiff(list1, list2):
+ # Compute set difference of lists
+ res = []
+ for x in list1:
+- if not x in list2:
+- res.append(x)
++ if not x in list2:
++ res.append(x)
+ return res
+
+ def copy_instance(toclass, fromdict):
+ # Initialize a class object of given type from a conformant dictionary.
+ for fld in fromdict.keys():
+- if not fld in dictmembers:
+- dictmembers.append(fld)
++ if not fld in dictmembers:
++ dictmembers.append(fld)
+ # The `optional' fields are the ones we can ignore for purposes of
+ # conformability checking; they'll still get copied if they are
+ # present in the dictionary.
+ optional = ('interface', 'monitor',
+- 'esmtpname', 'esmtppassword',
+- 'ssl', 'sslkey', 'sslcert', 'sslproto', 'sslcertck',
+- 'sslcertpath', 'sslcommonname', 'sslfingerprint', 'showdots')
++ 'esmtpname', 'esmtppassword',
++ 'ssl', 'sslkey', 'sslcert', 'sslproto', 'sslcertck',
++ 'sslcertpath', 'sslcommonname', 'sslfingerprint', 'showdots')
+ class_sig = setdiff(toclass.__dict__.keys(), optional)
+ class_sig.sort()
+ dict_keys = setdiff(fromdict.keys(), optional)
+ dict_keys.sort()
+ common = intersect(class_sig, dict_keys)
+ if 'typemap' in class_sig:
+- class_sig.remove('typemap')
++ class_sig.remove('typemap')
+ if tuple(class_sig) != tuple(dict_keys):
+- print "Fields don't match what fetchmailconf expected:"
++ print "Fields don't match what fetchmailconf expected:"
+ # print "Class signature: " + `class_sig`
+ # print "Dictionary keys: " + `dict_keys`
+- diff = setdiff(class_sig, common)
+- if diff:
+- print "Not matched in class `" + toclass.__class__.__name__ + "' signature: " + `diff`
+- diff = setdiff(dict_keys, common)
+- if diff:
+- print "Not matched in dictionary keys: " + `diff`
+- sys.exit(1)
++ diff = setdiff(class_sig, common)
++ if diff:
++ print "Not matched in class `" + toclass.__class__.__name__ + "' signature: " + `diff`
++ diff = setdiff(dict_keys, common)
++ if diff:
++ print "Not matched in dictionary keys: " + `diff`
++ sys.exit(1)
+ else:
+- for x in fromdict.keys():
+- setattr(toclass, x, fromdict[x])
++ for x in fromdict.keys():
++ setattr(toclass, x, fromdict[x])
+
+ #
+ # And this is the main sequence. How it works:
+@@ -2028,8 +2028,8 @@ def copy_instance(toclass, fromdict):
+ if __name__ == '__main__':
+
+ if not os.environ.has_key("DISPLAY"):
+- print "fetchmailconf must be run under X"
+- sys.exit(1)
++ print "fetchmailconf must be run under X"
++ sys.exit(1)
+
+ fetchmail_icon = """
+ R0lGODdhPAAoAPcAAP///wgICBAQEISEhIyMjJSUlKWlpa2trbW1tcbGxs7Ozufn5+/v7//39yEY
+@@ -2073,31 +2073,31 @@ gUSiYASJpMEHhilJTEnhAlGoQqYAZQ1AiqEMZ0jDGtqQImhwwA13yMMevoQAGvGhEAWHGMOAAAA7
+
+ # Process options
+ (options, arguments) = getopt.getopt(sys.argv[1:], "df:hV", ["help",
+- "version"])
++ "version"])
+ dump = rcfile = None;
+ for (switch, val) in options:
+- if (switch == '-d'):
+- dump = TRUE
+- elif (switch == '-f'):
+- rcfile = val
+- elif (switch == '-h' or switch == '--help'):
+- print """
++ if (switch == '-d'):
++ dump = TRUE
++ elif (switch == '-f'):
++ rcfile = val
++ elif (switch == '-h' or switch == '--help'):
++ 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 """
++ sys.exit(0)
++ elif (switch == '-V' or switch == '--version'):
++ 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."""
+- sys.exit(0)
++ sys.exit(0)
+
+ # Get client host's FQDN
+ hostname = socket.gethostbyaddr(socket.gethostname())[0]
+@@ -2112,26 +2112,26 @@ COPYING in the source or documentation directory for details."""
+ # want crackers to snoop password information out of the tempfile.
+ tmpfile = tempfile.mktemp()
+ if rcfile:
+- cmd = "umask 077 && fetchmail </dev/null -f " + rcfile + " --configdump --nosyslog >" + tmpfile
++ cmd = "umask 077 && fetchmail </dev/null -f " + rcfile + " --configdump --nosyslog >" + tmpfile
+ else:
+- cmd = "umask 077 && fetchmail </dev/null --configdump --nosyslog >" + tmpfile
++ cmd = "umask 077 && fetchmail </dev/null --configdump --nosyslog >" + tmpfile
+
+ try:
+- s = os.system(cmd)
+- if s != 0:
+- print "`" + cmd + "' run failure, status " + `s`
+- raise SystemExit
++ s = os.system(cmd)
++ if s != 0:
++ print "`" + cmd + "' run failure, status " + `s`
++ raise SystemExit
+ except:
+- print "Unknown error while running fetchmail --configdump"
+- os.remove(tmpfile)
+- sys.exit(1)
++ print "Unknown error while running fetchmail --configdump"
++ os.remove(tmpfile)
++ sys.exit(1)
+
+ try:
+- execfile(tmpfile)
++ execfile(tmpfile)
+ except:
+- print "Can't read configuration output of fetchmail --configdump."
+- os.remove(tmpfile)
+- sys.exit(1)
++ print "Can't read configuration output of fetchmail --configdump."
++ os.remove(tmpfile)
++ sys.exit(1)
+
+ os.remove(tmpfile)
+
+@@ -2145,23 +2145,23 @@ COPYING in the source or documentation directory for details."""
+ copy_instance(Fetchmailrc, fetchmailrc)
+ Fetchmailrc.servers = [];
+ for server in fetchmailrc['servers']:
+- Newsite = Server()
+- copy_instance(Newsite, server)
+- Fetchmailrc.servers.append(Newsite)
+- Newsite.users = [];
+- for user in server['users']:
+- Newuser = User()
+- copy_instance(Newuser, user)
+- Newsite.users.append(Newuser)
++ Newsite = Server()
++ copy_instance(Newsite, server)
++ Fetchmailrc.servers.append(Newsite)
++ Newsite.users = [];
++ for user in server['users']:
++ Newuser = User()
++ copy_instance(Newuser, user)
++ Newsite.users.append(Newuser)
+
+ # 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"+`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.
+ if not rcfile and not dump:
+- rcfile = os.environ["HOME"] + "/.fetchmailrc"
++ rcfile = os.environ["HOME"] + "/.fetchmailrc"
+
+ # OK, now run the configuration edit
+ root = MainWindow(rcfile)
+--
+2.8.3
+
diff --git a/package/fetchmail/0004-fetchmailconf.py-make-fetchmailconf.py-python-2-3-co.patch b/package/fetchmail/0004-fetchmailconf.py-make-fetchmailconf.py-python-2-3-co.patch
new file mode 100644
index 0000000..0ce1aed
--- /dev/null
+++ b/package/fetchmail/0004-fetchmailconf.py-make-fetchmailconf.py-python-2-3-co.patch
@@ -0,0 +1,279 @@
+From 2d76370ab99fded60ca84845dbb951290d2b1073 Mon Sep 17 00:00:00 2001
+From: Samuel Martin <s.martin49 at gmail.com>
+Date: Tue, 7 Jun 2016 23:22:46 +0200
+Subject: [PATCH] fetchmailconf.py: make fetchmailconf.py python{2,3}-compliant
+
+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.martin49 at gmail.com>
+---
+ 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 <matthias.andree at gmx.de>
+ # 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
+
--
2.8.3
More information about the buildroot
mailing list