~ubuntu-branches/ubuntu/hardy/exim4/hardy-proposed

« back to all changes in this revision

Viewing changes to src/exipick.src

  • Committer: Bazaar Package Importer
  • Author(s): Marc Haber
  • Date: 2005-07-02 06:08:34 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050702060834-qk17pd52kb9nt3bj
Tags: 4.52-1
* new upstream version 4.51. (mh)
  * adapt 70_remove_exim-users_references
  * remove 37_gnutlsparams
  * adapt 36_pcre
  * adapt 31_eximmanpage
* fix package priorities to have them in sync with override again. (mh)
* Fix error in nb (Norwegian) translation.
  Thanks to Helge Hafting. (mh). Closes: #315775
* Standards-Version: 3.6.2, no changes needed. (mh)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!PERL_COMMAND
 
2
# $Cambridge: exim/exim-src/src/exipick.src,v 1.5 2005/06/07 09:15:04 ph10 Exp $
2
3
 
3
4
# This variable should be set by the building process to Exim's spool directory.
4
5
my $spool = 'SPOOL_DIRECTORY';
7
8
use Getopt::Long;
8
9
 
9
10
my($p_name)   = $0 =~ m|/?([^/]+)$|;
10
 
my $p_version = "20040221.0";
 
11
my $p_version = "20050604.1";
11
12
my $p_usage   = "Usage: $p_name [--help|--version] (see --help for details)";
12
13
my $p_cp      = <<EOM;
13
 
        Copyright (c) 2003-2004 John Jetmore <jj33\@pobox.com>
 
14
        Copyright (c) 2003-2005 John Jetmore <jj33\@pobox.com>
14
15
 
15
16
    This program is free software; you can redistribute it and/or modify
16
17
    it under the terms of the GNU General Public License as published by
28
29
EOM
29
30
ext_usage(); # before we do anything else, check for --help
30
31
 
 
32
$| = 1; # unbuffer STDOUT
 
33
 
31
34
Getopt::Long::Configure("bundling_override");
32
35
GetOptions(
33
 
  'spool:s' => \$G::spool,      # exim spool dir
34
 
  'bp'      => \$G::mailq_bp,   # List the queue (noop - default)
35
 
  'bpa'     => \$G::mailq_bpa,  # ... with generated address as well
36
 
  'bpc'     => \$G::mailq_bpc,  # ... but just show a count of messages
37
 
  'bpr'     => \$G::mailq_bpr,  # ... do not sort
38
 
  'bpra'    => \$G::mailq_bpra, # ... with generated addresses, unsorted
39
 
  'bpru'    => \$G::mailq_bpru, # ... only undelivered addresses, unsorted
40
 
  'bpu'     => \$G::mailq_bpu,  # ... only undelivered addresses
41
 
  'and'     => \$G::and,        # 'and' the criteria (default)
42
 
  'or'      => \$G::or,         # 'or' the criteria
43
 
  'f:s'     => \$G::qgrep_f,    # from regexp
44
 
  'r:s'     => \$G::qgrep_r,    # recipient regexp
45
 
  #'s:s'     => \$G::qgrep_s,    # match against size field
46
 
  'y:s'     => \$G::qgrep_y,    # message younger than (secs)
47
 
  'o:s'     => \$G::qgrep_o,    # message older than (secs)
48
 
  'z'       => \$G::qgrep_z,    # frozen only
49
 
  'x'       => \$G::qgrep_x,    # non-frozen only
50
 
  'c'       => \$G::qgrep_c,    # display match count
51
 
  'l'       => \$G::qgrep_l,    # long format (default)
52
 
  'i'       => \$G::qgrep_i,    # message ids only
53
 
  'b'       => \$G::qgrep_b,    # brief format
54
 
  'flatq'   => \$G::flatq,      # brief format
55
 
  'show-vars:s' => \$G::show    # display the contents of these vars
 
36
  'spool:s'     => \$G::spool,      # exim spool dir
 
37
  'bp'          => \$G::mailq_bp,   # List the queue (noop - default)
 
38
  'bpa'         => \$G::mailq_bpa,  # ... with generated address as well
 
39
  'bpc'         => \$G::mailq_bpc,  # ... but just show a count of messages
 
40
  'bpr'         => \$G::mailq_bpr,  # ... do not sort
 
41
  'bpra'        => \$G::mailq_bpra, # ... with generated addresses, unsorted
 
42
  'bpru'        => \$G::mailq_bpru, # ... only undelivered addresses, unsorted
 
43
  'bpu'         => \$G::mailq_bpu,  # ... only undelivered addresses
 
44
  'and'         => \$G::and,        # 'and' the criteria (default)
 
45
  'or'          => \$G::or,         # 'or' the criteria
 
46
  'f:s'         => \$G::qgrep_f,    # from regexp
 
47
  'r:s'         => \$G::qgrep_r,    # recipient regexp
 
48
  's:s'         => \$G::qgrep_s,    # match against size field
 
49
  'y:s'         => \$G::qgrep_y,    # message younger than (secs)
 
50
  'o:s'         => \$G::qgrep_o,    # message older than (secs)
 
51
  'z'           => \$G::qgrep_z,    # frozen only
 
52
  'x'           => \$G::qgrep_x,    # non-frozen only
 
53
  'c'           => \$G::qgrep_c,    # display match count
 
54
  'l'           => \$G::qgrep_l,    # long format (default)
 
55
  'i'           => \$G::qgrep_i,    # message ids only
 
56
  'b'           => \$G::qgrep_b,    # brief format
 
57
  'flatq'       => \$G::flatq,      # brief format
 
58
  'caseful'     => \$G::caseful,    # in '=' criteria, respect case
 
59
  'caseless'    => \$G::caseless,   #   ...ignore case (default)
 
60
  'show-vars:s' => \$G::show_vars,  # display the contents of these vars
 
61
  'show-rules'  => \$G::show_rules, # display compiled match rules
 
62
  'show-tests'  => \$G::show_tests  # display tests as applied to each message
56
63
) || exit(1);
57
64
 
58
 
push(@ARGV, "\$sender_address =~ /$G::qgrep_f/") if ($G::qgrep_f);
59
 
push(@ARGV, "\$recipients =~ /$G::qgrep_r/")     if ($G::qgrep_r);
60
 
push(@ARGV, "\$message_age < $G::qgrep_y")       if ($G::qgrep_y);
61
 
push(@ARGV, "\$message_age > $G::qgrep_o")       if ($G::qgrep_o);
62
 
push(@ARGV, "\$deliver_freeze")                  if ($G::qgrep_z);
63
 
push(@ARGV, "!\$deliver_freeze")                 if ($G::qgrep_x);
64
 
$G::mailq_bp   = $G::mailq_bp; # shut up -w
65
 
$G::and        = $G::and;      # shut up -w
66
 
$spool         = $G::spool if ($G::spool);
67
 
my $count_only = 1 if ($G::mailq_bpc || $G::qgrep_c);
68
 
my $unsorted   = 1 if ($G::mailq_bpr || $G::mailq_bpra || $G::mailq_bpru);
69
 
my $msg        = get_all_msgs($spool, $unsorted);
70
 
my $crit       = process_criteria(\@ARGV);
71
 
my $e          = Exim::SpoolFile->new();
72
 
my $tcount     = 0 if ($count_only);
73
 
my $mcount     = 0 if ($count_only);
 
65
push(@ARGV, "\$sender_address     =~ /$G::qgrep_f/") if ($G::qgrep_f);
 
66
push(@ARGV, "\$recipients         =~ /$G::qgrep_r/") if ($G::qgrep_r);
 
67
push(@ARGV, "\$shown_message_size eq $G::qgrep_s")   if ($G::qgrep_s);
 
68
push(@ARGV, "\$message_age        <  $G::qgrep_y")   if ($G::qgrep_y);
 
69
push(@ARGV, "\$message_age        >  $G::qgrep_o")   if ($G::qgrep_o);
 
70
push(@ARGV, "\$deliver_freeze")                      if ($G::qgrep_z);
 
71
push(@ARGV, "!\$deliver_freeze")                     if ($G::qgrep_x);
 
72
$G::mailq_bp        = $G::mailq_bp;        # shut up -w
 
73
$G::and             = $G::and;             # shut up -w
 
74
$G::msg_ids         = {};
 
75
$G::caseless        = $G::caseful ? 0 : 1; # nocase by default, case if both
 
76
@G::recipients_crit = ();
 
77
$spool              = $G::spool if ($G::spool);
 
78
my $count_only      = 1 if ($G::mailq_bpc || $G::qgrep_c);
 
79
my $unsorted        = 1 if ($G::mailq_bpr || $G::mailq_bpra || $G::mailq_bpru);
 
80
my $msg             = get_all_msgs($spool, $unsorted);
 
81
my $crit            = process_criteria(\@ARGV);
 
82
my $e               = Exim::SpoolFile->new();
 
83
my $tcount          = 0 if ($count_only);
 
84
my $mcount          = 0 if ($count_only);
 
85
$e->set_undelivered_only(1)      if ($G::mailq_bpru || $G::mailq_bpu);
 
86
$e->set_show_generated(1)        if ($G::mailq_bpra || $G::mailq_bpa);
 
87
$e->output_long()                if ($G::qgrep_l);
 
88
$e->output_idonly()              if ($G::qgrep_i);
 
89
$e->output_brief()               if ($G::qgrep_b);
 
90
$e->output_flatq()               if ($G::flatq);
 
91
$e->set_show_vars($G::show_vars) if ($G::show_vars);
74
92
$e->set_spool($spool);
75
 
$e->set_undelivered_only(1) if ($G::mailq_bpru || $G::mailq_bpu);
76
 
$e->set_show_generated(1)   if ($G::mailq_bpa || $G::mailq_bpra);
77
 
$e->output_long()           if ($G::qgrep_l);
78
 
$e->output_idonly()         if ($G::qgrep_i);
79
 
$e->output_brief()          if ($G::qgrep_b);
80
 
$e->output_flatq()          if ($G::flatq);
81
 
$e->set_show_vars($G::show) if ($G::show);
82
93
 
83
94
MSG:
84
95
foreach my $m (@$msg) {
 
96
  next if (scalar(keys(%$G::msg_ids)) && !$G::or
 
97
                                      && !$G::msg_ids->{$m->{message}});
85
98
  if (!$e->parse_message($m->{message})) {
86
99
    warn "Couldn't parse $m->{message}: ".$e->error()."\n";
87
100
    next(MSG);
88
101
  }
89
102
  $tcount++;
90
103
  my $match = 0;
 
104
  my @local_crit = ();
 
105
  foreach my $c (@G::recipients_crit) {              # handle each_recip* vars
 
106
    foreach my $addr (split(/, /, $e->get_var($c->{var}))) {
 
107
      my %t = ( 'cmp' => $c->{cmp}, 'var' => $c->{var} );
 
108
      $t{cmp} =~ s/"?\$var"?/'$addr'/;
 
109
      push(@local_crit, \%t);
 
110
    }
 
111
  }
 
112
  if ($G::show_tests) { print $e->get_var('message_id'), "\n"; }
91
113
  CRITERIA:
92
 
  foreach my $c (@$crit) {
 
114
  foreach my $c (@$crit, @local_crit) {
93
115
    my $var = $e->get_var($c->{var});
94
116
    my $ret = eval($c->{cmp});
 
117
    if ($G::show_tests) {
 
118
      printf "  %25s =  '%s'\n  %25s => $ret\n",$c->{var},$var,$c->{cmp},$ret;
 
119
    }
95
120
    if ($@) {
96
121
      print STDERR "Error in eval '$c->{cmp}': $@\n";
97
122
      next(MSG);
101
126
      else        { next(CRITERIA); }
102
127
    } else { # no match
103
128
      if ($G::or) { next(CRITERIA); }
104
 
      else        { next(MSG); }
 
129
      else        { next(MSG);      }
105
130
    }
106
131
  }
107
 
  next(MSG) if (scalar(@$crit) > 0 && !$match);
 
132
  next(MSG) if (scalar(@$crit, @local_crit) > 0 && !$match);
108
133
 
109
134
  if ($count_only) {
110
135
    $mcount++;
128
153
 
129
154
  foreach (@$a) {
130
155
    foreach my $t ('@') { s/$t/\\$t/g; } # '$'
131
 
    if (/^(.*?)\s*(<=|>=|==|!=|<|>)\s*(.*)$/) {
 
156
    if (/^(.*?)\s+(<=|>=|==|!=|<|>)\s+(.*)$/) {
132
157
      #print STDERR "found as integer\n";
133
158
      my $v = $1; my $o = $2; my $n = $3;
134
159
      if    ($n =~ /^([\d\.]+)M$/)  { $n = $1 * 1024 * 1024; }
145
170
        next;
146
171
      }
147
172
      push(@c, { var => lc($v), cmp => "(\$var $o $n) ? 1 : 0" });
148
 
    } elsif (/^(.*?)\s*(=~|!~)\s*(.*)$/) {
 
173
    } elsif (/^(.*?)\s+(=~|!~)\s+(.*)$/) {
149
174
      #print STDERR "found as string regexp\n";
150
175
      push(@c, { var => lc($1), cmp => "(\"\$var\" $2 $3) ? 1 : 0" });
151
 
    } elsif (/^(.*?)\s*(eq|ne)\s*(.*)$/) {
 
176
    } elsif (/^(.*?)\s+=\s+(.*)$/) {
 
177
      #print STDERR "found as bare string regexp\n";
 
178
      my $case = $G::caseful ? '' : 'i';
 
179
      push(@c, { var => lc($1), cmp => "(\"\$var\" =~ /$2/$case) ? 1 : 0" });
 
180
    } elsif (/^(.*?)\s+(eq|ne)\s+(.*)$/) {
152
181
      #print STDERR "found as string cmp\n";
153
 
      push(@c, { var => lc($1), cmp => "(\"\$var\" $2 \"$3\") ? 1 : 0" });
154
 
    } elsif (/^(.*?)\s*=\s*(.*)$/) {
155
 
      #print STDERR "found as bare string regexp\n";
156
 
      push(@c, { var => lc($1), cmp => "(\"\$var\" =~ /$2/) ? 1 : 0" });
 
182
      my $var = lc($1); my $op = $2; my $val = $3;
 
183
      $val =~ s|^(['"])(.*)\1$|$2|;
 
184
      push(@c, { var => $var, cmp => "(\"\$var\" $op \"$val\") ? 1 : 0" });
 
185
      if ($var eq 'message_id' && $op eq "eq") {
 
186
        #print STDERR "short circuit @c[-1]->{cmp} $val\n";
 
187
        $G::msg_ids->{$val} = 1;
 
188
      }
157
189
    } elsif (/^(!)?(\S+)$/) {
158
190
      #print STDERR "found as boolean\n";
159
191
      push(@c, { var => lc($2), cmp => "($1\$var) ? 1 : 0" });
161
193
      print STDERR "Expression $_ did not parse\n";
162
194
      $e = 1;
163
195
    }
 
196
    # support the each_* psuedo variables.  Steal the criteria off of the
 
197
    # queue for special processing later
 
198
    if ($c[-1]{var} =~ /^each_(recipients(_(un)?del)?)$/) {
 
199
      my $var = $1;
 
200
      push(@G::recipients_crit,pop(@c));
 
201
      $G::recipients_crit[-1]{var} = $var; # remove each_ from the variable
 
202
    }
164
203
  }
165
204
 
166
205
  exit(1) if ($e);
167
206
 
 
207
  if ($G::show_rules) { foreach (@c) { print "$_->{var}\t$_->{cmp}\n"; } }
 
208
 
168
209
  return(\@c);
169
210
}
170
211
 
209
250
  $self->{_output_idonly}    = 0;
210
251
  $self->{_output_brief}     = 0;
211
252
  $self->{_output_flatq}     = 0;
212
 
  $self->{_show_vars}        = {};
 
253
  $self->{_show_vars}        = [];
213
254
 
214
255
  $self->_reset();
215
256
  return($self);
256
297
  my $s    = shift;
257
298
 
258
299
  foreach my $v (split(/\s*,\s*/, $s)) {
259
 
    $self->{_show_vars}{$v}++;
 
300
    push(@{$self->{_show_vars}}, $v);
260
301
  }
261
302
}
262
303
 
374
415
 
375
416
  # line 2
376
417
  chomp($_ = <I>);
377
 
  return(0) if (!/^(\S+)\s(\d+)\s(\d+)$/);
 
418
  return(0) if (!/^(.+)\s(\-?\d+)\s(\-?\d+)$/);
378
419
  $self->{_vars}{originator_login} = $1;
379
420
  $self->{_vars}{originator_uid}   = $2;
380
421
  $self->{_vars}{originator_gid}   = $3;
416
457
        $self->{_vars}{local_error_message} = 1;
417
458
      } elsif ($tag eq '-local_scan') {
418
459
        $self->{_vars}{local_scan_data} = $arg;
 
460
      } elsif ($tag eq '-spam_score_int') {
 
461
        $self->{_vars}{spam_score_int} = $arg;
 
462
        $self->{_vars}{spam_score}     = $arg / 10;
 
463
      } elsif ($tag eq '-bmi_verdicts') {
 
464
        $self->{_vars}{bmi_verdicts} = $arg;
 
465
      } elsif ($tag eq '-host_lookup_deferred') {
 
466
        $self->{_vars}{host_lookup_deferred} = 1;
419
467
      } elsif ($tag eq '-host_lookup_failed') {
420
468
        $self->{_vars}{host_lookup_failed} = 1;
421
469
      } elsif ($tag eq '-body_linecount') {
422
470
        $self->{_vars}{body_linecount} = $arg;
 
471
      } elsif ($tag eq '-body_zerocount') {
 
472
        $self->{_vars}{body_zerocount} = $arg;
423
473
      } elsif ($tag eq '-frozen') {
424
474
        $self->{_vars}{deliver_freeze} = 1;
425
475
        $self->{_vars}{deliver_frozen_at} = $arg;
 
476
      } elsif ($tag eq '-allow_unqualified_recipient') {
 
477
        $self->{_vars}{allow_unqualified_recipient} = 1;
 
478
      } elsif ($tag eq '-allow_unqualified_sender') {
 
479
        $self->{_vars}{allow_unqualified_sender} = 1;
426
480
      } elsif ($tag eq '-deliver_firsttime') {
427
481
        $self->{_vars}{deliver_firsttime} = 1;
428
482
        $self->{_vars}{first_delivery} = 1;
447
501
      } elsif ($tag eq '-interface_address') {
448
502
        $self->{_vars}{interface_port} = $self->_get_host_and_port(\$arg);
449
503
        $self->{_vars}{interface_address} = $arg;
 
504
      } elsif ($tag eq '-active_hostname') {
 
505
        $self->{_vars}{smtp_active_hostname} = $arg;
450
506
      } elsif ($tag eq '-host_auth') {
451
507
        $self->{_vars}{sender_host_authenticated} = $arg;
452
508
      } elsif ($tag eq '-host_name') {
501
557
      $self->{_recips}{$1} = { pno => $4, errors_to => $2 };
502
558
      $addr = $1;
503
559
    } elsif (/^.*#(\d+)$/) {
504
 
      print STDERR "exim4 #$1 style (unimplemented): $_\n";
 
560
      #print STDERR "exim4 #$1 style (unimplemented): $_\n";
505
561
      $self->_error("exim4 #$1 style (unimplemented): $_");
506
562
    } else {
507
563
      #print STDERR "default type: $_\n";
510
566
    }
511
567
    $self->{_udel_tree}{$addr} = 1 if (!$self->{_del_tree}{$addr});
512
568
  }
513
 
  $self->{_vars}{recipients} = join(', ', keys(%{$self->{_recips}}));
514
 
  $self->{_vars}{recipients_del} = join(', ', keys(%{$self->{_del_tree}}));
515
 
  $self->{_vars}{recipients_undel} = join(', ', keys(%{$self->{_udel_tree}}));
 
569
  $self->{_vars}{recipients}         = join(', ', keys(%{$self->{_recips}}));
 
570
  $self->{_vars}{recipients_del}     = join(', ', keys(%{$self->{_del_tree}}));
 
571
  $self->{_vars}{recipients_undel}   = join(', ', keys(%{$self->{_udel_tree}}));
 
572
  $self->{_vars}{recipients_undel_count} = scalar(keys(%{$self->{_udel_tree}}));
 
573
  $self->{_vars}{recipients_del_count}   = 0;
 
574
  foreach my $r (keys %{$self->{_del_tree}}) {
 
575
    next if (!$self->{_recips}{$r});
 
576
    $self->{_vars}{recipients_del_count}++;
 
577
  }
516
578
 
517
579
  # blank line
518
580
  $_ = <I>;
533
595
    my $bytes = $_;
534
596
    return(0) if (read(I, $_, $bytes) != $bytes);
535
597
    chomp(); # may regret this later
 
598
    $self->{_vars}{message_linecount} += scalar(split(/\n/)) if ($t ne '*');
536
599
    # build the $header_ variable, following exim's rules (sort of)
537
600
    if (/^([^ :]+):(.*)$/s) {
538
601
      my $v = "header_" . lc($1);
562
625
    $self->{_vars}{message_size} += $self->{_vars}{message_body_size} + 1;
563
626
  }
564
627
 
 
628
  $self->{_vars}{message_linecount} += $self->{_vars}{body_linecount};
 
629
 
 
630
  my $i = $self->{_vars}{message_size};
 
631
  if ($i == 0)              { $i = ""; }
 
632
  elsif ($i < 1024)         { $i = sprintf("%d", $i); }
 
633
  elsif ($i < 10*1024)      { $i = sprintf("%.1fK", $i / 1024); }
 
634
  elsif ($i < 1024*1024)    { $i = sprintf("%dK", ($i+512)/1024); }
 
635
  elsif ($i < 10*1024*1024) { $i = sprintf("%.1fM", $i/(1024*1024)); }
 
636
  else { $i = sprintf("%dM", ($i + 512 * 1024)/(1024*1024)); }
 
637
  $self->{_vars}{shown_message_size} = $i;
 
638
 
565
639
  return(1);
566
640
}
567
641
 
591
665
  return if ($self->{_delivered});
592
666
 
593
667
  if ($self->{_output_idonly}) {
594
 
    print $fh $self->{_message}, "\n";
 
668
    print $fh $self->{_message};
 
669
    foreach my $v (@{$self->{_show_vars}}) {
 
670
      print $fh " $v='", $self->get_var($v), "'";
 
671
    }
 
672
    print $fh "\n";
595
673
    return;
596
674
  }
597
675
 
603
681
      else { printf $fh "%2dh ", $i; }
604
682
    } else { printf $fh "%2dm ", $i; }
605
683
 
606
 
    $i = $self->{_vars}{message_size};
607
 
    if ($i == 0)              { $i = "     "; }
608
 
    elsif ($i < 1024)         { $i = sprintf("%5d", $i); }
609
 
    elsif ($i < 10*1024)      { $i = sprintf("%4.1fK", $i / 1024); }
610
 
    elsif ($i < 1024*1024)    { $i = sprintf("%4dK", ($i+512)/1024); }
611
 
    elsif ($i < 10*1024*1024) { $i = sprintf("%4.1fM", $i/(1024*1024)); }
612
 
    else { $i = sprintf("%4dM", ($i + 512 * 1024)/(1024*1024)); }
613
 
    print $fh "$i ";
 
684
    if ($self->{_output_flatq} && $self->{_show_vars}) {
 
685
        print $fh join(';',
 
686
                       map { "$_='".$self->get_var($_)."'" }
 
687
                           (@{$self->{_show_vars}})
 
688
                      );
 
689
    } else {
 
690
      printf $fh "%5s", $self->{_vars}{shown_message_size};
 
691
    }
 
692
    print $fh " ";
614
693
  }
615
694
  print $fh "$self->{_message} ";
616
695
  print $fh "From: " if ($self->{_output_brief});
624
703
    print $fh " *** frozen ***" if ($self->{_vars}{deliver_freeze});
625
704
    print $fh "\n";
626
705
 
627
 
    foreach my $v (keys(%{$self->{_show_vars}})) {
 
706
    foreach my $v (@{$self->{_show_vars}}) {
628
707
      printf $fh "  %25s = '%s'\n", $v, $self->get_var($v);
629
708
    }
630
709
 
645
724
      push(@r, $r);
646
725
    }
647
726
    print $fh " To: ", join(';', @r);
 
727
    if ($self->{_show_vars}) {
 
728
      print $fh " Vars: ", join(';',
 
729
                                map { "$_='".$self->get_var($_)."'" }
 
730
                                    (@{$self->{_show_vars}})
 
731
                               );
 
732
    }
648
733
  } elsif ($self->{_output_flatq}) {
649
734
    print $fh " *** frozen ***" if ($self->{_vars}{deliver_freeze});
650
735
    my @r = ();
711
796
 
712
797
=head1 DESCRIPTION
713
798
 
714
 
exipick is designed to display the contents of a Exim mail spool based on user-specified criteria.  It is designed to mimic the output of 'exim -bp' (or any of the other -bp* options) and Exim's spec.txt should be used to learn more about the exact format of the output.  The criteria are formed by creating comparisons against characteristics of the messages, for instance message_size, sender_helo_name, or message_headers.
 
799
exipick is designed to display the contents of a Exim mail spool based on user-specified criteria.  It is designed to mimic the output of 'exim -bp' (or any of the other -bp* options) and Exim's spec.txt should be used to learn more about the exact format of the output.  The criteria are formed by creating comparisons against characteristics of the messages, for instance $message_size, $sender_helo_name, or $message_headers.
715
800
 
716
801
=head1 OPTIONS
717
802
 
718
803
=over 4
719
804
 
720
 
=item -spool
721
 
 
722
 
The path to exim's spool directory.  In general usage the $spool variable in the script should automatically be set to your site's main spool directory, but this option is useful for alternate installs, or installs on NFS servers, etc.
723
 
 
724
 
=item -and
 
805
=item --spool
 
806
 
 
807
The path to Exim's spool directory.  In general usage you should set the $spool variable in the script to your site's main spool directory (and if exipick was installed from the Exim distribution, this is done by default), but this option is useful for alternate installs, or installs on NFS servers, etc.
 
808
 
 
809
=item --and
725
810
 
726
811
A message will be displayed only if it matches all of the specified criteria.  This is the default.
727
812
 
728
 
=item -or
 
813
=item --or
729
814
 
730
815
A message will be displayed if it matches any of the specified criteria.
731
816
 
 
817
=item --caseful
 
818
 
 
819
By default criteria using the '=' operator are caseless.  Specifying this option make them respect case.
 
820
 
 
821
=item --show-vars <variable>[,<variable>...]
 
822
 
 
823
Cause the value of each specified variable to be displayed for every message dispayed.  For instance, the command "exipick --show-vars '$sender_ident' 'sender_host_address eq 127.0.01'" will show the ident string for every message submitted via localhost.  How exactly the variable value is diplayed changes according to what output format you specify.
 
824
 
 
825
=item --show-rules
 
826
 
 
827
If specified the internal representation of each message criteria is shown.  This is primarily used for debugging purposes.
 
828
 
 
829
==item --show-tests
 
830
 
 
831
If specified, for every message (regardless of matching criteria) the criteria's actual value is shown and the compiled internal eval is shown.  This is used primarily for debugging purposes.
 
832
 
 
833
=item --flatq
 
834
 
 
835
Change format of output so that every message is on a single line.  Useful for parsing with tools such as sed, awk, cut, etc.
 
836
 
732
837
=item The -bp* options all control how much information is displayed and in what manner.  They all match the functionality of the options of the same name in Exim.  Briefly:
733
838
 
734
839
=item -bp   display the matching messages in 'mailq' format.
753
858
 
754
859
=item -r <regexp>  Same as '$recipients = <regexp>'
755
860
 
 
861
=item -s <string>  Same as '$shown_message_size eq <string>'
 
862
 
756
863
=item -y <seconds> Same as '$message_age < <seconds>'
757
864
 
758
865
=item -o <seconds> Same as '$message_age > <seconds>'
769
876
 
770
877
=item -b           Display brief format only
771
878
 
772
 
Please see the 'exiqgrep' documentation for more details on the behaviour and output format produced by these options.
 
879
Please see the 'exiqgrep' documentation for more details on the behaviour and output format produced by these options
773
880
 
774
881
=item <criterion>
775
882
 
776
 
The criteria are used to determine whether or not a given message should be displayed.  The criteria are built using variables containing information about the individual messages (see VARIABLES section for list and descriptions of available variables).  Each criterion is evaluated for each message in the spool and if all (by default) criteria match or (if -or option is specified) any criterion matches, the message is displayed.  See VARIABLE TYPES for explanation of types of variables and the evaluations that can be performed on them and EXAMPLES section for complete examples.
 
883
The criteria are used to determine whether or not a given message should be displayed.  The criteria are built using variables containing information about the individual messages (see VARIABLES section for list and descriptions of available variables).  Each criterion is evaluated for each message in the spool and if all (by default) criteria match or (if --or option is specified) any criterion matches, the message is displayed.  See VARIABLE TYPES for explanation of types of variables and the evaluations that can be performed on them and EXAMPLES section for complete examples.
777
884
 
778
885
The format of a criterion is explained in detail below, but a key point to make is that the variable being compared must always be on the left side of the comparison.
779
886
 
780
 
If no criteria are provided all messages in the queue are displayed (in this case the output of exipick should be identical to the output of 'exim -bp').
 
887
If no criteria are provided all messages in the queue are displayed (in this case the output of exipick should be identical to the output of 'exim -bp')
781
888
 
782
889
=item --help
783
890
 
799
906
 
800
907
Variable of the numeric type can be of integer or float.  Valid comparisons are <, <=, >, >=, ==, and !=.
801
908
 
802
 
The numbers specified in the criteria can have a suffix of d, h, m, s, M, K, or B, in which case the number will be mulitplied by 86400, 3600, 60, 1, 1048576, 1024, or 1 respectively.  These suffixes are case sensitive.  While these are obviously designed to aid in date and size calculations, they are not restricted to variables of their respective types.
 
909
The numbers specified in the criteria can have a suffix of d, h, m, s, M, K, or B, in which case the number will be mulitplied by 86400, 3600, 60, 1, 1048576, 1024, or 1 respectively.  These suffixes are case sensitive.  While these are obviously designed to aid in date and size calculations, they are not restricted to variables of their respective types.  That is, though it's odd it's legal to create a criterion of a message being around for 3 kiloseconds: '$message_age >= 3K'.
803
910
 
804
911
=item BOOLEAN
805
912
 
806
 
Variables of the boolean type are very easy to use in criteria.  The format is either the variable by itself or the variable negated with a ! sign.  For instance, 'deliver_freeze' matches if the message in question is frozen, '!deliver_freeze' matches if message is not frozen.
 
913
Variables of the boolean type are very easy to use in criteria.  The format is either the variable by itself or the variable negated with a ! sign.  For instance, '$deliver_freeze' matches if the message in question is frozen, '!$deliver_freeze' matches if message is not frozen.
807
914
 
808
915
=item STRING
809
916
 
810
 
String variables are basically defined as those that are neither numeric nor boolean and can contain any data.  There are several types of comparisons that can be made against string variables.  With the exception of '=', the operators all match the functionality of the like-named perl operators.
811
 
 
812
 
The simplest form is a bare string regular expression, represented by the operator '='.  The value used for the comparison will be evaluated as a regular expression and can be as simple or as complex as desired.  For instance 'sender_helo_name = example' on the simple end or 'sender_helo_name = ^aol\.com$ on the more complex end.
813
 
 
814
 
Slightly more complex is the string comparison with the operators 'eq' and 'ne' for equal and not equal, respectively.  'sender_helo_name eq hotmail.com' is true for messages with the exact helo string "hotmail.com", while 'sender_helo_name ne hotmail.com' is true for any message any helo string other than hotmail.com.
815
 
 
816
 
The most complex and the most flexible format are straight regular expressions with the operators =~ and !~.  The value in the criteria is expected to be a correctly formatted perl regular expression B<including the regexp delimiters (usually //)>.  The criterion 'sender_helo_name !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/' matches for any message which does not have an IP address for its helo string.
 
917
String variables are basically defined as those that are neither numeric nor boolean and can contain any data.  The string operators are =, eq, ne, =~, and !~.  With the exception of '=', the operators all match the functionality of the like-named perl operators.
 
918
 
 
919
The simplest form is a bare string regular expression, represented by the operator '='.  The value used for the comparison will be evaluated as a regular expression and can be as simple or as complex as desired.  For instance '$sender_helo_name = example' on the simple end or '$sender_helo_name = ^aol\.com$' on the more complex end.  This comparison is caseless by default, but see the --caseful option to change this.
 
920
 
 
921
Slightly more complex is the string comparison with the operators 'eq' and 'ne' for equal and not equal, respectively.  '$sender_helo_name eq hotmail.com' is true for messages with the exact helo string "hotmail.com", while '$sender_helo_name ne hotmail.com' is true for any message with a helo string other than "hotmail.com".
 
922
 
 
923
The most complex and the most flexible format are straight regular expressions with the operators '=~' and '!~'.  The value in the criteria is expected to be a correctly formatted perl regular expression B<including the regexp delimiters (usually //)>.  The criterion '$sender_helo_name !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/' matches for any message which does not have an IP address for its helo string.
817
924
 
818
925
=back
819
926
 
820
927
=head1 VARIABLES
821
928
 
822
 
With a few exceptions the available variables match Exim's internal expansion variables in both name and exact contents.  There are a few notable additions and format deviations which are noted below.  Although a brief explanation is offered below, Exim's spec.txt should be consulted for full details.  It is important to remember that not every variable will be defined for every message.  For example, sender_host_port is not defined for messages not received from a remote host.
 
929
With a few exceptions the available variables match Exim's internal expansion variables in both name and exact contents.  There are a few notable additions and format deviations which are noted below.  Although a brief explanation is offered below, Exim's spec.txt should be consulted for full details.  It is important to remember that not every variable will be defined for every message.  For example, $sender_host_port is not defined for messages not received from a remote host.
823
930
 
824
 
In the list below, '.' denotes standard messages with contentes matching Exim's variable, '#' denotes standard variables with non-standard contents, and '+' denotes a non-standard variable.
 
931
In the list below, '.' denotes standard messages with contents matching Exim's variable, '#' denotes standard variables with non-standard contents, and '+' denotes a non-standard variable.
825
932
 
826
933
=head2 Boolean variables
827
934
 
828
935
=over 4
829
936
 
830
 
=item + deliver_freeze
831
 
 
832
 
TRUE if the message is frozen.
833
 
 
834
 
=item . first_delivery
835
 
 
836
 
TRUE if the message has not been deferred.
837
 
 
838
 
=item . manually_thawed
 
937
=item + $allow_unqualified_recipient
 
938
 
 
939
TRUE if unqualified recipient addresses are permitted in header lines.
 
940
 
 
941
=item + $allow_unqualified_sender
 
942
 
 
943
TRUE if unqualified sender addresses are permitted in header lines.
 
944
 
 
945
=item + $deliver_freeze
 
946
 
 
947
TRUE if the message is currently frozen.
 
948
 
 
949
=item . $first_delivery
 
950
 
 
951
TRUE if the message has never been deferred.
 
952
 
 
953
=item . $manually_thawed
839
954
 
840
955
TRUE when the message has been manually thawed.
841
956
 
842
 
=item + dont_deliver
 
957
=item + $dont_deliver
843
958
 
844
959
TRUE if, under normal circumstances, Exim will not try to deliver the message.
845
960
 
846
 
=item . host_lookup_failed
847
 
 
848
 
TRUE if there was an attempt to look up the host's name from its IP address, but the attempt failed.
849
 
 
850
 
=item + local_error_message
 
961
=item . $host_lookup_deferred
 
962
 
 
963
TRUE if there was an attempt to look up the host's name from its IP address, but an error occurred that during the attempt.
 
964
 
 
965
=item . $host_lookup_failed
 
966
 
 
967
TRUE if there was an attempt to look up the host's name from its IP address, but the attempt returned a negative result.
 
968
 
 
969
=item + $local_error_message
851
970
 
852
971
TRUE if the message is a locally-generated error message.
853
972
 
854
 
=item + sender_local
 
973
=item + $sender_local
855
974
 
856
975
TRUE if the message was locally generated.
857
976
 
858
 
=item + sender_set_untrusted
 
977
=item + $sender_set_untrusted
859
978
 
860
979
TRUE if the envelope sender of this message was set by an untrusted local caller.
861
980
 
862
 
=item . tls_certificate_verified
 
981
=item . $tls_certificate_verified
863
982
 
864
983
TRUE if a TLS certificate was verified when the message was received.
865
984
 
869
988
 
870
989
=over 4
871
990
 
872
 
=item . body_linecount
 
991
=item . $body_linecount
873
992
 
874
993
The number of lines in the message's body.
875
994
 
876
 
=item + deliver_frozen_at
 
995
=item . $body_zerocount
 
996
 
 
997
The number of binary zero bytes in the message's body.
 
998
 
 
999
=item + $deliver_frozen_at
877
1000
 
878
1001
The epoch time at which message was frozen.
879
1002
 
880
 
=item . interface_port
 
1003
=item . $interface_port
881
1004
 
882
1005
The local port number if network-originated messages.
883
1006
 
884
 
=item . message_age
 
1007
=item . $message_age
885
1008
 
886
1009
The number of seconds since the message was received.
887
1010
 
888
 
=item . message_body_size
 
1011
=item . $message_body_size
889
1012
 
890
1013
The size of the body in bytes.
891
1014
 
892
 
=item . message_size
 
1015
=item . $message_linecount
 
1016
 
 
1017
The number of lines in the entire message (body and headers).
 
1018
 
 
1019
=item . $message_size
893
1020
 
894
1021
The size of the message in bytes.
895
1022
 
896
 
=item . originator_gid
 
1023
=item . $originator_gid
897
1024
 
898
1025
The group id under which the process that called Exim was running as when the message was received.
899
1026
 
900
 
=item . originator_uid
 
1027
=item . $originator_uid
901
1028
 
902
1029
The user id under which the process that called Exim was running as when the message was received.
903
1030
 
904
 
=item . received_count
 
1031
=item . $received_count
905
1032
 
906
1033
The number of Received: header lines in the message.
907
1034
 
908
 
=item + received_time
 
1035
=item . $received_time
909
1036
 
910
1037
The epoch time at which the message was received.
911
1038
 
912
 
=item . recipients_count
913
 
 
914
 
The number of envelope recipients that came with the message.
915
 
 
916
 
=item . sender_host_port
 
1039
=item . $recipients_count
 
1040
 
 
1041
The number of envelope recipients for the message.
 
1042
 
 
1043
=item + $recipients_del_count
 
1044
 
 
1045
The number of envelope recipients for the message which have already been delivered.  Note that this is the count of original recipients to which the message has been delivered.  It does not include generated addresses so it is possible that this number will be less than the number of addresses in the recipients_del string.
 
1046
 
 
1047
=item + $recipients_undel_count
 
1048
 
 
1049
The number of envelope recipients for the message which have not yet been delivered.
 
1050
 
 
1051
=item . $sender_host_port
917
1052
 
918
1053
The port number that was used on the remote host for network-originated messages.
919
1054
 
920
 
=item + warning_count
 
1055
=item + $warning_count
921
1056
 
922
1057
The number of delay warnings which have been sent for this message.
923
1058
 
927
1062
 
928
1063
=over 4
929
1064
 
930
 
=item . acl_c0-acl_c9, acl_m0-acl_m9
 
1065
=item . $acl_c0-$acl_c9, $acl_m0-$acl_m9
931
1066
 
932
1067
User definable variables.
933
1068
 
934
 
=item . authenticated_id
 
1069
=item . $authenticated_id
935
1070
 
936
1071
Optional saved information from authenticators, or the login name of the calling process for locally submitted messages.
937
1072
 
938
 
=item . authenticated_sender
 
1073
=item . $authenticated_sender
939
1074
 
940
1075
The value of AUTH= param for smtp messages, or a generated value from the calling processes login and qualify domain for locally submitted messages.
941
1076
 
942
 
=item # header_*
 
1077
=item + $bmi_verdicts
 
1078
 
 
1079
I honestly don't know what the format of this variable is.  It only exists if you have Exim compiled with WITH_CONTENT_SCAN and EXPERIMENTAL_BRIGHTMAIL (and, you know, pay Symantec/Brightmail a bunch of money for the client libs and a server to use them with).
 
1080
 
 
1081
=item + $each_recipients
 
1082
 
 
1083
This is a psuedo variable which allows you to apply a criterion against each address in $recipients individually.  This allows you to create criteria against which every individual recipient is tested.  For instance, '$recipients =~ /aol.com/' will match if any of the recipient addresses contain the string "aol.com".  However, with the criterion '$each_recipients =~ /@aol.com$/', a message will only match if B<every> recipient matches that pattern.  Note that this obeys --and or --or being set.  Using it with --or is very similar to just matching against $recipients, but with the added benefit of being able to use anchors at the beginning and end of each recipient address.
 
1084
 
 
1085
=item + $each_recipients_del
 
1086
 
 
1087
Like $each_recipients, but for the $recipients_del variable.
 
1088
 
 
1089
=item + $each_recipients_undel
 
1090
 
 
1091
Like $each_recipients, but for the $recipients_undel variable.
 
1092
 
 
1093
=item # $header_*
943
1094
 
944
1095
The value of the same named message header, for example header_to or header_reply-to.  These variables are really closer to Exim's rheader_* variables, with the exception that leading and trailing space is removed.
945
1096
 
946
 
=item . interface_address
 
1097
=item . $interface_address
947
1098
 
948
1099
The address of the local IP interface for network-originated messages.
949
1100
 
950
 
=item . local_scan_data
 
1101
=item . $local_scan_data
951
1102
 
952
1103
The text returned by the local_scan() function when a message is received.
953
1104
 
954
 
=item # message_body
 
1105
=item # $message_body
955
1106
 
956
1107
The message's body.  Unlike Exim's variable of the same name, this variable contains the entire message body.  The logic behind this is that the message body is not read unless it is specifically referenced, so under normal circumstances it is not a penalty, but when you need the entire body you need the entire body.  Like Exim's copy, newlines and nulls are replaced by spaces.
957
1108
 
958
 
=item . message_headers
 
1109
=item . $message_headers
959
1110
 
960
1111
A concatenation of all the header lines except for lines added by routers or transports.
961
1112
 
962
 
=item . message_id
 
1113
=item . $message_id
963
1114
 
964
1115
The unique message id that is used by Exim to identify the message.
965
1116
 
966
 
=item + originator_login
 
1117
=item + $originator_login
967
1118
 
968
1119
The login of the process which called Exim.
969
1120
 
970
 
=item . received_protocol
 
1121
=item . $received_protocol
971
1122
 
972
1123
The name of the protocol by which the message was received.
973
1124
 
974
 
=item # recipients
 
1125
=item # $recipients
975
1126
 
976
1127
The list of envelope recipients for a message.  Unlike Exim's version, this variable always contains every envelope recipient of the message.  The recipients are separated by a comma and a space.
977
1128
 
978
 
=item + recipients_del
979
 
 
980
 
The list of delivered envelope recipients for a message.  This non-standard variable is in the same format as recipients and contains the list of already-delivered recipients.
981
 
 
982
 
=item + recipients_undel
 
1129
=item + $recipients_del
 
1130
 
 
1131
The list of delivered envelope recipients for a message.  This non-standard variable is in the same format as recipients and contains the list of already-delivered recipients including any generated addresses.
 
1132
 
 
1133
=item + $recipients_undel
983
1134
 
984
1135
The list of undelivered envelope recipients for a message.  This non-standard variable is in the same format as recipients and contains the list of undelivered recipients.
985
1136
 
986
 
=item . reply_address
 
1137
=item . $reply_address
987
1138
 
988
1139
The contents of the Reply-To: header line if one exists and it is not empty, or otherwise the contents of the From: header line.
989
1140
 
990
 
=item . sender_address
 
1141
=item . $sender_address
991
1142
 
992
1143
The sender's address that was received in the message's envelope.  For bounce messages, the value of this variable is the empty string.
993
1144
 
994
 
=item . sender_address_domain
995
 
 
996
 
The domain part of sender_address.
997
 
 
998
 
=item . sender_address_local_part
999
 
 
1000
 
The local part of sender_address.
1001
 
 
1002
 
=item . sender_helo_name
 
1145
=item . $sender_address_domain
 
1146
 
 
1147
The domain part of $sender_address.
 
1148
 
 
1149
=item . $sender_address_local_part
 
1150
 
 
1151
The local part of $sender_address.
 
1152
 
 
1153
=item . $sender_helo_name
1003
1154
 
1004
1155
The HELO or EHLO value supplied for smtp or bsmtp messages.
1005
1156
 
1006
 
=item . sender_host_address
 
1157
=item . $sender_host_address
1007
1158
 
1008
1159
The remote host's IP address.
1009
1160
 
1010
 
=item . sender_host_authenticated
 
1161
=item . $sender_host_authenticated
1011
1162
 
1012
1163
The name of the authenticator driver which successfully authenticated the client from which the message was received.
1013
1164
 
1014
 
=item . sender_host_name
 
1165
=item . $sender_host_name
1015
1166
 
1016
1167
The remote host's name as obtained by looking up its IP address.
1017
1168
 
1018
 
=item . sender_ident
 
1169
=item . $sender_ident
1019
1170
 
1020
1171
The identification received in response to an RFC 1413 request for remote messages, the login name of the user that called Exim for locally generated messages.
1021
1172
 
1022
 
=item . tls_cipher
 
1173
=item + $shown_message_size
 
1174
 
 
1175
This non-standard variable contains the formatted size string.  That is, for a message whose $message_size is 66566 bytes, $shown_message_size is 65K.
 
1176
 
 
1177
=item . $smtp_active_hostname
 
1178
 
 
1179
The value of the active host name when the message was received, as specified by the "smtp_active_hostname" option.
 
1180
 
 
1181
=item . $spam_score
 
1182
 
 
1183
The spam score of the message, for example '3.4' or '30.5'.  (Requires exiscan or WITH_CONTENT_SCAN)
 
1184
 
 
1185
=item . $spam_score_int
 
1186
 
 
1187
The spam score of the message, multiplied by ten, as an integer value.  For instance '34' or '305'.  (Requires exiscan or WITH_CONTENT_SCAN)
 
1188
 
 
1189
=item . $tls_cipher
1023
1190
 
1024
1191
The cipher suite that was negotiated for encrypted SMTP connections.
1025
1192
 
1026
 
=item . tls_peerdn
 
1193
=item . $tls_peerdn
1027
1194
 
1028
1195
The value of the Distinguished Name of the certificate if Exim is configured to request one.
1029
1196
 
1033
1200
 
1034
1201
=over 4
1035
1202
 
1036
 
=item exipick 'deliver_freeze'
 
1203
=item exipick '$deliver_freeze'
1037
1204
 
1038
1205
Display only frozen messages.
1039
1206
 
1040
 
=item exipick 'received_protocol eq asmtp' 'message_age < 20m'
1041
 
 
1042
 
Display only messages wich were delivered over an authenticated smtp session in the last 20 minutes.
1043
 
 
1044
 
=item exipick -bpc 'message_size > 200K'
 
1207
=item exipick '$received_protocol eq asmtp' '$message_age < 20m'
 
1208
 
 
1209
Display only messages which were delivered over an authenticated smtp session in the last 20 minutes.
 
1210
 
 
1211
=item exipick -bpc '$message_size > 200K'
1045
1212
 
1046
1213
Display a count of messages in the queue which are over 200 kilobytes in size.
1047
1214
 
1048
 
=item exipick -or 'sender_helo_name =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/' 'sender_helo_name = _'
 
1215
=item exipick -or '$sender_helo_name =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/' '$sender_helo_name = _'
1049
1216
 
1050
1217
Display message which have a HELO string which either is an IP address or contains an underscore.
1051
1218
 
1053
1220
 
1054
1221
=head1 REQUIREMENTS
1055
1222
 
1056
 
None that I know of, except an Exim installation.
 
1223
None that I know of, except an Exim installation.  Your life will also be a lot easier if you set $spool at the top of the script to your install's spool directory (assuming this was not done automatically by the Exim install process).
1057
1224
 
1058
1225
=head1 ACKNOWLEDGEMENTS
1059
1226