2 messages in net.sourceforge.lists.courier-users[courier-users] Passing state informa...
FromSent OnAttachments
Lloyd ZusmanMay 20, 2004 5:25 am 
Julian MehnleMay 22, 2004 10:27 am 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:[courier-users] Passing state information among Courier::Filter modulesActions...
From:Lloyd Zusman (lj@asfast.com)
Date:May 20, 2004 5:25:45 am
List:net.sourceforge.lists.courier-users

I'm using several filter modules within Julian Mehnle's excellent Courier::Filter package. Everything works fine, but there's a feature that I'd like to request.

Although the various filtering tasks that I perform within my modules are mostly independent of one another, sometimes the result of one filtering action can affect what I want to do within a subsequent filter.

One example (out of many) involves Courier::Filter::Module::SPF. A subsequent home-grown filtering step of mine wants to know the exact result of the SPF filtering: its processing differs depending on whether the SPF is 'softfail', 'unknown', 'neutral', or 'none'.

This illustrates the need for state information that can be shared among the various filtering steps.

I came up with a way to do this (see below), but it's a hack, and I'm wondering how feasible it would be to enhance Courier::Filter so that there is a more formal mechanism for sharing state among the various calls to the filter modules.

My hacked up method can be illustrated in this code fragment from my pureperlfilter.conf file:

# ... etc. ...

# State information. my %state = ();

$options = {

# ... etc. ...

modules => [ Courier::Filter::Module::MyFirst->new( state => \%state, ), # My modified version of C::F::M::SPF Courier::Filter::Module::MySPF->new( reject_on => [ 'fail', 'error' ], state => \%state, ), Courier::Filter::Module::MyFilter->new( state => \%state, ), ], };

Each filter module can then access the 'state' hashmap via $module->{state}.

All that the 'MyFirst' filter does is to remove all keys from $module->{state} and then return 'undef'.

Then, in the 'MySPF' filter, which is a minor rewrite of Courier::Filter::Module::SPF, the SPF query gets performed and its result ('pass', 'unknown', 'softfail', etc.) gets stored in $module->{state}->{spfresult}.

Finally, in 'MyFilter', $module->{state}->{spfresult} gets queried, and this value gets used to do more filtering of my choice.

I want to reiterate that this SPF case is but one example of many in which the passing of state among the various filters would be useful. Therefore, I am _not_ requesting simply an SPF-specific feature, but rather, a more general feature that allows state to be shared among all the steps within a filter chain.

I can think of a couple ways that this could be implemented:

1. A getstate() and setstate() method within Courier::Filter which manages a global state hash that is initialized to be empty before the filter chain gets invoked. Then, the following could be done:

$module->setstate('foo', $bar); $module->setstate('bar', $burfle);

# And then later ...

my $foo = $module->getstate('foo');

2. Direct access to a module-specific state hash that is automatically initialized to be empty at the start of the filter chain. This would work pretty much the same as my hack from within a filter module, but without the necessity for the user to manage it from within pureperlfilter.conf and without the user needing to define a first-in-the-chain filter that does nothing more than clear the keys of the hash. The example in (1) would then look like this within the filter module:

$module->{state}->{foo} = $bar; $module->{state}->{bar} = $burfle;

# And then later ...

my $foo = $module->{state}->{foo};

And, of course, there are other ways in which this could be done.

What do you think?

Thanks in advance.