
--On 8 April 2008 22:10:58 -0400 Barry Warsaw <barry@list.org> wrote:
After far too long, I'm finally happy to announce the availability of GNU Mailman version 3.0 alpha 1, code name "Leave That Thing Alone".
This is great news.
I've downloaded the code, and had a look at the LMTP server code, which I'm looking forward to. I'm hoping that it will permit integration with Exim in a way (LMTP call forwards) that gives us something sensible to do with messages from forbidden posters.
Unfortunately, it doesn't. But, if the following seems sensible, then I'm willing to implement it:
The LMTP server is implemented as a subclass of Python's built in SMTPServer, which seems to have only one method: process_message. That must be run too late to give any useful information to a callforward. However, on closer inspection, there's a "channel" class which inherits from smtpd.SMTPChannel. This seems to override some useful looking methods:
def smtp_LHLO(self, arg):
def smtp_HELO(self, arg):
Ah, and the source suggests to me that overriding smtp_RCPT is feasible. That's the place to check whether the list exists (and whether the sender is permitted to post - but let's do one thing at a time).
Validating the recipient
All that's required is that the code which checks the existence of a list is moved from process_message to smtp_RCPT, and it's modified to "self.__rcpttos.append(address)" when the address is valid, but not otherwise. Thus, we build rcpttos instead of reading from it. LMTP requires a reply after DATA for only those addresses that haven't been rejected at RCPT. If I'm reading the code correctly, then a 550 error would be generated if the queue disappeared between RCTP and DATA (by virtue of the exception being thrown by queue.enqueue().
Validating the sender
Now, as to the question of determining whether the message sender is permitted to post to a list, that's a bit more complicated. As far as I can see, all the logic for this is in moderate.py - in the "process" function. But, the decision is all tangled up with with the actions.
I propose an additional function, to be called from process, or by the lmtp server in smtp_RCPT: perhaps post_action(list, sender) which returns the name of the action to take when "sender" posts to the list "list". I guess it will return one of "accept", "discard", "reject", or "hold", and the lmtp server should reject (not bounce) the message if "reject" or "discard" is returned. It might be nice to introduce a distinction between bounce and reject. For example, a site admin might decide to permit bounce messages to be generated for local mail domains.
-- Ian Eiloart IT Services, University of Sussex x3148