]> Pileus Git - ~andy/fetchmail/blobdiff - fetchmailconf.py
Complete Dominik's name.
[~andy/fetchmail] / fetchmailconf.py
index e2e3f09453867c5944af45fb652e1a257c96883b..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
 # Matthias Andree <matthias.andree@gmx.de>
 # Requires Python with Tkinter, and the following OS-dependent services:
 #      posix, posixpath, socket
-version = "1.51 $Revision$"
+version = "1.57"
 
 from Tkinter import *
 from Dialog import *
 
 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.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.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'),
            ('postmaster',      'String'),
            ('bouncemail',      'Boolean'),
            ('spambounce',      'Boolean'),
+           ('softbounce',      'Boolean'),
            ('properties',      'String'),
            ('syslog',    'Boolean'),
            ('invisible',       '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")
            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.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
        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.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'),
        self.users = []                 # List of user entries for site
        Server.typemap = (
            ('pollname',  'String'),
@@ -121,7 +130,8 @@ class Server:
            ('esmtpname', 'String'),
            ('esmtppassword', 'String'),
            ('principal', 'String'),
            ('esmtpname', 'String'),
            ('esmtppassword', 'String'),
            ('principal', 'String'),
-           ('tracepolls','Boolean'))
+           ('tracepolls','Boolean'),
+           ('badheader', 'Boolean'))
 
     def dump(self, folded):
        res = ""
 
     def dump(self, folded):
        res = ""
@@ -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.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]
 
 
        if res[-1] == " ": res = res[0:-1]
 
@@ -249,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.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
        self.batchlimit = 0     # Max message forwarded per batch
        self.expunge = 0        # Interval between expunges (IMAP)
        self.ssl = 0            # Enable Seccure Socket Layer
@@ -258,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.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 = (
        self.sslfingerprint = None      # SSL key fingerprint to check
        self.properties = None  # Extension properties
        User.typemap = (
@@ -297,6 +310,7 @@ class User:
            ('sslcert',     'String'),
            ('sslcertck',   'Boolean'),
            ('sslcertpath', 'String'),
            ('sslcert',     'String'),
            ('sslcertck',   'Boolean'),
            ('sslcertpath', 'String'),
+           ('sslcommonname', 'String'),
            ('sslfingerprint', 'String'),
            ('properties',  'String'))
 
            ('sslfingerprint', 'String'),
            ('properties',  'String'))
 
@@ -371,6 +385,8 @@ class User:
            res = res +  flag2str(self.sslcertck, 'sslcertck')
        if self.sslcertpath and self.sslcertpath != UserDefaults.sslcertpath:
            res = res + " sslcertpath " + `self.sslcertpath`
            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:
        if self.sslfingerprint and self.sslfingerprint != UserDefaults.sslfingerprint:
            res = res + " sslfingerprint " + `self.sslfingerprint`
        if self.expunge != UserDefaults.expunge:
@@ -397,7 +413,7 @@ class User:
        if self.mailboxes:
             res = res + "    folder"
             for x in self.mailboxes:
        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):
             res = res + "\n"
        for fld in ('smtpaddress', 'preconnect', 'postconnect', 'mda', 'bsmtp', 'properties'):
            if getattr(self, fld):
@@ -666,9 +682,12 @@ needed to create a simple fetchmail setup.  These include:
 
 4. A protocol to use (POP, IMAP, ETRN, etc.)
 
 
 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
    deletion of fetched message.
 
 The novice-configuration code will assume that you want to forward mail
@@ -716,6 +735,14 @@ Send spam bounces?
        postmaster (depending on the "Bounces to sender?" option.  Otherwise,
        spam bounces are not sent (the default).
 
        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.
 Invisible
        If false (the default) fetchmail generates a Received line into
        each message and generates a HELO from the machine it is running on.
@@ -806,11 +833,18 @@ class ConfigurationEdit(Frame, MyWidget):
 
            sb = Frame(gf)
            Checkbutton(sb,
 
            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)
 
                '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?',
            sf = Frame(gf)
            Checkbutton(sf,
                {'text':'Log to syslog?',
@@ -997,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
 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.
 """}
 
 print the server's key is checked against.
 """}
 
@@ -1099,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)
            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:',
            LabeledEntry(ctlwin, 'True name of ' + host + ':',
                      self.via, leftwidth).pack(side=TOP, fill=X)
            LabeledEntry(ctlwin, 'Cycles to skip between polls:',
@@ -1436,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>
 
 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 + """
 """
            if string.find(greetline, "InterChange") > 0:
                warnings = warnings + """
@@ -1645,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)
                        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)
            LabeledEntry(sslwin, 'SSL key fingerprint:',
                         self.sslfingerprint, '14').pack(side=TOP, fill=X)
            sslwin.pack(fill=X, anchor=N)
@@ -1664,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)
            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)
                     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)
                     self.smtpname, '26').pack(side=TOP, fill=X)
            LabeledEntry(targwin, 'Connection setup command:',
                     self.preconnect, '26').pack(side=TOP, fill=X)
@@ -1946,7 +1979,7 @@ def copy_instance(toclass, fromdict):
     optional = ('interface', 'monitor',
                'esmtpname', 'esmtppassword',
                'ssl', 'sslkey', 'sslcert', 'sslproto', 'sslcertck',
     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)
     class_sig = setdiff(toclass.__dict__.keys(), optional)
     class_sig.sort()
     dict_keys = setdiff(fromdict.keys(), optional)
@@ -2039,24 +2072,31 @@ gUSiYASJpMEHhilJTEnhAlGoQqYAZQ1AiqEMZ0jDGtqQImhwwA13yMMevoQAGvGhEAWHGMOAAAA7
 #
 
     # Process options
 #
 
     # Process options
-    (options, arguments) = getopt.getopt(sys.argv[1:], "df:hV")
+    (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
     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 """
            print """
-Usage: fetchmailconf {[-d] [-f fetchmailrc]|-h|-V}
--d       - dump configuration (for debugging)
--f fmrc  - read alternate fetchmailrc file
--      - print this help text and quit
--      - print fetchmailconf version and quit
+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)
 """
            sys.exit(0)
-       elif (switch == '-V'):
+       elif (switch == '-V' or switch == '--version'):
            print "fetchmailconf %s" % 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
            sys.exit(0)
 
     # Get client host's FQDN