Discussion:
custom hooks: how to ban a message
(too old to reply)
Jeremy Laidman
2007-10-30 05:35:41 UTC
Permalink
Hi all.

I'm running amavis 2.5.2 and I've written a custom hook for the
checks() subroutine. My hook is analysing the headers of the message
and the sender/recipient domains and, based on a local policy, I might
need to quarantine a message. However I'm not sure what I'm supposed
to do to make this happen. I've had a look at the example in
amavisd-custom.conf, but its quarantining code seems to be taking a
copy of the message and letting the original continue on its merry
way.

Is there a simple way to tag the message as banned, and let the
regular behaviour for a banned attachment take over?

Can I do the same per-recipient if I wanted to?

I'm doing something like this:

sub checks() {
...
if ($need_to_ban_message) {
$msginfo->add_contents_category(CC_BANNED,0);
for my $r (@{$msginfo->per_recip_data}) {
$r->recip_done(1);
}
}
}

but I get errors in my like like:

(!!)TROUBLE in check_mail: delivery-notificaton FAILED: Assert
failed: 0, 1, at ...

It would seem I have a few other things to set in order to correctly
change the status of the message. Am I on the right track?

Can I choose to not quarantine a message in some cases, but send a
notificaton as if I had?

Also, I realise that I'm trying to tag a message as banned, which is
normally associated with an attachment. However, I still want to ban
messages by my policy even when there's no attachment. Am I going to
fall foul of anything by overloading the "banned" status? Should I be
setting a message to "badh" instead?

Cheers
Jeremy

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/
Mark Martinec
2007-10-30 18:37:42 UTC
Permalink
Jeremy,
Post by Jeremy Laidman
I'm running amavis 2.5.2 and I've written a custom hook for the
checks() subroutine. My hook is analysing the headers of the message
and the sender/recipient domains and, based on a local policy, I might
need to quarantine a message. However I'm not sure what I'm supposed
to do to make this happen. I've had a look at the example in
amavisd-custom.conf, but its quarantining code seems to be taking a
copy of the message and letting the original continue on its merry
way.
Yes, this is pretty much the same as the base code does it,
just calling do_quarantine where appropriate, possibly multiple
times. Quarantining is in most respects fully independent from
other actions (such as passing/discarding/rejecting/bouncing,
and sending notifications).
Post by Jeremy Laidman
Is there a simple way to tag the message as banned, and let the
regular behaviour for a banned attachment take over?
You could call:
$r->add_contents_category(CC_BANNED,0);
for each recipient object, and:
$msginfo->add_contents_category(CC_BANNED,0);
once for the whole message, to add CC_BANNED label
to a set of contents categories.

This should be pretty much indistinguishable from
the baseline code doing the same.
Post by Jeremy Laidman
Can I do the same per-recipient if I wanted to?
Yes, add_contents_category is a property of each
recipient (and also a property of a message as a whole,
see 'blocking contents category' in 2.5.0 release notes).
Post by Jeremy Laidman
sub checks() {
...
if ($need_to_ban_message) {
$msginfo->add_contents_category(CC_BANNED,0);
$r->recip_done(1);
}
}
}
(!!)TROUBLE in check_mail: delivery-notificaton FAILED: Assert
failed: 0, 1, at ...
Don't set recip_done to true, just add_contents_category().

If you do set recip_done, you must also set recip_smtp_response(...),
indicating the success status of a delivery that you pretended
to have done.
Post by Jeremy Laidman
It would seem I have a few other things to set in order to correctly
change the status of the message. Am I on the right track?
Looks good.
Post by Jeremy Laidman
Can I choose to not quarantine a message in some cases, but send a
notificaton as if I had?
Additional notifications can be sent from a custom hook,
as indicated in the amavisd-custom.conf example.
Turning off quarantinining is trickier - I can't think
of an elegant way to do it from a custom hook.
I admit it would be useful.
Post by Jeremy Laidman
Also, I realise that I'm trying to tag a message as banned, which is
normally associated with an attachment. However, I still want to ban
messages by my policy even when there's no attachment. Am I going to
fall foul of anything by overloading the "banned" status? Should I be
setting a message to "badh" instead?
There is no involvement of attachents concept there, all MIME
parts are treated equally. If there is only one top-level MIME part,
so be it, it still has its content type, file type, and possibly
even a suggested name. I think you are using the right approach.

Mark

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/
Jeremy Laidman
2007-10-31 09:17:03 UTC
Permalink
Mark, thanks for your helpful response.
Post by Mark Martinec
Post by Jeremy Laidman
Can I do the same per-recipient if I wanted to?
Yes, add_contents_category is a property of each
recipient (and also a property of a message as a whole,
see 'blocking contents category' in 2.5.0 release notes).
(after reading about blocking contents cateogory) now I understand why
each recipient AND the message need to be marked as banned.
Post by Mark Martinec
Post by Jeremy Laidman
(!!)TROUBLE in check_mail: delivery-notificaton FAILED: Assert
failed: 0, 1, at ...
Don't set recip_done to true, just add_contents_category().
OK, but...
Post by Mark Martinec
If you do set recip_done, you must also set recip_smtp_response(...),
indicating the success status of a delivery that you pretended
to have done.
So I could do this if I wanted to have control over the SMTP response.
Post by Mark Martinec
Post by Jeremy Laidman
Can I choose to not quarantine a message in some cases, but send a
notificaton as if I had?
Additional notifications can be sent from a custom hook,
as indicated in the amavisd-custom.conf example.
Turning off quarantinining is trickier - I can't think
of an elegant way to do it from a custom hook.
I admit it would be useful.
Can I set the quarantine method ($banned_files_quarantine_method) to
undef() or something like that?
Post by Mark Martinec
Post by Jeremy Laidman
Also, I realise that I'm trying to tag a message as banned, which is
normally associated with an attachment. However, I still want to ban
messages by my policy even when there's no attachment.
There is no involvement of attachents concept there, all MIME
parts are treated equally.
Yes, for a single-part MIME with no other parts. However what about a
plain RFC2822 message without any MIME? In particular, some of the
base code, do_notify_and_quarantine(), looks at $r->banned_parts, but
if I haven't set any banned parts, I might break something. I suspect
this will only break template macros related to banned attachments,
which I can deal with. But I'd like to be sure that there isn't a bit
of code that assumes a banned attachment is always present in a banned
message.

Two more questions on this subject, if I may impose:

My reading of the release notes suggests that I can check the virus
status of the message before performing an action, because the custom
checks() happens after the built-in checks. Assuming that's correct,
what's the best way to do this? Should I test
$r->is_in_contents_category(CC_VIRUS) per recipient? Or can I do it
for the entire message with
$msginfo->is_in_contents_category(CC_VIRUS)?

Also, can I determine, from within a custom hook, what is the current
loaded policy bank?

Cheers
Jeremy

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/
Mark Martinec
2007-11-01 00:03:17 UTC
Permalink
Jeremy,
Post by Jeremy Laidman
Post by Mark Martinec
Don't set recip_done to true, just add_contents_category().
OK, but...
Post by Mark Martinec
If you do set recip_done, you must also set recip_smtp_response(...),
indicating the success status of a delivery that you pretended
to have done.
So I could do this if I wanted to have control over the SMTP response.
Yes, but only if it is your custom hook code that sets recip_done to true,
indicating (or faking) it performed a delivery. Otherwise the status
code will be overwritten by some later code section which does a delivery
and sets recip_done to true.
Post by Jeremy Laidman
Post by Mark Martinec
Turning off quarantinining is trickier - I can't think
of an elegant way to do it from a custom hook.
I admit it would be useful.
Can I set the quarantine method ($banned_files_quarantine_method) to
undef() or something like that?
Not really - doing so would change a global setting for the lifetime
of this process, affecting future messages checked by this child process.
Some other trick will need to be devised (like adding a new variable
or a recipient object property), with a corresponding supporting change
in the base code.
Post by Jeremy Laidman
Post by Mark Martinec
There is no involvement of attachents concept there, all MIME
parts are treated equally.
Yes, for a single-part MIME with no other parts. However what about a
plain RFC2822 message without any MIME?
It is still a tree of MIME parts, a small one with a single node.
Post by Jeremy Laidman
In particular, some of the
base code, do_notify_and_quarantine(), looks at $r->banned_parts,
It will contain a list of just one element, the plain mail body part.
Actually the list may even be empty, in case of no body and no
header/body separator line.
Post by Jeremy Laidman
but if I haven't set any banned parts, I might break something. I suspect
this will only break template macros related to banned attachments,
which I can deal with. But I'd like to be sure that there isn't a bit
of code that assumes a banned attachment is always present in a banned
message.
It shouldn't break anything. If it does, it needs to be fixed.
Post by Jeremy Laidman
My reading of the release notes suggests that I can check the virus
status of the message before performing an action, because the custom
checks() happens after the built-in checks. Assuming that's correct,
what's the best way to do this?
Right.
Post by Jeremy Laidman
Should I test $r->is_in_contents_category(CC_VIRUS) per recipient?
Or can I do it for the entire message with
$msginfo->is_in_contents_category(CC_VIRUS)?
The $msginfo has a CC_VIRUS set if a virus was found.
Probably this is what you want.

A recipient's object has a CC_VIRUS set if a virus was found AND this
particular recipient DOES NOT have a bypass_virus_checks_maps set.

As you already know, the is_in_contents_category test for presence
of a contents category, but this is not necessary a blocking ccat,
e.g. when a recipient is a virus lover.
Post by Jeremy Laidman
Sorry, one more question: Can I determine, from within a custom hook,
what is the currently loaded policy bank?
Yes, the c('policy_bank_path') returns a string, which is a
slash-separated list of currently loaded policy bank names.
Same as provided by a macro %p.

Mark

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/
Jeremy Laidman
2007-11-14 04:15:51 UTC
Permalink
Post by Mark Martinec
Post by Jeremy Laidman
Can I choose to not quarantine a message in some cases, but send a
notification as if I had?
(I've given up on skipping the quarantine for now.)
Post by Mark Martinec
Additional notifications can be sent from a custom hook,
as indicated in the amavisd-custom.conf example.
I'm having a bit of trouble with this. I'm not sure if I'm fighting
amavis or just my inexperience with it. Any pointers would be very
useful.

I want to notify the local user (sender for outbound, recipient(s) for
inbound) when a message is banned by my custom hook, using a template.
I can't leave things to the normal final destiny settings, because
banned files need to be handled differently to these policy
violations, and I can't see any way of making the notification
dependent on the reason for a banned message. So I'm trying to notify
within my custom hook.

When I follow the example, it doesn't seem to be able to expand a
template's macros successfully. I'm copying the global
Amavis::builtins and trying to use that, calling the expand sub from
its package in the main code.

Even if I get this working, I think the normal banned template gets
sent to the user, as well as my notification, which is not acceptable.

So my questions:
1) Can I expand a template within a custom hook?
2) Can I prevent the original notification from being sent?
3) Do I want to do this? Is there a better way?

Thanks so much for your help, and amavis - such a very useful program.

Cheers
Jeremy

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/
Jeremy Laidman
2007-11-16 02:34:21 UTC
Permalink
Post by Jeremy Laidman
1) Can I expand a template within a custom hook?
2) Can I prevent the original notification from being sent?
3) Do I want to do this? Is there a better way?
Can anyone help? Or is this in the "too hard" basket?

Is anyone else using custom hooks? Google shows me nothing except the
release notes and my own posts.

Cheers
Jeremy

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/
Mark Martinec
2007-11-17 00:57:48 UTC
Permalink
Jeremy,
Post by Jeremy Laidman
Post by Mark Martinec
Additional notifications can be sent from a custom hook,
as indicated in the amavisd-custom.conf example.
I'm having a bit of trouble with this. I'm not sure if I'm fighting
amavis or just my inexperience with it. Any pointers would be very
useful.
The hooks are somewhat limiting for the purposes you have in mind.
I see that some improvements would be in order.
Post by Jeremy Laidman
I want to notify the local user (sender for outbound, recipient(s) for
inbound) when a message is banned by my custom hook, using a template.
I can't leave things to the normal final destiny settings, because
banned files need to be handled differently to these policy
violations, and I can't see any way of making the notification
dependent on the reason for a banned message. So I'm trying to notify
within my custom hook.
A possible solution would be to allow custom hooks to prepare a
value for some new dedicated macro, and let templates base their
expansion on that value. That would probably offer the cleanest
solution for least work.

I also see a need for a mechanism by which custom hooks could
suppress normal notifications and quarantining - currently this
is only possible indirectly by modifying attributes of a mail
(e.g. its contents category). Then you could send your own
notifications without worrying about multiple notifications.
Post by Jeremy Laidman
When I follow the example, it doesn't seem to be able to expand a
template's macros successfully. I'm copying the global
Amavis::builtins and trying to use that, calling the expand sub from
its package in the main code.
That should work. I'll test it tomorrow.
Post by Jeremy Laidman
Even if I get this working, I think the normal banned template gets
sent to the user, as well as my notification, which is not acceptable.
1) Can I expand a template within a custom hook?
I believe this should be possible. Will try.
Post by Jeremy Laidman
2) Can I prevent the original notification from being sent?
Not without a hack, or without modifying a reason for a notification.
Post by Jeremy Laidman
3) Do I want to do this? Is there a better way?
I think your needs are sensible. I'll see what can be done.

Mark

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/
Mark Martinec
2007-11-17 14:29:08 UTC
Permalink
Post by Mark Martinec
I also see a need for a mechanism by which custom hooks could
suppress normal notifications and quarantining - currently this
is only possible indirectly by modifying attributes of a mail
(e.g. its contents category). Then you could send your own
notifications without worrying about multiple notifications.
On a second thought, preparing a policy bank with required
settings (like suppressing quarantine, special templates,
destiny* settings, ..) and having it pre-configured in the normal
config file, then loaded when needed by a custom hook - could
achieve most if not all of your needs.

Just call:
Amavis::load_policy_bank($some_bank_name)
as needed from a custom hook.

A custom macro could still be useful though.

Mark

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/
Jeremy Laidman
2007-11-18 00:30:03 UTC
Permalink
Post by Mark Martinec
On a second thought, preparing a policy bank with required
settings (like suppressing quarantine, special templates,
destiny* settings, ..) and having it pre-configured in the normal
config file, then loaded when needed by a custom hook - could
achieve most if not all of your needs.
Yes, I think I see what you mean. In fact I'd probably have my policy
bank definition at the top of my included file that contains the
custom hook code, just to keep it all in one place.
Post by Mark Martinec
Amavis::load_policy_bank($some_bank_name)
as needed from a custom hook.
Thanks a lot for your help. I'll give it a go now.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/
Mark Martinec
2007-11-29 16:48:17 UTC
Permalink
Jeremy,
Post by Jeremy Laidman
Post by Mark Martinec
On a second thought, preparing a policy bank with required
settings (like suppressing quarantine, special templates,
destiny* settings, ..) and having it pre-configured in the normal
config file, then loaded when needed by a custom hook - could
achieve most if not all of your needs.
Yes, I think I see what you mean. In fact I'd probably have my policy
bank definition at the top of my included file that contains the
custom hook code, just to keep it all in one place.
Post by Mark Martinec
Amavis::load_policy_bank($some_bank_name)
as needed from a custom hook.
Thanks a lot for your help. I'll give it a go now.
Just wanted to check: were you able to achieve what you intended?

In my current code I moved the custom hook initialization call
(the Amavis::Custom->new) slightly earlier, so that loading
a policy bank from there can influence a few more things, just
in case someone would need it (like OS fingerprinting settings,
local_domains).

Mark

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell. From the desktop to the data center, Linux is going
mainstream. Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/
Mark Martinec
2008-03-06 20:08:28 UTC
Permalink
Jeremy,
Post by Mark Martinec
In my current code I moved the custom hook initialization call
(the Amavis::Custom->new) slightly earlier, so that loading
a policy bank from there can influence a few more things, just
in case someone would need it (like OS fingerprinting settings,
local_domains).
Nice. Not sure I need it, but good to know.
Speaking of the init call, I couldn't get it to run only once.
It seems to run on every email.
Indeed. A fresh custom object is created with every mail.
This makes it less of a chance that come custom hook would
forget to reset some state and leak information from
one message to the next.
Although I don't use it this way, I can see it being
useful for opening a persistent database handle, inherited by every child.
What I do is load some data from a config file and I'd rather not have to
do that for every email.
If you need persistent data, there are two options:

To have some variable which may be declared at amavisd startup time
in a parent process and forked into children, just declare it
with my() or own() or use 'vars' in amavisd.conf, and you have it.

If each child process should have its own (e.g. a connection to
a database), declare some variable globally (in amavisd.conf)
and leave it undefined, then at the first call for a custom
hook's new() it can be initialized, e.g. a socket created
or an SQL connection made. A DESTROY method could be declared
for a clean shutdown.

Mark

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
AMaViS-user mailing list
AMaViS-***@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/

Continue reading on narkive:
Loading...