line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# $Id: DCCIf.pm,v 1.4 2004/02/11 14:36:48 matt Exp $ |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Net::DCCIf; |
4
|
1
|
|
|
1
|
|
6779
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
36
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
791
|
use IO::Socket; |
|
1
|
|
|
|
|
33392
|
|
|
1
|
|
|
|
|
5
|
|
7
|
1
|
|
|
1
|
|
493
|
use Socket qw(:crlf inet_ntoa); |
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
303
|
|
8
|
1
|
|
|
1
|
|
1060
|
use Fatal qw(open close); |
|
1
|
|
|
|
|
17068
|
|
|
1
|
|
|
|
|
8
|
|
9
|
1
|
|
|
1
|
|
1083
|
use Symbol qw(gensym); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
67
|
|
10
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
5
|
use vars qw($VERSION); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
1755
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
$VERSION = '0.02'; |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
my %result_map = ( |
16
|
|
|
|
|
|
|
A => 'Accept', |
17
|
|
|
|
|
|
|
R => 'Reject', |
18
|
|
|
|
|
|
|
S => 'Accept Some', |
19
|
|
|
|
|
|
|
T => 'Temporary Failure', |
20
|
|
|
|
|
|
|
); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub new { |
23
|
0
|
|
|
0
|
1
|
|
my $class = shift; |
24
|
|
|
|
|
|
|
|
25
|
0
|
|
|
|
|
|
return bless {}, $class; |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
sub connect { |
29
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
30
|
0
|
|
|
|
|
|
my %opts = @_; |
31
|
|
|
|
|
|
|
|
32
|
0
|
|
|
|
|
|
%$self = (); # clear out self in case its being re-used. |
33
|
|
|
|
|
|
|
|
34
|
0
|
|
0
|
|
|
|
$opts{homedir} ||= $self->{homedir} || '/var/dcc'; |
|
|
|
0
|
|
|
|
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# this slightly odd logic copied from the original dccif.pl |
37
|
0
|
0
|
|
|
|
|
if ($opts{clnt_addr}) { |
|
|
0
|
|
|
|
|
|
38
|
0
|
0
|
|
|
|
|
inet_aton($opts{clnt_addr}) || die "Client address lookup failed: $!"; |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
elsif ($opts{clnt_name}) { |
41
|
0
|
|
0
|
|
|
|
$opts{clnt_addr} = inet_ntoa(scalar(gethostbyname($opts{clnt_name}))) |
42
|
|
|
|
|
|
|
|| die "Cannot resolve domain name $opts{clnt_name}: $!"; |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
else { |
45
|
0
|
|
|
|
|
|
$opts{clnt_name} = ''; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
0
|
|
0
|
|
|
|
my $server = IO::Socket::UNIX->new( |
49
|
|
|
|
|
|
|
Type => SOCK_STREAM, |
50
|
|
|
|
|
|
|
Peer => "$opts{homedir}/dccifd", |
51
|
|
|
|
|
|
|
) || die "Socket connect failed ($opts{homedir}/dccifd): $!"; |
52
|
|
|
|
|
|
|
|
53
|
0
|
|
|
|
|
|
$self->{server} = $server; |
54
|
0
|
|
|
|
|
|
$self->{homedir} = $opts{homedir}; |
55
|
|
|
|
|
|
|
|
56
|
0
|
|
|
|
|
|
my @options; |
57
|
0
|
0
|
|
|
|
|
if ($opts{known_spam}) { |
58
|
0
|
|
|
|
|
|
push @options, "spam"; |
59
|
|
|
|
|
|
|
} |
60
|
0
|
0
|
|
|
|
|
if ($opts{output_body}) { |
61
|
0
|
|
|
|
|
|
push @options, "body"; |
62
|
|
|
|
|
|
|
} |
63
|
0
|
0
|
|
|
|
|
if ($opts{output_header}) { |
64
|
0
|
|
|
|
|
|
push @options, "header"; |
65
|
|
|
|
|
|
|
} |
66
|
0
|
0
|
|
|
|
|
if ($opts{query_only}) { |
67
|
0
|
|
|
|
|
|
push @options, "query"; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
0
|
|
|
|
|
|
$self->send("opts", join(" ", @options), LF); |
71
|
|
|
|
|
|
|
|
72
|
0
|
|
|
|
|
|
$self->send("clnt helo env_from", |
73
|
|
|
|
|
|
|
$opts{clnt_addr}, CR, $opts{clnt_name}, LF, |
74
|
|
|
|
|
|
|
$opts{helo}, LF, |
75
|
|
|
|
|
|
|
$opts{env_from}, LF, |
76
|
|
|
|
|
|
|
); |
77
|
|
|
|
|
|
|
|
78
|
0
|
0
|
|
|
|
|
if (!ref($opts{env_to})) { |
79
|
0
|
0
|
|
|
|
|
$opts{env_to} = $opts{env_to} ? [$opts{env_to}] : []; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
0
|
|
|
|
|
|
$self->{env_to} = $opts{env_to}; |
83
|
|
|
|
|
|
|
|
84
|
0
|
|
|
|
|
|
foreach my $env_to (@{$opts{env_to}}) { |
|
0
|
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
$self->send("env_to", $env_to, LF); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
0
|
|
|
|
|
|
$self->send("end of env_tos", LF); |
89
|
|
|
|
|
|
|
|
90
|
0
|
|
|
|
|
|
return $self; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub dcc_file { |
94
|
0
|
|
|
0
|
1
|
|
my ($self, $file) = @_; |
95
|
|
|
|
|
|
|
|
96
|
0
|
|
|
|
|
|
my $fh = gensym(); |
97
|
0
|
|
|
|
|
|
open($fh, $file); |
98
|
|
|
|
|
|
|
|
99
|
0
|
|
|
|
|
|
return $self->dcc_fh($fh); |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub dcc_fh { |
103
|
0
|
|
|
0
|
1
|
|
my ($self, $fh) = @_; |
104
|
|
|
|
|
|
|
|
105
|
0
|
|
|
|
|
|
my $buf; |
106
|
0
|
|
|
|
|
|
while (1) { |
107
|
0
|
|
|
|
|
|
my $i = sysread($fh, $buf, 8192); |
108
|
0
|
0
|
|
|
|
|
die "sysread file handle failed: $!" unless defined($i); |
109
|
0
|
0
|
|
|
|
|
last unless $i; |
110
|
0
|
|
|
|
|
|
$self->send("body", $buf); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
0
|
|
|
|
|
|
return $self->get_results(); |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub send { |
117
|
0
|
|
|
0
|
1
|
|
my ($self, $type, @data) = @_; |
118
|
|
|
|
|
|
|
# warn("send $type:", join('', @data)) if $type ne 'body'; |
119
|
0
|
0
|
|
|
|
|
$self->{server}->syswrite(join('', @data)) || die "socket write failed at $type: $!"; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub get_results { |
123
|
0
|
|
|
0
|
1
|
|
my ($self) = @_; |
124
|
|
|
|
|
|
|
|
125
|
0
|
0
|
|
|
|
|
if ($self->{results}) { |
126
|
0
|
|
|
|
|
|
return @{$self->{results}}; |
|
0
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
0
|
0
|
|
|
|
|
$self->{server}->shutdown(1) || die "socket shutdown failed: $!"; |
130
|
0
|
|
0
|
|
|
|
my $result = $self->{server}->getline || die "socket read failed: $!"; |
131
|
0
|
|
0
|
|
|
|
my $oks = $self->{server}->getline || die "socket read failed: $!"; |
132
|
0
|
|
|
|
|
|
chomp($result); chomp($oks); |
|
0
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
|
134
|
0
|
|
|
|
|
|
$result = $result_map{$result}; |
135
|
0
|
|
|
|
|
|
my @ok_map; |
136
|
0
|
|
|
|
|
|
foreach my $env_to (@{$self->{env_to}}) { |
|
0
|
|
|
|
|
|
|
137
|
0
|
|
|
|
|
|
my $val = substr($oks, 0, 1, ''); |
138
|
0
|
|
|
|
|
|
push @ok_map, $env_to, $result_map{$val}; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
|
$self->{results} = [ $result, @ok_map ]; |
142
|
0
|
|
|
|
|
|
return( $result, @ok_map ); |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub get_output { |
146
|
0
|
|
|
0
|
1
|
|
my ($self, %opts) = @_; |
147
|
|
|
|
|
|
|
|
148
|
0
|
|
|
|
|
|
my $output_fh = $opts{output_fh}; |
149
|
0
|
0
|
|
|
|
|
if (!$output_fh) { |
150
|
0
|
0
|
|
|
|
|
if ($opts{output_file}) { |
151
|
0
|
|
|
|
|
|
$output_fh = gensym(); |
152
|
0
|
|
|
|
|
|
open($output_fh, ">" . $self->{output_file}); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
0
|
|
|
|
|
|
my $ret = ''; |
157
|
0
|
|
|
|
|
|
my $buf; |
158
|
0
|
|
|
|
|
|
while (1) { |
159
|
0
|
|
|
|
|
|
my $i = $self->{server}->read($buf, 8192); |
160
|
0
|
0
|
|
|
|
|
die "read socket failed: $!" unless defined($i); |
161
|
0
|
0
|
|
|
|
|
last unless $i; |
162
|
0
|
0
|
|
|
|
|
if ($output_fh) { |
163
|
0
|
0
|
|
|
|
|
print $output_fh ($buf) or die "write output filehandle failed: $!"; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
else { |
166
|
0
|
|
|
|
|
|
$ret .= $buf; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
0
|
|
|
|
|
|
return $ret; |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub disconnect { |
174
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
175
|
0
|
|
|
|
|
|
delete $self->{server}; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
1; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
=head1 NAME |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
Net::DCCIf - Interface to the DCC daemon |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=head1 SYNOPSIS |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
my $dcc = Net::DCCIf->new(); |
187
|
|
|
|
|
|
|
$dcc->connect(); |
188
|
|
|
|
|
|
|
my ($results, $oks) = $dcc->dcc_file("test.eml"); |
189
|
|
|
|
|
|
|
$dcc->disconnect(); |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=head1 DESCRIPTION |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
This module is a simple interface to the Distributed Checksum Clearinghouse |
194
|
|
|
|
|
|
|
daemon (dccifd). It is a simpler replacement for the F script that |
195
|
|
|
|
|
|
|
dcc ships with, making usage more perlish (though probably at the expense of |
196
|
|
|
|
|
|
|
a slight performance drop). |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=head1 API |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
The API is intentionally simple. Hopefully it allows enough flexibility to |
201
|
|
|
|
|
|
|
support everything needed, however if not there may be some advantages to |
202
|
|
|
|
|
|
|
sticking with F from the DCC distribution. |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=head2 C<< Net::DCCIf->new() >> |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
This constructs a new Net::DCCIf object. It takes no options, and will always |
207
|
|
|
|
|
|
|
return a valid object unless there is an out of memory error. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=head2 C<< $dcc->connect(%options) >> |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
Attempt to connect to the local unix domain socket. By default this domain |
212
|
|
|
|
|
|
|
socket is expected to be at F, however you can override |
213
|
|
|
|
|
|
|
this with the C option. If the connection fails for any reason |
214
|
|
|
|
|
|
|
then an exception will be thrown detailing the error. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
Returns the object, to facilitate method chaining. |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
B |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=over 4 |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=item C<< env_from => $from >> |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
The envelope from address (C data). |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=item C<< env_to => \@env_tos >> |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
The envelope to addresses as an array reference (C data). |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
B<< WARNING: >> if you pass an empty list here then DCC will assume |
231
|
|
|
|
|
|
|
zero recipients and not increment the counter for this email (equivalent |
232
|
|
|
|
|
|
|
to doing a C<< query_only >> lookup). |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=item C<< helo => $helo >> |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
The HELO line. |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=item C<< homedir => $dir >> |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Specifies the location of the C unix domain socket. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=item C<< clnt_addr => $addr >> |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Specifies the IP address of the connecting server. If this is an invalid |
245
|
|
|
|
|
|
|
address then an exception will be thrown. |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=item C<< clnt_name => $name >> |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
Specifies the host name of the connecting server. If the C is |
250
|
|
|
|
|
|
|
specified, but C is not, then a hostname lookup will be |
251
|
|
|
|
|
|
|
performed to try and determine the IP address. If this lookup fails an |
252
|
|
|
|
|
|
|
exception will be thrown. |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=item C<< known_spam => 1 >> |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
Specifies that we already know this email is spam (i.e. it came in to |
257
|
|
|
|
|
|
|
a spamtrap address) and so we let the DCC server know about it. |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=item C<< output_body => 1 >> |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
Makes L<< get_output()|/$dcc->get_output(%options) >> return the full body of the email with |
262
|
|
|
|
|
|
|
a header added to it. |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=item C<< output_header => 1 >> |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
Makes L<< get_output()|/$dcc->get_output(%options) >> return just a header line. |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=item C<< query_only => 1 >> |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
Issues a query only, rather than first incrementing the database and then |
271
|
|
|
|
|
|
|
querying. |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=back |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=head2 C<< $dcc->dcc_file($filename) >> |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
Opens the file and calls L<< dcc_fh()|/$dcc->dcc_fh($fh) >> on the resulting filehandle. |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
Returns C<($result, @mappings)>. See L below. |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head2 C<< $dcc->dcc_fh($fh) >> |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Sends the contents of the filehandle to the dcc server. |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
Returns C<($result, @mappings)>. See L below. |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
=head2 C<< $dcc->send($type, @data) >> |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
Sends raw text data to the dcc server. The type is usually one of C<"header"> or |
290
|
|
|
|
|
|
|
C<"body">, and is used in error messages if there is a problem sending the |
291
|
|
|
|
|
|
|
data. |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
Use this method B any calls to C or C. Using it after |
294
|
|
|
|
|
|
|
may result in an error or unexpected results. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head2 C<< $dcc->get_results() >> |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Following sending the email via C you have to manually extract the |
299
|
|
|
|
|
|
|
results (these are the same results as returned by C and C |
300
|
|
|
|
|
|
|
above). |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=head2 C<< $dcc->get_output(%options) >> |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
This method returns the header or body from the dcc server that resulted from |
305
|
|
|
|
|
|
|
running dcc on the data. The output depends on the values of the C |
306
|
|
|
|
|
|
|
or C options passed in the C call. |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
Returns the data as a string unless the C or C options |
309
|
|
|
|
|
|
|
are set. |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
B |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=over 4 |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=item C<< output_fh => $fh >> |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
A filehandle to send the output to. If you wish the output to go to STDOUT, you can |
318
|
|
|
|
|
|
|
pass it with C<< $dcc->get_output(output_fh => \*STDOUT) >>. |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
This option overrides any setting for C. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=item C<< output_file => $file >> |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
A filename to send the output to, as with C above. |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=back |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=head2 C<< $dcc->disconnect() >> |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
Disconnect from the dccifd server and cleanup. |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=head1 Results |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
The results returned from C, C and C above are a |
335
|
|
|
|
|
|
|
list of values: C<($action, @mappings)>. |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
The C<$action> value is one of: |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=over 4 |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=item "Accept" |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=item "Reject" |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=item "Reject Some" |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=item "Temporary Failure" |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=back |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
The C<@mappings> value is a list of envelope to addresses followed by the action |
352
|
|
|
|
|
|
|
that should be taken for that address. It is often easier to map this to a hash: |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
my ($action, %mappings) = $dcc->get_results(); |
355
|
|
|
|
|
|
|
print "Action: $action\n"; |
356
|
|
|
|
|
|
|
print "Matt Sergeant action: " . $mappings{'matt@sergeant.org'} . "\n"; |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
This should only have differing values in it should the primary action be |
359
|
|
|
|
|
|
|
"Reject Some", otherwise the values will all be the same as C<$action>. |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
Ordering of the mappings will be the same as the order of C addresses |
362
|
|
|
|
|
|
|
passed to C above. Note that this ordering will be lost if you |
363
|
|
|
|
|
|
|
map it to a hash. |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=head1 Exceptions |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
This module throws exceptions for all errors. In order to catch these errors |
368
|
|
|
|
|
|
|
without having your program exit you can use the C construct: |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
my $dcc = Net::DCCIf->new(); |
371
|
|
|
|
|
|
|
eval { |
372
|
|
|
|
|
|
|
$dcc->connect(); |
373
|
|
|
|
|
|
|
my ($results, %mapping) = $dcc->dcc_file("test.eml"); |
374
|
|
|
|
|
|
|
print "Results: $results\n"; |
375
|
|
|
|
|
|
|
print "Recipients: $_ => $mapping{$_}\n" for keys %mapping; |
376
|
|
|
|
|
|
|
}; |
377
|
|
|
|
|
|
|
if ($@) { |
378
|
|
|
|
|
|
|
warn("An error occurred in dcc: $@"); |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
=head1 BUGS |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
No real test suite yet, as its hard to do when testing daemons and so I |
384
|
|
|
|
|
|
|
got lazy :-( |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
=head1 AUTHOR |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
Matt Sergeant working for MessageLabs |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=head1 LICENSE |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
This is free software. You may redistribute it under the same terms |
393
|
|
|
|
|
|
|
as Perl itself. |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
Copyright 2003. All Rights Reserved. |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
=cut |