3 # This is a class which watches a maildir for new messages. It uses the
4 # linux dirwatcher API (if available) to look for new files. The
5 # .messageReceived method is invoked with the filename of the new message,
6 # relative to the 'new' directory of the maildir.
8 # this is an abstract base class. It must be subclassed by something to
9 # provide a delay function (which polls in the case that DNotify isn't
10 # available) and a way to safely schedule code to run after a signal handler
11 # has fired. See maildirgtk.py and maildirtwisted.py for forms that use the
12 # event loops provided by Gtk+ and Twisted.
15 from dnotify
import DNotify
22 """This is a class which watches a maildir for new messages. Once
23 started, it will run its .messageReceived method when a message is
26 def __init__(self
, basedir
=None):
27 """Create the Maildir watcher. BASEDIR is the maildir directory (the
28 one which contains new/ and tmp/)
30 self
.basedir
= basedir
32 self
.pollinterval
= 10 # only used if we don't have DNotify
36 def setBasedir(self
, basedir
):
37 self
.basedir
= basedir
40 """You must run start to receive any messages."""
42 self
.newdir
= os
.path
.join(self
.basedir
, "new")
46 if not os
.path
.isdir(self
.basedir
) or not os
.path
.isdir(self
.newdir
):
47 raise "invalid maildir '%s'" % self
.basedir
48 # we must hold an fd open on the directory, so we can get notified
53 self
.dnotify
= DNotify(self
.newdir
, self
.dnotify_callback
,
55 except (IOError, OverflowError):
56 # IOError is probably linux<2.4.19, which doesn't support
57 # dnotify. OverflowError will occur on some 64-bit machines
58 # because of a python bug
59 print "DNotify failed, falling back to polling"
64 def startTimeout(self
):
66 def stopTimeout(self
):
68 def dnotify_callback(self
):
85 if not os
.path
.isfile(os
.path
.join(self
.newdir
, f
)):
88 for f
in os
.listdir(self
.newdir
):
89 if not f
in self
.files
:
91 self
.files
.extend(newfiles
)
92 # TODO: sort by ctime, then filename, since safecat uses a rather
93 # fine-grained timestamp in the filename
95 # TODO: consider catching exceptions in messageReceived
96 self
.messageReceived(n
)
100 def messageReceived(self
, filename
):
101 """Called when a new file is noticed. Override it in subclasses.
102 Will receive path relative to maildir/new."""
113 if __name__
== '__main__':