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@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@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@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@bar "
+-		   "might result in your mail being sent to foo@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@bar "
++                   "might result in your mail being sent to foo@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@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@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@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
+
