Hi,
currently, all mail that
- contains a "mailbomb"
- contains encrypted parts
- contains any other undecipherable parts
falls under content category "UNCHECKED" and thus shares a final destination.
I think it might be desirable to have different final destinations for these
cases. Please take the attached (untested) patch to amavis 2.8 as a
suggestion. It introduces two sub-cc's for UNCHECKED. One for mail that only
contains encrypted parts (e.g. S/MIME), the other for mail that contains
anything over limits (mailbombs?).
Thank you for comments,
Carsten
diff --git a/amavisd-new.unpatched b/amavisd-new.unpatched
index 7365735..3563bd2 100755
--- a/amavisd-new.unpatched
+++ b/amavisd-new.unpatched
@@ -427,9 +427,9 @@ BEGIN {
# referenced indirectly through *_by_ccat variables for compatibility
[qw(
$final_virus_destiny $final_banned_destiny $final_unchecked_destiny
- $final_spam_destiny $final_bad_header_destiny
- @virus_lovers_maps @spam_lovers_maps @unchecked_lovers_maps
- @banned_files_lovers_maps @bad_header_lovers_maps
+ $final_encrypted_destiny $final_mailbomb_destiny $final_spam_destiny
+ $final_bad_header_destiny @virus_lovers_maps @spam_lovers_maps
+ @unchecked_lovers_maps @banned_files_lovers_maps @bad_header_lovers_maps
$always_bcc $dsn_bcc
$mailfrom_notify_sender $mailfrom_notify_recip
$mailfrom_notify_admin $mailfrom_notify_spamadmin
@@ -1126,6 +1126,8 @@ BEGIN {
$final_virus_destiny = D_DISCARD;
$final_banned_destiny = D_DISCARD;
$final_unchecked_destiny = D_PASS;
+ $final_encrypted_destiny = D_PASS;
+ $final_mailbomb_destiny = D_PASS;
$final_spam_destiny = D_PASS;
$final_bad_header_destiny = D_PASS;
@@ -1282,6 +1284,8 @@ BEGIN {
CC_SPAMMY.',1','Spammy3', # tag3_level
CC_SPAM, 'Spam', # kill_level
CC_UNCHECKED, 'Unchecked',
+ CC_UNCHECKED.',1', 'UncheckedCrypted',
+ CC_UNCHECKED.',2', 'UncheckedOverLimits',
CC_BANNED, 'Banned',
CC_VIRUS, 'Virus',
);
@@ -1720,6 +1724,8 @@ BEGIN {
CC_VIRUS, sub { c('final_virus_destiny') },
CC_BANNED, sub { c('final_banned_destiny') },
CC_UNCHECKED, sub { c('final_unchecked_destiny') },
+ CC_UNCHECKED.',1', sub { c('final_encrypted_destiny') },
+ CC_UNCHECKED.',2', sub { c('final_mailbomb_destiny') },
CC_SPAM, sub { c('final_spam_destiny') },
CC_BADH, sub { c('final_bad_header_destiny') },
CC_MTA.',1', D_TEMPFAIL,
@@ -1736,6 +1742,8 @@ BEGIN {
CC_VIRUS, 'id=%n - INFECTED: %V',
CC_BANNED, 'id=%n - BANNED: %F',
CC_UNCHECKED, 'id=%n - UNCHECKED',
+ CC_UNCHECKED.',1', 'id=%n - UNCHECKED: encrypted message',
+ CC_UNCHECKED.',2', 'id=%n - UNCHECKED: possible mail bomb',
CC_SPAM, 'id=%n - spam',
CC_SPAMMY.',1', 'id=%n - spammy (tag3)',
CC_SPAMMY, 'id=%n - spammy',
@@ -12532,7 +12540,7 @@ sub check_mail($$) {
# across some permanent problem making us unable to decide
# if the message is to be really delivered.
# is any mail component password protected or otherwise non-decodable?
- my $any_undecipherable = 0;
+ my $any_undecipherable = 0; my $all_crypted = 1; my $over_levels = 0;
my $mime_err; # undef, or MIME parsing error string as given by MIME::Parser
if (defined $last_task_completed_at) {
my $dt = $msginfo->rx_time - $last_task_completed_at;
@@ -12793,13 +12801,16 @@ sub check_mail($$) {
$which_section = "parts_decode_ext";
snmp_count('OpsDec');
- ($hold,$any_undecipherable) =
+ ($hold,$any_undecipherable,$all_crypted,$over_levels) =
Amavis::Unpackers::decompose_mail($msginfo->mail_tempdir,
$file_generator_object);
if ($hold ne '' || $any_undecipherable) {
- $msginfo->add_contents_category(CC_UNCHECKED,0);
+ my $subcc = 0;
+ $subcc = 1 if ($any_undecipherable && $all_crypted);
+ $subcc = 2 if ($hold ne '' and $over_levels);
+ $msginfo->add_contents_category(CC_UNCHECKED,$subcc);
for my $r (@{$msginfo->per_recip_data}) {
- $r->add_contents_category(CC_UNCHECKED,0)
+ $r->add_contents_category(CC_UNCHECKED,$subcc)
if !$r->bypass_virus_checks;
}
}
@@ -27525,12 +27536,15 @@ sub decompose_mail($$) {
my($tempdir,$file_generator_object) = @_;
my $hold; my(@parts); my $depth = 1; my $any_undecipherable = 0;
+ my $all_crypted = 1;
+ my $over_levels = 0;
my $which_section = "parts_decode";
# fetch all not-yet-visited part names, and start a new cycle
TIER:
while (@parts = @{$file_generator_object->parts_list}) {
if ($MAXLEVELS > 0 && $depth > $MAXLEVELS) {
$hold = "Maximum decoding depth ($MAXLEVELS) exceeded";
+ $over_levels = 1;
last;
}
$file_generator_object->parts_list_reset; # new cycle of names
@@ -27578,13 +27592,17 @@ TIER:
for my $part (@parts) {
if ($part->exists && !defined($hold))
{ $hold = decompose_part($part, $tempdir) }
- $any_undecipherable++ if grep($_ eq 'U', @{ $part->attributes || [] });
+ if grep($_ eq 'U', @{ $part->attributes || [] }) {
+ $any_undecipherable++;
+ if (! grep($_ eq 'C', @{ $part->attributes || [] }))
+ { $all_crypted = 0; }
+ }
}
last TIER if defined $hold;
$depth++;
}
section_time($which_section); prolong_timer($which_section);
- ($hold, $any_undecipherable);
+ ($hold, $any_undecipherable, $all_crypted, $over_levels);
}
# Decompose one part