# by Eric S. Raymond, <esr@snark.thyrsus.com>.
# Requires Python with Tkinter, and the following OS-dependent services:
# posix, posixpath, socket
-version = "1.23"
+version = "1.28"
from Tkinter import *
from Dialog import *
self.pass8bits = FALSE # Force BODY=7BIT
self.mimedecode = FALSE # Undo MIME armoring
self.dropstatus = FALSE # Drop incoming Status lines
+ self.dropdelivered = FALSE # Drop incoming Delivered-To lines
self.idle = FALSE # IDLE after poll
self.limit = 0 # Message size limit
self.warnings = 0 # Size warning interval
('pass8bits', 'Boolean'),
('mimedecode', 'Boolean'),
('dropstatus', 'Boolean'),
+ ('dropdelivered', 'Boolean'),
('idle', 'Boolean'),
('limit', 'Int'),
('warnings', 'Int'),
def __repr__(self):
res = " "
- res = res + "user " + str(self.remote) + " there ";
+ res = res + "user " + `self.remote` + " there ";
if self.password:
- res = res + "with password " + str(self.password) + " "
+ res = res + "with password " + `self.password` + " "
if self.localnames:
res = res + "is"
for x in self.localnames:
or self.pass8bits != UserDefaults.pass8bits
or self.mimedecode != UserDefaults.mimedecode
or self.dropstatus != UserDefaults.dropstatus
+ or self.dropdelivered != UserDefaults.dropdelivered
or self.idle != UserDefaults.idle):
res = res + " options"
if self.keep != UserDefaults.keep:
res = res + flag2str(self.mimedecode, 'mimedecode')
if self.dropstatus != UserDefaults.dropstatus:
res = res + flag2str(self.dropstatus, 'dropstatus')
+ if self.dropdelivered != UserDefaults.dropdelivered:
+ res = res + flag2str(self.dropdelivered, 'dropdelivered')
if self.idle != UserDefaults.idle:
res = res + flag2str(self.idle, 'idle')
if self.limit != UserDefaults.limit:
if self.sslkey and self.sslkey != UserDefaults.sslkey:
res = res + " sslkey " + `self.sslkey`
if self.sslcert and self.sslcert != UserDefaults.sslcert:
- res = res + " ssl " + `self.sslcert`
+ res = res + " sslcert " + `self.sslcert`
if self.expunge != UserDefaults.expunge:
res = res + " expunge " + `self.expunge`
res = res + "\n"
helpwin(self.helptxt)
def handleList(self, event):
- self.editItem();
+ self.editItem();
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)
- apply(self.editor, (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()
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 server_delete(self, sitename):
try:
+ for user in self.subwidgets.keys():
+ user.destruct()
del self.configuration[sitename]
except:
pass
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):
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.
+
"""
# 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, "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). You should get rid of it --
-and the brain-dead NT server it rode in on.
+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:
3.0beta or a more recent version. Better yet, switch to IMAP.
"""
- if string.find(greetline, "sprynet.com") > 0:
+ 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
server.
"""
- if string.find(greetline, "usa.net") > 0:
+ 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
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
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). We have worked around this
-bug, but suspect InterChange is likely to be broken in other ways.
-You should get rid of 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:
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
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):
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':
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)
Checkbutton(limwin, text="Idle after each poll (IMAP only)",
variable=self.idle).pack(side=TOP, anchor=W)
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:
- cmd = "fetchmail -f " + rcfile + " --configdump --nosyslog >" + tmpfile
+ cmd = "umask 077; fetchmail -f " + rcfile + " --configdump --nosyslog >" + tmpfile
else:
- cmd = "fetchmail --configdump --nosyslog >" + tmpfile
+ cmd = "umask 077; fetchmail --configdump --nosyslog >" + tmpfile
try:
s = os.system(cmd)