# Matthias Andree <matthias.andree@gmx.de>
# Requires Python with Tkinter, and the following OS-dependent services:
# posix, posixpath, socket
-version = "1.48"
+version = "1.57"
from Tkinter import *
from Dialog import *
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?
('postmaster', 'String'),
('bouncemail', 'Boolean'),
('spambounce', 'Boolean'),
+ ('softbounce', 'Boolean'),
('properties', 'String'),
('syslog', 'Boolean'),
('invisible', 'Boolean'))
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
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'),
('esmtpname', 'String'),
('esmtppassword', 'String'),
('principal', 'String'),
- ('tracepolls','Boolean'))
+ ('tracepolls','Boolean'),
+ ('badheader', 'Boolean'))
def dump(self, folded):
res = ""
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`
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]
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.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 = (
('sslcert', 'String'),
('sslcertck', 'Boolean'),
('sslcertpath', 'String'),
+ ('sslcommonname', 'String'),
('sslfingerprint', 'String'),
('properties', 'String'))
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.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):
"ODMR":"odmr"}
authlist = ("any", "password", "gssapi", "kerberos", "ssh", "otp",
- "msn", "ntlm")
+ "msn", "ntlm")
listboxhelp = {
'title' : 'List Selection Help',
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
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.
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?',
# 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()
#
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.
"""}
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:',
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)
+ 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)
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 + """
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()
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)
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)
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)
#
# 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]