--- Mail-SpamAssassin-3.2.3/lib/Mail/SpamAssassin/Conf.pm Wed Oct 17 16:45:20 2007 +++ lib/Mail/SpamAssassin/Conf.pm Wed Oct 17 17:05:01 2007 @@ -2412,5 +2412,5 @@ }); -=item rbl_timeout t [t_min] (default: 15 3) +=item rbl_timeout t [t_min] [zone] (default: 15 3) All DNS queries are made at the beginning of a check and we try to read @@ -2436,4 +2436,10 @@ additional time. +If a parameter 'zone' is specified (it must end with a letter, which +distinguishes it from other numeric parametrs), then the setting only +applies to DNS queries against the specified DNS domain (host, domain or +RBL (sub)zone). Matching is case-insensitive, the actual domain may be a +subdomain of the specified zone. + =cut @@ -2447,11 +2453,21 @@ return $MISSING_REQUIRED_VALUE; } - local ($1,$2); + local ($1,$2,$3); unless ($value =~ /^ ( [+-]? \d+ (?: \. \d*)? ) - (?: \s+ ( [+-]? \d+ (?: \. \d*)? ) )? $/xs) { + (?: \s+ ( [+-]? \d+ (?: \. \d*)? ) )? + (?: \s+ (\S* [a-zA-Z]) )? $/xs) { return $INVALID_VALUE; } - $self->{rbl_timeout} = $1+0; - $self->{rbl_timeout_min} = $2+0 if defined $2; + my $zone = $3; + if (!defined $zone) { # a global setting + $self->{rbl_timeout} = $1+0; + $self->{rbl_timeout_min} = $2+0 if defined $2; + } + else { # per-zone settings + $zone =~ s/^\.//; $zone =~ s/\.$//; # strip leading and trailing dot + $zone = lc $zone; + $self->{by_zone}{$zone}{rbl_timeout} = $1+0; + $self->{by_zone}{$zone}{rbl_timeout_min} = $2+0 if defined $2; + } } }); --- Mail-SpamAssassin-3.2.3/lib/Mail/SpamAssassin/AsyncLoop.pm Wed Oct 17 16:42:11 2007 +++ lib/Mail/SpamAssassin/AsyncLoop.pm Wed Oct 17 17:05:01 2007 @@ -178,9 +178,32 @@ $ent->{start_time} = $now if !defined $ent->{start_time}; + # are there any applicable per-zone settings? + my $zone = $ent->{zone}; + my $settings; # a ref to a by-zone or to global settings + my $conf_by_zone = $self->{main}->{conf}->{by_zone}; + if (defined $zone && $conf_by_zone) { + # dbg("async: searching for by_zone settings for $zone"); + $zone =~ s/^\.//; $zone =~ s/\.\z//; # strip leading and trailing dot + for (;;) { # 2.10.example.com, 10.example.com, example.com, com, '' + if (exists $conf_by_zone->{$zone}) { + $settings = $conf_by_zone->{$zone}; + dbg("async: applying by_zone settings for $zone"); + last; + } elsif ($zone eq '') { + last; + } else { # strip one level, careful with address literals + $zone = ($zone =~ /^( (?: [^.] | \[ (?: \\. | [^\]\\] )* \] )* ) + \. (.*) \z/xs) ? $2 : ''; + } + } + } + my $t_init = $ent->{timeout_initial}; # application-specified has precedence + $t_init = $settings->{rbl_timeout} if $settings && !defined $t_init; $t_init = $self->{main}->{conf}->{rbl_timeout} if !defined $t_init; $t_init = 0 if !defined $t_init; # last-resort default, just in case my $t_end = $ent->{timeout_min}; # application-specified has precedence + $t_end = $settings->{rbl_timeout_min} if $settings && !defined $t_end; $t_end = 0.2 * $t_init if !defined $t_end; $t_end = 0 if $t_end < 0; # just in case