]> Pileus Git - ~andy/fetchmail/blobdiff - fetchmailconf.py
Update German translation.
[~andy/fetchmail] / fetchmailconf.py
index b1f492dbdccc6495fdae50e802437cc855f9e7dd..2dc02d875995b088dd49e2e84a89ae434e085074 100755 (executable)
@@ -5,7 +5,7 @@
 # Matthias Andree <matthias.andree@gmx.de>
 # Requires Python with Tkinter, and the following OS-dependent services:
 #      posix, posixpath, socket
-version = "1.47"
+version = "1.57"
 
 from Tkinter import *
 from Dialog import *
@@ -22,6 +22,7 @@ class Configuration:
        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?
@@ -33,6 +34,7 @@ class Configuration:
            ('postmaster',      'String'),
            ('bouncemail',      'Boolean'),
            ('spambounce',      'Boolean'),
+           ('softbounce',      'Boolean'),
            ('properties',      'String'),
            ('syslog',    'Boolean'),
            ('invisible',       'Boolean'))
@@ -55,10 +57,16 @@ class Configuration:
            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
@@ -97,6 +105,7 @@ class Server:
        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'),
@@ -121,7 +130,8 @@ class Server:
            ('esmtpname', 'String'),
            ('esmtppassword', 'String'),
            ('principal', 'String'),
-           ('tracepolls','Boolean'))
+           ('tracepolls','Boolean'),
+           ('badheader', 'Boolean'))
 
     def dump(self, folded):
        res = ""
@@ -132,7 +142,7 @@ class Server:
            res = res + (" via " + str(self.via) + "\n");
        if self.protocol != ServerDefaults.protocol:
            res = res + " with proto " + self.protocol
-       if self.service and self.service != defaultports[self.protocol] and self.service != ianaservices[defaultports[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`
@@ -191,6 +201,8 @@ class Server:
        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]
 
@@ -235,6 +247,7 @@ class User:
        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
@@ -248,7 +261,7 @@ class User:
        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 = 10      # Do fast uidl 9 out of 10 times
+       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
@@ -257,6 +270,7 @@ class User:
        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 = (
@@ -274,6 +288,7 @@ class User:
            ('antispam',    'String'),
            ('keep',    'Boolean'),
            ('flush',       'Boolean'),
+           ('limitflush',  'Boolean'),
            ('fetchall',    'Boolean'),
            ('rewrite',     'Boolean'),
            ('forcecr',     'Boolean'),
@@ -295,6 +310,7 @@ class User:
            ('sslcert',     'String'),
            ('sslcertck',   'Boolean'),
            ('sslcertpath', 'String'),
+           ('sslcommonname', 'String'),
            ('sslfingerprint', 'String'),
            ('properties',  'String'))
 
@@ -310,6 +326,7 @@ class User:
            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
@@ -324,6 +341,8 @@ class User:
            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:
@@ -366,6 +385,8 @@ class User:
            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:
@@ -392,7 +413,7 @@ class User:
        if self.mailboxes:
             res = res + "    folder"
             for x in self.mailboxes:
-               res = res + " " + x
+               res = res + ' "%s"' % x
             res = res + "\n"
        for fld in ('smtpaddress', 'preconnect', 'postconnect', 'mda', 'bsmtp', 'properties'):
            if getattr(self, fld):
@@ -428,7 +449,8 @@ defaultports = {"auto":None,
                "ETRN":"smtp",
                "ODMR":"odmr"}
 
-authlist = ("any", "password", "gssapi", "kerberos", "ssh", "otp")
+authlist = ("any", "password", "gssapi", "kerberos", "ssh", "otp",
+           "msn", "ntlm")
 
 listboxhelp = {
     'title' : 'List Selection Help',
@@ -660,9 +682,12 @@ needed to create a simple fetchmail setup.  These include:
 
 4. A protocol to use (POP, IMAP, ETRN, etc.)
 
-5. A polling interval.
+5. A poll interval in seconds.
+   If 0, fetchmail will run in the foreground once when started.
+   If > 0, fetchmail will run in the background and start a new poll
+   cycle after the interval has elapsed.
 
-6. Options to fetch old messages as well as new, uor to suppress
+6. Options to fetch old messages as well as new, or to suppress
    deletion of fetched message.
 
 The novice-configuration code will assume that you want to forward mail
@@ -710,6 +735,14 @@ Send spam bounces?
        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.
+
 Invisible
        If false (the default) fetchmail generates a Received line into
        each message and generates a HELO from the machine it is running on.
@@ -800,11 +833,18 @@ class ConfigurationEdit(Frame, MyWidget):
 
            sb = Frame(gf)
            Checkbutton(sb,
-               {'text':'send spam bounces?',
+               {'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?',
@@ -864,14 +904,17 @@ class ConfigurationEdit(Frame, MyWidget):
            # Pre-1.5.2 compatibility...
            except os.error:
                pass
+           oldumask = os.umask(077)
            fm = open(self.outfile, 'w')
+           os.umask(oldumask)
        if fm:
-           fm.write("# Configuration created %s by fetchmailconf\n" % time.ctime(time.time()))
+           # 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()
-           if fm != sys.stdout:
-               os.chmod(self.outfile, 0600)
            self.destruct()
 
 #
@@ -962,7 +1005,12 @@ sechelp = {
     'title' : 'Security option help',
     'banner': 'Security',
     'text' : """
-The `interface' option allows you to specify a range
+The 'authorization mode' allows you to choose the
+mode that fetchmail uses to log in to your server. You
+can usually leave this at 'any', but you will have to pick
+'NTLM' and 'MSN' manually for the nonce.
+
+The 'interface' option allows you to specify a range
 of IP addresses to monitor for activity.  If these
 addresses are not active, fetchmail will not poll.
 Specifying this may protect you from a spoofing attack
@@ -983,8 +1031,10 @@ 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 sslcertck option enables strict checking of SSL server
-certificates (and sslcertpath gives trusted certificate
-directory). With sslfingerprint, you can specify a finger-
+certificates (and sslcertpath gives the trusted certificate
+directory). The sslcommonname option helps if the server is
+misconfigured and returning "Server CommonName mismatch"
+warnings. With sslfingerprint, you can specify a finger-
 print the server's key is checked against.
 """}
 
@@ -1085,6 +1135,8 @@ class ServerEdit(Frame, MyWidget):
            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:',
@@ -1163,8 +1215,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
-               #       ButtonBar(secwin, 'Authorization mode:',
-               #                self.auth, authlist, 1, None).pack(side=TOP)
+               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)
@@ -1422,13 +1474,6 @@ 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 + """
@@ -1501,6 +1546,7 @@ Fetchmail doesn't know anything special about this server type.
            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()
@@ -1630,6 +1676,8 @@ class UserEdit(Frame, MyWidget):
                        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)
@@ -1649,9 +1697,9 @@ class UserEdit(Frame, MyWidget):
            Label(targwin, text="Domains to fetch from (ODMR/ETRN only)").pack(side=TOP)
            ListEdit("Domains:",
                     self.user.fetchdomains, None, None, targwin, None)
-           LabeledEntry(targwin, 'Append to MAIL FROM line:',
+           LabeledEntry(targwin, 'Use domain on RCPT TO line:',
                     self.smtpaddress, '26').pack(side=TOP, fill=X)
-           LabeledEntry(targwin, 'Set RCPT To address:',
+           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)
@@ -1684,6 +1732,8 @@ class UserEdit(Frame, MyWidget):
        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",
@@ -1929,7 +1979,7 @@ def copy_instance(toclass, fromdict):
     optional = ('interface', 'monitor',
                'esmtpname', 'esmtppassword',
                'ssl', 'sslkey', 'sslcert', 'sslproto', 'sslcertck',
-               'sslcertpath', 'sslfingerprint', 'showdots')
+               'sslcertpath', 'sslcommonname', 'sslfingerprint', 'showdots')
     class_sig = setdiff(toclass.__dict__.keys(), optional)
     class_sig.sort()
     dict_keys = setdiff(fromdict.keys(), optional)
@@ -2022,20 +2072,32 @@ gUSiYASJpMEHhilJTEnhAlGoQqYAZQ1AiqEMZ0jDGtqQImhwwA13yMMevoQAGvGhEAWHGMOAAAA7
 #
 
     # Process options
-    (options, arguments) = getopt.getopt(sys.argv[1:], "df:h")
+    (options, arguments) = getopt.getopt(sys.argv[1:], "df:hV", ["help",
+           "version"])
     dump = rcfile = None;
     for (switch, val) in options:
        if (switch == '-d'):
            dump = TRUE
        elif (switch == '-f'):
            rcfile = val
-       elif (switch == '-h'):
+       elif (switch == '-h' or switch == '--help'):
            print """
-Usage: fetchmailconf [-d] [-f fetchmailrc]
--d       - dump configuration (for debugging)
--f fmrc  - read alternate fetchmailrc file
+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 """
+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)
 
     # Get client host's FQDN
     hostname = socket.gethostbyaddr(socket.gethostname())[0]