]> Pileus Git - ~andy/fetchmail/blobdiff - fetchmailconf
Bug fixes and internationalization improvements.
[~andy/fetchmail] / fetchmailconf
index c5b6113112725ddeff53da52a81a7159d8de1431..15ccc2fbf02234e060d0a15ecbd43983ae4d6a71 100755 (executable)
@@ -4,7 +4,7 @@
 # by Eric S. Raymond, <esr@snark.thyrsus.com>.
 # Requires Python with Tkinter, and the following OS-dependent services:
 #      posix, posixpath, socket
 # by Eric S. Raymond, <esr@snark.thyrsus.com>.
 # Requires Python with Tkinter, and the following OS-dependent services:
 #      posix, posixpath, socket
-version = "1.15"
+version = "1.28"
 
 from Tkinter import *
 from Dialog import *
 
 from Tkinter import *
 from Dialog import *
@@ -74,7 +74,7 @@ class Server:
        self.protocol = 'auto'          # Default to auto protocol
        self.port = 0                   # Port number to use
        self.uidl = FALSE               # Don't use RFC1725 UIDLs by default
        self.protocol = 'auto'          # Default to auto protocol
        self.port = 0                   # Port number to use
        self.uidl = FALSE               # Don't use RFC1725 UIDLs by default
-       self.auth = 'password'          # Default to password authentication
+       self.preauth = 'password'       # 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.timeout = 300              # 5-minute timeout
        self.envelope = 'Received'      # Envelope-address header
        self.envskip = 0                # Number of envelope headers to skip
@@ -96,7 +96,7 @@ class Server:
            ('protocol',  'String'),
            ('port',      'Int'),
            ('uidl',      'Boolean'),
            ('protocol',  'String'),
            ('port',      'Int'),
            ('uidl',      'Boolean'),
-           ('auth',      'String'),
+           ('preauth',      'String'),
            ('timeout',   'Int'),
            ('envelope',  'String'),
            ('envskip',   'Int'),
            ('timeout',   'Int'),
            ('envelope',  'String'),
            ('envskip',   'Int'),
@@ -111,69 +111,69 @@ class Server:
            ('netsec',   'String'))
 
     def dump(self, folded):
            ('netsec',   'String'))
 
     def dump(self, folded):
-       str = ""
-       if self.active:   str = str + "poll"
-       else:             str = str + "skip"
-       str = str + (" " + self.pollname)
+       res = ""
+       if self.active:   res = res + "poll"
+       else:             res = res + "skip"
+       res = res + (" " + self.pollname)
        if self.via:
        if self.via:
-           str = str + (" via \"%s\"\n" % (self.via,));
+           res = res + (" via " + str(self.via) + "\n");
        if self.protocol != ServerDefaults.protocol:
        if self.protocol != ServerDefaults.protocol:
-           str = str + " with proto " + self.protocol 
+           res = res + " with proto " + self.protocol 
        if self.port != defaultports[self.protocol] and self.port != 0:
        if self.port != defaultports[self.protocol] and self.port != 0:
-           str = str + " port " + `self.port`
+           res = res + " port " + `self.port`
        if self.timeout != ServerDefaults.timeout:
        if self.timeout != ServerDefaults.timeout:
-           str = str + " timeout " + `self.timeout`
+           res = res + " timeout " + `self.timeout`
        if self.interval != ServerDefaults.interval: 
        if self.interval != ServerDefaults.interval: 
-           str = str + " interval " + `self.interval`
+           res = res + " interval " + `self.interval`
        if self.envelope != ServerDefaults.envelope or self.envskip != ServerDefaults.envskip:
            if self.envskip:
        if self.envelope != ServerDefaults.envelope or self.envskip != ServerDefaults.envskip:
            if self.envskip:
-               str = str + " envelope " + self.envskip + " " + self.envelope
+               res = res + " envelope " + `self.envskip` + " " + self.envelope
            else:
            else:
-               str = str + " envelope " + self.envelope
+               res = res + " envelope " + self.envelope
        if self.qvirtual:
        if self.qvirtual:
-           str = str + (" qvirtual \"%s\"\n" % (self.qvirtual,));
-       if self.auth != ServerDefaults.auth:
-           str = str + " auth " + self.auth
+           res = res + (" qvirtual " + str(self.qvirtual) + "\n");
+       if self.preauth != ServerDefaults.preauth:
+           res = res + " preauth " + self.preauth
        if self.dns != ServerDefaults.dns or self.uidl != ServerDefaults.uidl:
        if self.dns != ServerDefaults.dns or self.uidl != ServerDefaults.uidl:
-           str = str + " and options"
+           res = res + " and options"
        if self.dns != ServerDefaults.dns:
        if self.dns != ServerDefaults.dns:
-           str = str + flag2str(self.dns, 'dns')
+           res = res + flag2str(self.dns, 'dns')
        if self.uidl != ServerDefaults.uidl:
        if self.uidl != ServerDefaults.uidl:
-           str = str + flag2str(self.uidl, 'uidl')
-       if folded:        str = str + "\n    "
-       else:             str = str + " "
+           res = res + flag2str(self.uidl, 'uidl')
+       if folded:        res = res + "\n    "
+       else:             res = res + " "
 
        if self.aka:
 
        if self.aka:
-            str = str + "aka"
+            res = res + "aka"
             for x in self.aka:
             for x in self.aka:
-               str = str + " " + x
-       if self.aka and self.localdomains: str = str + " "
+               res = res + " " + x
+       if self.aka and self.localdomains: res = res + " "
        if self.localdomains:
        if self.localdomains:
-            str = str + ("localdomains")
+            res = res + ("localdomains")
             for x in self.localdomains:
             for x in self.localdomains:
-               str = str + " " + x
+               res = res + " " + x
         if (self.aka or self.localdomains):
            if folded:
         if (self.aka or self.localdomains):
            if folded:
-               str = str + "\n    "
+               res = res + "\n    "
            else:
            else:
-               str = str + " "
+               res = res + " "
 
        if self.interface:
 
        if self.interface:
-            str = str + "interface \"" + self.interface + "\""
+            res = res + "interface " + str(self.interface)
        if self.monitor:
        if self.monitor:
-            str = str + "monitor \"" + self.monitor + "\""
+            res = res + "monitor " + str(self.monitor)
        if self.netsec:
        if self.netsec:
-            str = str + "netsec \"" + self.netsec + "\""
+            res = res + "netsec " + str(self.netsec)
        if self.interface or self.monitor or self.netsec:
            if folded:
        if self.interface or self.monitor or self.netsec:
            if folded:
-               str = str + "\n"
+               res = res + "\n"
 
 
-       if str[-1] == " ": str = str[0:-1]
+       if res[-1] == " ": res = res[0:-1]
 
        for user in self.users:
 
        for user in self.users:
-           str = str + repr(user)
-       str = str + "\n"
-       return str;
+           res = res + repr(user)
+       res = res + "\n"
+       return res;
 
     def __delitem__(self, name):
         for ui in range(len(self.users)):
 
     def __delitem__(self, name):
         for ui in range(len(self.users)):
@@ -214,13 +214,18 @@ class User:
        self.forcecr = FALSE            # Force LF -> CR/LF
        self.stripcr = FALSE            # Strip CR
        self.pass8bits = FALSE          # Force BODY=7BIT
        self.forcecr = FALSE            # Force LF -> CR/LF
        self.stripcr = FALSE            # Strip CR
        self.pass8bits = FALSE          # Force BODY=7BIT
-       self.mimedecode = TRUE          # Undo MIME armoring
+       self.mimedecode = FALSE         # Undo MIME armoring
        self.dropstatus = FALSE         # Drop incoming Status lines
        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 = 0              # Size warning interval
        self.fetchlimit = 0             # Max messages fetched per batch
        self.batchlimit = 0             # Max message forwarded per batch
        self.expunge = 0                # Interval between expunges (IMAP)
        self.limit = 0                  # Message size limit
         self.warnings = 0              # Size warning interval
        self.fetchlimit = 0             # Max messages fetched per batch
        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.properties = None         # Extension properties
        User.typemap = (
            ('remote',      'String'),
         self.properties = None         # Extension properties
        User.typemap = (
            ('remote',      'String'),
@@ -243,23 +248,28 @@ class User:
            ('pass8bits',   'Boolean'),
            ('mimedecode',  'Boolean'),
            ('dropstatus',  'Boolean'),
            ('pass8bits',   'Boolean'),
            ('mimedecode',  'Boolean'),
            ('dropstatus',  'Boolean'),
+            ('dropdelivered', 'Boolean'),
+           ('idle',        'Boolean'),
            ('limit',       'Int'),
            ('warnings',    'Int'),
            ('fetchlimit',  'Int'),
            ('batchlimit',  'Int'),
            ('expunge',     'Int'),
            ('limit',       'Int'),
            ('warnings',    'Int'),
            ('fetchlimit',  'Int'),
            ('batchlimit',  'Int'),
            ('expunge',     'Int'),
-            ('properties',   'String'))
+           ('ssl',         'Boolean'),
+           ('sslkey',      'String'),
+           ('sslcert',     'String'),
+            ('properties',  'String'))
 
     def __repr__(self):
 
     def __repr__(self):
-       str = "    "
-       str = str + "user \"" + self.remote + "\" there ";
+       res = "    "
+       res = res + "user " + `self.remote` + " there ";
        if self.password:
        if self.password:
-            str = str + "with password \"" + self.password + '" '
+            res = res + "with password " + `self.password` + " "
        if self.localnames:
        if self.localnames:
-            str = str + "is"
+            res = res + "is"
             for x in self.localnames:
             for x in self.localnames:
-               str = str + " " + x
-            str = str + " here"
+               res = res + " " + x
+            res = res + " here"
        if (self.keep != UserDefaults.keep
                or self.flush != UserDefaults.flush
                or self.fetchall != UserDefaults.fetchall
        if (self.keep != UserDefaults.keep
                or self.flush != UserDefaults.flush
                or self.fetchall != UserDefaults.fetchall
@@ -268,60 +278,72 @@ class User:
                or self.stripcr != UserDefaults.stripcr 
                or self.pass8bits != UserDefaults.pass8bits
                or self.mimedecode != UserDefaults.mimedecode
                or self.stripcr != UserDefaults.stripcr 
                or self.pass8bits != UserDefaults.pass8bits
                or self.mimedecode != UserDefaults.mimedecode
-               or self.dropstatus != UserDefaults.dropstatus):
-           str = str + " options"
+               or self.dropstatus != UserDefaults.dropstatus
+               or self.dropdelivered != UserDefaults.dropdelivered
+               or self.idle != UserDefaults.idle):
+           res = res + " options"
        if self.keep != UserDefaults.keep:
        if self.keep != UserDefaults.keep:
-           str = str + flag2str(self.keep, 'keep')
+           res = res + flag2str(self.keep, 'keep')
        if self.flush != UserDefaults.flush:
        if self.flush != UserDefaults.flush:
-           str = str + flag2str(self.flush, 'flush')
+           res = res + flag2str(self.flush, 'flush')
        if self.fetchall != UserDefaults.fetchall:
        if self.fetchall != UserDefaults.fetchall:
-           str = str + flag2str(self.fetchall, 'fetchall')
+           res = res + flag2str(self.fetchall, 'fetchall')
        if self.rewrite != UserDefaults.rewrite:
        if self.rewrite != UserDefaults.rewrite:
-           str = str + flag2str(self.rewrite, 'rewrite')
+           res = res + flag2str(self.rewrite, 'rewrite')
        if self.forcecr != UserDefaults.forcecr:
        if self.forcecr != UserDefaults.forcecr:
-           str = str + flag2str(self.forcecr, 'forcecr')
+           res = res + flag2str(self.forcecr, 'forcecr')
        if self.stripcr != UserDefaults.stripcr:
        if self.stripcr != UserDefaults.stripcr:
-           str = str + flag2str(self.stripcr, 'stripcr')
+           res = res + flag2str(self.stripcr, 'stripcr')
        if self.pass8bits != UserDefaults.pass8bits:
        if self.pass8bits != UserDefaults.pass8bits:
-           str = str + flag2str(self.pass8bits, 'pass8bits')
+           res = res + flag2str(self.pass8bits, 'pass8bits')
        if self.mimedecode != UserDefaults.mimedecode:
        if self.mimedecode != UserDefaults.mimedecode:
-           str = str + flag2str(self.mimedecode, 'mimedecode')
+           res = res + flag2str(self.mimedecode, 'mimedecode')
        if self.dropstatus != UserDefaults.dropstatus:
        if self.dropstatus != UserDefaults.dropstatus:
-           str = str + flag2str(self.dropstatus, '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:
        if self.limit != UserDefaults.limit:
-           str = str + " limit " + `self.limit`
+           res = res + " limit " + `self.limit`
        if self.warnings != UserDefaults.warnings:
        if self.warnings != UserDefaults.warnings:
-           str = str + " warnings " + `self.warnings`
+           res = res + " warnings " + `self.warnings`
        if self.fetchlimit != UserDefaults.fetchlimit:
        if self.fetchlimit != UserDefaults.fetchlimit:
-           str = str + " fetchlimit " + `self.fetchlimit`
+           res = res + " fetchlimit " + `self.fetchlimit`
        if self.batchlimit != UserDefaults.batchlimit:
        if self.batchlimit != UserDefaults.batchlimit:
-           str = str + " batchlimit " + `self.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.expunge != UserDefaults.expunge:
        if self.expunge != UserDefaults.expunge:
-           str = str + " expunge " + `self.expunge`
-        str = str + "\n"
+           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 != []:
         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 != []:
-            str = str + "    smtphost "
+            res = res + "    smtphost "
             for x in trimmed:
             for x in trimmed:
-                str = str + " " + x
-                str = str + "\n"
+                res = res + " " + x
+                res = res + "\n"
        if self.mailboxes:
        if self.mailboxes:
-            str = str + "    folder"
+            res = res + "    folder"
             for x in self.mailboxes:
             for x in self.mailboxes:
-               str = str + " " + x
-            str = str + "\n"
+               res = res + " " + x
+            res = res + "\n"
         for fld in ('smtpaddress', 'preconnect', 'postconnect', 'mda', 'bsmtp', 'properties'):
             if getattr(self, fld):
         for fld in ('smtpaddress', 'preconnect', 'postconnect', 'mda', 'bsmtp', 'properties'):
             if getattr(self, fld):
-                str = str + " %s %s\n" % (fld, `getattr(self, fld)`)
+                res = res + " %s %s\n" % (fld, `getattr(self, fld)`)
        if self.lmtp != UserDefaults.lmtp:
        if self.lmtp != UserDefaults.lmtp:
-           str = str + flag2str(self.lmtp, 'lmtp')
+           res = res + flag2str(self.lmtp, 'lmtp')
         if self.antispam != UserDefaults.antispam:
         if self.antispam != UserDefaults.antispam:
-            str = str + "    antispam " + self.antispam + "\n"
-       return str;
+            res = res + "    antispam " + self.antispam + "\n"
+       return res;
 
     def __str__(self):
        return "[User: " + repr(self) + "]"
 
     def __str__(self):
        return "[User: " + repr(self) + "]"
@@ -340,7 +362,7 @@ defaultports = {"auto":0,
                "IMAP-K4":143,
                "ETRN":25}
 
                "IMAP-K4":143,
                "ETRN":25}
 
-authlist = ("password", "kerberos")
+preauthlist = ("password", "kerberos", "ssh")
 
 listboxhelp = {
     'title' : 'List Selection Help',
 
 listboxhelp = {
     'title' : 'List Selection Help',
@@ -395,10 +417,18 @@ def helpwin(helpdict):
     helpwin.title(helpdict['title']) 
     helpwin.iconname(helpdict['title'])
     Label(helpwin, text=helpdict['banner']).pack()
     helpwin.title(helpdict['title']) 
     helpwin.iconname(helpdict['title'])
     Label(helpwin, text=helpdict['banner']).pack()
-    textwin = Message(helpwin, text=helpdict['text'], width=600)
-    textwin.pack()
+    textframe = Frame(helpwin)
+    scroll = Scrollbar(textframe)
+    helpwin.textwidget = Text(textframe, setgrid=TRUE)
+    textframe.pack(side=TOP, expand=YES, fill=BOTH)
+    helpwin.textwidget.config(yscrollcommand=scroll.set)
+    helpwin.textwidget.pack(side=LEFT, expand=YES, fill=BOTH)
+    scroll.config(command=helpwin.textwidget.yview)
+    scroll.pack(side=RIGHT, fill=BOTH)
+    helpwin.textwidget.insert(END, helpdict['text']);
     Button(helpwin, text='Done', 
           command=lambda x=helpwin: Widget.destroy(x), bd=2).pack()
     Button(helpwin, text='Done', 
           command=lambda x=helpwin: Widget.destroy(x), bd=2).pack()
+    textframe.pack(side=TOP)
 
 def make_icon_window(base, image):
     try:
 
 def make_icon_window(base, image):
     try:
@@ -458,15 +488,18 @@ class ListEdit(Frame):
        helpwin(self.helptxt)
 
     def handleList(self, event):
        helpwin(self.helptxt)
 
     def handleList(self, event):
-       self.editItem();
+        self.editItem();
 
     def handleNew(self, event):
        item = self.newval.get()
 
     def handleNew(self, event):
        item = self.newval.get()
-       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)
-       self.newval.set('')
+        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()
 
     def editItem(self):
        select = self.listwidget.curselection()
@@ -476,7 +509,8 @@ class ListEdit(Frame):
            index = select[0]
            if index and self.editor:
                label = self.listwidget.get(index);
            index = select[0]
            if index and self.editor:
                label = self.listwidget.get(index);
-               apply(self.editor, (label,))
+                if self.editor:
+                    apply(self.editor, (label,))
 
     def deleteItem(self):
        select = self.listwidget.curselection()
 
     def deleteItem(self):
        select = self.listwidget.curselection()
@@ -638,6 +672,8 @@ class ConfigurationEdit(Frame, MyWidget):
 
     def server_delete(self, sitename):
         try:
 
     def server_delete(self, sitename):
         try:
+            for user in self.subwidgets.keys():
+                user.destruct()
             del self.configuration[sitename]
         except:
            pass
             del self.configuration[sitename]
         except:
            pass
@@ -647,8 +683,9 @@ class ConfigurationEdit(Frame, MyWidget):
        Frame.__init__(self, self.container)
        self.master.title('fetchmail ' + self.mode + ' configurator');
        self.master.iconname('fetchmail ' + self.mode + ' configurator');
        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
         self.keepalive = []    # Use this to anchor the PhotoImage object
-        make_icon_window(self, fetchmail_gif)
+        make_icon_window(self, fetchmail_icon)
        Pack.config(self)
         self.post(Configuration, 'configuration')
 
        Pack.config(self)
         self.post(Configuration, 'configuration')
 
@@ -854,6 +891,10 @@ The `interface' and `monitor' options are available
 only for Linux and freeBSD systems.  See the fetchmail
 manual page for details on these.
 
 only for Linux and freeBSD systems.  See the fetchmail
 manual page for details on these.
 
+The ssl option enables SSL communication with a mailserver
+supporting Secure Sockets Layer. The sslkey and sslcert options
+declare key and certificate files for use with SSL.
+
 The `netsec' option will be configurable only if fetchmail
 was compiled with IPV6 support.  If you need to use it,
 you probably know what to do.
 The `netsec' option will be configurable only if fetchmail
 was compiled with IPV6 support.  If you need to use it,
 you probably know what to do.
@@ -904,7 +945,7 @@ class ServerEdit(Frame, MyWidget):
        self.post(Server, 'server')
        self.makeWidgets(self.server.pollname, mode)
         self.keepalive = []    # Use this to anchor the PhotoImage object
        self.post(Server, 'server')
        self.makeWidgets(self.server.pollname, mode)
         self.keepalive = []    # Use this to anchor the PhotoImage object
-        make_icon_window(self, fetchmail_gif)
+        make_icon_window(self, fetchmail_icon)
 #      self.grab_set()
 #      self.focus_set()
 #      self.wait_window()
 #      self.grab_set()
 #      self.focus_set()
 #      self.wait_window()
@@ -937,7 +978,7 @@ class ServerEdit(Frame, MyWidget):
 
     def user_delete(self, username):
         if self.subwidgets.has_key(username):
 
     def user_delete(self, username):
         if self.subwidgets.has_key(username):
-            del self.subwidgets[username]
+            self.subwidgets[username].destruct()
         del self.server[username]
 
     def makeWidgets(self, host, mode):
         del self.server[username]
 
     def makeWidgets(self, host, mode):
@@ -1030,8 +1071,8 @@ class ServerEdit(Frame, MyWidget):
                 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
                 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, 1, None).pack(side=TOP)
+                #      ButtonBar(secwin, 'Preauthorization mode:',
+                #                self.preauth, preauthlist, 1, 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 'interface' in dictmembers:
                     LabeledEntry(secwin, 'IP range to check before poll:',
                         self.interface, leftwidth).pack(side=TOP, fill=X)
@@ -1091,7 +1132,10 @@ you'll have to build it from sources yourself with the configure
 switch --enable-POP2.
 
 """
 switch --enable-POP2.
 
 """
-            if string.find(greetline, "1.003") > 0 or string.find(greetline, "1.004") > 0:
+
+### POP3 servers start here
+
+           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
                 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
@@ -1101,29 +1145,6 @@ It is strongly recommended that you find a better POP3 server.  The fetchmail
 FAQ includes pointers to good ones.
 
 """
 FAQ includes pointers to good ones.
 
 """
-            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
-(otherwise you won't necessarily see all your mail, not even new mail).
-They also botch the TOP command the fetchmail normally uses for retrieval
-(it only retrieves about 10 lines rather than the number specified).
-Turning on fetchall will disable the use of TOP.
-
-Therefore, it is strongly recommended that you turn on `fetchall' on all
-user entries associated with this server.  
-
-"""
-            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.  
-
-"""
-
 # Steve VanDevender <stevev@efn.org> writes:
 # The only system I have seen this happen with is cucipop-1.31
 # under SunOS 4.1.4.  cucipop-1.31 runs fine on at least Solaris
 # Steve VanDevender <stevev@efn.org> writes:
 # The only system I have seen this happen with is cucipop-1.31
 # under SunOS 4.1.4.  cucipop-1.31 runs fine on at least Solaris
@@ -1142,19 +1163,163 @@ turn on `fetchall' on all user entries associated with this server.
 # 
 # +OK Cubic Circle's v1.31 1998/05/13 POP3 ready <6229000062f95036@wakko>
 #
 # 
 # +OK Cubic Circle's v1.31 1998/05/13 POP3 ready <6229000062f95036@wakko>
 #
-            if string.find(greetline, "Cubic Circle") > 0:
+           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
 SunOS and Solaris machines run cucipop OK.
                 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
 SunOS and Solaris machines run cucipop OK.
+
+"""
+           if string.find(greetline, "David POP3 Server") > 0:
+                warnings = warnings + """
+This POP3 serrver is badly broken.  You should get rid of it -- and the
+brain-dead NT operating system it rode in on.
+
 """
 """
-            if string.find(greetline, "QPOP") > 0:
+# 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 + """
+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, "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
+around this bug, turn on `fetchall' on all user entries associated with
+this server.  
+
+"""
+           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
+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 + """
+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 + """
 This appears to be a version of Eudora qpopper.  That's good.  Fetchmail
                 warnings = warnings + """
 This appears to be a version of Eudora qpopper.  That's good.  Fetchmail
-knows all about qpopper.
+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
+error on very large messages.  This is probably not a fetchmail bug, as
+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 + """
+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 + """
+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
+this bug, turn on `fetchall' on all user entries associated with this
+server.
+
+"""
+            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
+this bug, turn on `fetchall' on all user entries associated with this
+server.
+
+"""
+            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
+(otherwise you won't necessarily see all your mail, not even new mail).
+They also botch the TOP command the fetchmail normally uses for retrieval
+(it only retrieves about 10 lines rather than the number specified).
+Turning on fetchall will disable the use of TOP.
+
+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 + """
+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.
+
+"""
+
+### IMAP servers start here
+
+            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
+BODY[TEXT] response.<p>
+
+Fetchmail works around this problem, but we strongly recommend voting
+with your dollars for a server that isn't brain-dead.  If you stick
+with code as shoddy as GroupWise seems to be, you will probably pay
+for it with other problems.<p>
+
+"""
+            if string.find(greetline, "Netscape IMAP4rev1 Service 3.6") > 0:
+                warnings = warnings + """
+This server violates the RFC2060 requirement that a BODY[TEXT] fetch should
+set the messages's Seen flag.  As a result, if you use the keep option the
+same messages will be downloaded over and over.
+
+"""
+            if string.find(greetline, "InterChange") > 0:
+                warnings = warnings + """
+The InterChange IMAP server screws up on mail with attachments.  It
+doesn't fetch them if you give it a BODY[TEXT] request, though it
+does if you request RFC822.TEXT.  According to the IMAP RFCs and their
+maintainer these should be equivalent -- and we can't drop the
+BODY[TEXT] form because M$ Exchange (quite legally under RFC2062)
+rejects it.
+
+"""
+            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 + """
+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
+will see attachments as part of the message text.  If your Domino server's
+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 + """
@@ -1162,14 +1327,6 @@ 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.
 
 password in clear.  You should talk to the mailserver administrator about
 this.
 
-"""
-            if string.find(greetline, "csi.com") > 0:
-                warnings = warnings + """
-It appears you're talking to CompuServe.  You can use their special RPA
-service for authentication, but only if your fetchmail -V output's first
-line contains the string "RPA".  This is not included in stock fetchmail
-binaries; to compile it in, rebuild from sources with the configure
-option --enable-RPA.
 """
             if string.find(greetline, "IMAP2bis") > 0:
                 warnings = warnings + """
 """
             if string.find(greetline, "IMAP2bis") > 0:
                 warnings = warnings + """
@@ -1181,21 +1338,21 @@ To work around this, it is recommended that you set the `fetchall'
 option on all user entries associated with this server, so any stuck
 mail will be retrieved next time around.
 
 option on all user entries associated with this server, so any stuck
 mail will be retrieved next time around.
 
-"""
-            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.
+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 + """
 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 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 + """
 Fetchmail doesn't know anything special about this server type.
 """
             if warnings == '':
                 warnings = warnings + """
 Fetchmail doesn't know anything special about this server type.
+
 """
 
             # Display success window with warnings
 """
 
             # Display success window with warnings
@@ -1267,14 +1424,16 @@ class UserEdit(Frame, MyWidget):
        self.post(User, 'user')
        self.makeWidgets(mode, self.parent.server.pollname)
         self.keepalive = []    # Use this to anchor the PhotoImage object
        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_gif)
+        make_icon_window(self, fetchmail_icon)
 #      self.grab_set()
 #      self.focus_set()
 #      self.wait_window()
        return self
 
     def destruct(self):
 #      self.grab_set()
 #      self.focus_set()
 #      self.wait_window()
        return self
 
     def destruct(self):
-        del self.parent.subwidgets[self.user.remote]
+        # 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]
         Widget.destroy(self.master)
 
     def nosave(self):
         Widget.destroy(self.master)
 
     def nosave(self):
@@ -1301,6 +1460,16 @@ class UserEdit(Frame, MyWidget):
                      self.password, '12').pack(side=TOP, fill=X)
         secwin.pack(fill=X, anchor=N)
 
                      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)
+            sslwin.pack(fill=X, anchor=N)
+
         names = Frame(leftwin, relief=RAISED, bd=5)
         Label(names, text="Local names").pack(side=TOP)
         ListEdit("New name: ",
         names = Frame(leftwin, relief=RAISED, bd=5)
         Label(names, text="Local names").pack(side=TOP)
         ListEdit("New name: ",
@@ -1358,6 +1527,8 @@ class UserEdit(Frame, MyWidget):
                    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)
                    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':
        optwin.pack(fill=X)
 
         if mode != 'novice':
@@ -1371,9 +1542,11 @@ class UserEdit(Frame, MyWidget):
                      self.fetchlimit, '30').pack(side=TOP, fill=X)
             LabeledEntry(limwin, 'Max messages to forward per poll:',
                      self.batchlimit, '30').pack(side=TOP, fill=X)
                      self.fetchlimit, '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 in ('IMAP', 'IMAP-K4', 'IMAP-GSS'):
-                LabeledEntry(limwin, 'Interval between expunges (IMAP):',
+            if self.parent.server.protocol != 'ETRN':
+                LabeledEntry(limwin, 'Interval between expunges:',
                              self.expunge, '30').pack(side=TOP, fill=X)
                              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 in ('IMAP', 'IMAP-K4', 'IMAP-GSS'):
             limwin.pack(fill=X)
 
             if self.parent.server.protocol in ('IMAP', 'IMAP-K4', 'IMAP-GSS'):
@@ -1404,7 +1577,7 @@ class Configurator(Frame):
        self.master.iconname('fetchmail configurator');
        Pack.config(self)
         self.keepalive = []    # Use this to anchor the PhotoImage object
        self.master.iconname('fetchmail configurator');
        Pack.config(self)
         self.keepalive = []    # Use this to anchor the PhotoImage object
-        make_icon_window(self, fetchmail_gif)
+        make_icon_window(self, fetchmail_icon)
 
        Message(self, text="""
 Use `Novice Configuration' for basic fetchmail setup;
 
        Message(self, text="""
 Use `Novice Configuration' for basic fetchmail setup;
@@ -1426,6 +1599,7 @@ 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()
 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)
 
     def novice(self):
        self.master.destroy()
 
     def novice(self):
        self.master.destroy()
@@ -1439,7 +1613,7 @@ return to the main panel.
         self.master.destroy()
         self.onexit()
 
         self.master.destroy()
         self.onexit()
 
-# Run a command an a scrolling text widget, displaying its output
+# Run a command in a scrolling text widget, displaying its output
 
 class RunWindow(Frame):
     def __init__(self, command, master, parent):
 
 class RunWindow(Frame):
     def __init__(self, command, master, parent):
@@ -1452,7 +1626,7 @@ class RunWindow(Frame):
                text="Running "+command, 
                bd=2).pack(side=TOP, pady=10)
         self.keepalive = []    # Use this to anchor the PhotoImage object
                text="Running "+command, 
                bd=2).pack(side=TOP, pady=10)
         self.keepalive = []    # Use this to anchor the PhotoImage object
-        make_icon_window(self, fetchmail_gif)
+        make_icon_window(self, fetchmail_icon)
 
         # This is a scrolling text window
        textframe = Frame(self)
 
         # This is a scrolling text window
        textframe = Frame(self)
@@ -1494,9 +1668,14 @@ class MainWindow(Frame):
                text='Fetchmailconf ' + version, 
                bd=2).pack(side=TOP, pady=10)
         self.keepalive = []    # Use this to anchor the PhotoImage object
                text='Fetchmailconf ' + version, 
                bd=2).pack(side=TOP, pady=10)
         self.keepalive = []    # Use this to anchor the PhotoImage object
-        make_icon_window(self, fetchmail_gif)
+        make_icon_window(self, fetchmail_icon)
         self.debug = 0
 
         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,
        Message(self, text="""
 Use `Configure fetchmail' to tell fetchmail about the remote
 servers it should poll (the host name, your username there,
@@ -1528,7 +1707,6 @@ Or you can just select `Quit' to exit the launcher now.
         Configurator(self.outfile, Toplevel(),
                      lambda self=self: self.configbutton.configure(state=NORMAL),
                      self)
         Configurator(self.outfile, Toplevel(),
                      lambda self=self: self.configbutton.configure(state=NORMAL),
                      self)
-
     def test(self):
        RunWindow("fetchmail -d0 -v --nosyslog", Toplevel(), self)
 
     def test(self):
        RunWindow("fetchmail -d0 -v --nosyslog", Toplevel(), self)
 
@@ -1564,7 +1742,7 @@ def copy_instance(toclass, fromdict):
 # 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.
 # 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', 'netsec')
+    optional = ('interface', 'monitor', 'netsec', 'ssl', 'sslkey', 'sslcert')
     class_sig = setdiff(toclass.__dict__.keys(), optional)
     class_sig.sort()
     dict_keys = setdiff(fromdict.keys(), optional)
     class_sig = setdiff(toclass.__dict__.keys(), optional)
     class_sig.sort()
     dict_keys = setdiff(fromdict.keys(), optional)
@@ -1612,7 +1790,11 @@ def copy_instance(toclass, fromdict):
 
 if __name__ == '__main__': 
 
 
 if __name__ == '__main__': 
 
-    fetchmail_gif = """
+    if not os.environ.has_key("DISPLAY"):
+        print "fetchmailconf must be run under X"
+        sys.exit(1)
+
+    fetchmail_icon = """
 R0lGODdhPAAoAPcAAP///wgICBAQEISEhIyMjJSUlKWlpa2trbW1tcbGxs7Ozufn5+/v7//39yEY
 GNa9tUoxKZyEe1o5KTEQAN7OxpyMhIRjUvfn3pxSKYQ5EO/Wxv/WvWtSQrVzSmtCKWspAMatnP/e
 xu+1jIxSKaV7Wt6ca5xSGK2EY8aUa72MY86UY617UsaMWrV7SpRjOaVrOZRaKYxSIXNCGGs5EIRC
 R0lGODdhPAAoAPcAAP///wgICBAQEISEhIyMjJSUlKWlpa2trbW1tcbGxs7Ozufn5+/v7//39yEY
 GNa9tUoxKZyEe1o5KTEQAN7OxpyMhIRjUvfn3pxSKYQ5EO/Wxv/WvWtSQrVzSmtCKWspAMatnP/e
 xu+1jIxSKaV7Wt6ca5xSGK2EY8aUa72MY86UY617UsaMWrV7SpRjOaVrOZRaKYxSIXNCGGs5EIRC
@@ -1646,12 +1828,10 @@ OtO0k84+7KjzBjzplMJOOOOoo8846/ATxqJWinkkGUyEkMAaIezABQM3bMAEK1xEsUMDGjARRxhY
 xEGGHfPjEcccca6BRxhyuEMY7FCHMNDhf9140r2qRiVvdENQ3liUArzREW/0qRsRVIAGFfBADnLw
 gUSiYASJpMEHhilJTEnhAlGoQqYAZQ1AiqEMZ0jDGtqQImhwwA13yMMevoQAGvGhEAWHGMOAAAA7
 """
 xEGGHfPjEcccca6BRxhyuEMY7FCHMNDhf9140r2qRiVvdENQ3liUArzREW/0qRsRVIAGFfBADnLw
 gUSiYASJpMEHhilJTEnhAlGoQqYAZQ1AiqEMZ0jDGtqQImhwwA13yMMevoQAGvGhEAWHGMOAAAA7
 """
-# Note on making icons: the above was generated by the following procedure:
+# The base64 data in the string above was generated by the following procedure:
 #
 # import base64
 #
 # import base64
-# data = open("fetchmail.gif", "rb").read()
-# print "fetchmail_gif =\\"
-# print repr(base64.encodestring(data))
+# print base64.encodestring(open("fetchmail.gif", "rb").read())
 #
 
     # Process options
 #
 
     # Process options
@@ -1671,12 +1851,14 @@ gUSiYASJpMEHhilJTEnhAlGoQqYAZQ1AiqEMZ0jDGtqQImhwwA13yMMevoQAGvGhEAWHGMOAAAA7
     ServerDefaults = Server()
     UserDefaults = User()
 
     ServerDefaults = Server()
     UserDefaults = User()
 
-    # Read the existing configuration
+    # Read the existing configuration.  We set the umask to 077 to make sure
+    # that group & other read/write permissions are shut off -- we wouldn't
+    # want crackers to snoop password information out of the tempfile.
     tmpfile = "/tmp/fetchmailconf." + `os.getpid()`
     if rcfile:
     tmpfile = "/tmp/fetchmailconf." + `os.getpid()`
     if rcfile:
-        cmd = "fetchmail -f " + rcfile + " --configdump --nosyslog >" + tmpfile
+        cmd = "umask 077; fetchmail -f " + rcfile + " --configdump --nosyslog >" + tmpfile
     else:
     else:
-        cmd = "fetchmail --configdump --nosyslog >" + tmpfile
+        cmd = "umask 077; fetchmail --configdump --nosyslog >" + tmpfile
         
     try:
         s = os.system(cmd)
         
     try:
         s = os.system(cmd)
@@ -1701,7 +1883,7 @@ gUSiYASJpMEHhilJTEnhAlGoQqYAZQ1AiqEMZ0jDGtqQImhwwA13yMMevoQAGvGhEAWHGMOAAAA7
     # `Configuration' is the top level of the object tree we're going to mung.
     # The dictmembers list is used to track the set of fields the dictionary
     # contains; in particular, we can use it to tell whether things like the
     # `Configuration' is the top level of the object tree we're going to mung.
     # The dictmembers list is used to track the set of fields the dictionary
     # contains; in particular, we can use it to tell whether things like the
-    # monitor, interface, and netsec fields are present.
+    # monitor, interface, netsec, ssl, sslkey, or sslcert fields are present.
     dictmembers = []
     Fetchmailrc = Configuration()
     copy_instance(Fetchmailrc, fetchmailrc)
     dictmembers = []
     Fetchmailrc = Configuration()
     copy_instance(Fetchmailrc, fetchmailrc)