File Coverage

blib/lib/Net/Milter.pm
Criterion Covered Total %
statement 33 411 8.0
branch 1 216 0.4
condition 1 18 5.5
subroutine 10 31 32.2
pod 14 14 100.0
total 59 690 8.5


line stmt bran cond sub pod time code
1             package Net::Milter;
2 1     1   36667 use strict;
  1         2  
  1         37  
3 1     1   5 use Carp;
  1         2  
  1         111  
4 1     1   6 use vars qw($VERSION $DEBUG);
  1         6  
  1         81  
5             $VERSION='0.09';
6             $DEBUG=0;
7              
8 1     1   6 use constant PROTOCOL_NEGATION => 0;
  1         2  
  1         196  
9              
10             ############
11             sub new
12             {
13             # create new blank class
14 1     1 1 13 my $proto = shift;
15 1   33     7 my $class = ref($proto) || $proto;
16 1         4 my $self= {};
17              
18             # define the various negotiation options
19             # we'll put them here and not touch them so we can loop through and do bit wise checks later
20 1         6 $self->{action_types} = ['SMFIF_ADDHDRS', 'SMFIF_CHGBODY', 'SMFIF_ADDRCPT', 'SMFIF_DELRCPT', 'SMFIF_CHGHDRS', 'SMFIF_QUARANTINE'];
21 1         5 $self->{content_types} = ['SMFIP_NOCONNECT', 'SMFIP_NOHELO', 'SMFIP_NOMAIL', 'SMFIP_NORCPT', 'SMFIP_NOBODY', 'SMFIP_NOHDRS', 'SMFIP_NOEOH'];
22              
23 1         3 bless($self,$class);
24 1         8 return $self;
25             } # end sub new
26             ############
27              
28             ############
29             sub open {
30             # open the socket
31 1     1   1379 use IO::Socket;
  1         38884  
  1         6  
32              
33 0     0 1 0 my $self = shift;
34 0         0 my ($addr,$port,$proto) = @_;
35              
36 0 0       0 if ($DEBUG==1) {print STDERR "open\n";}
  0         0  
37              
38 0         0 my $sock;
39              
40 0 0 0     0 if (lc($proto) eq 'tcp' || lc($proto) eq 'inet') {
    0 0        
41 0 0       0 if ($DEBUG==1) {print STDERR "\topen tcp socket\n";}
  0         0  
42 1     1   1274 use IO::Socket::INET;
  1         2  
  1         11  
43 0 0       0 $sock = new IO::Socket::INET (PeerAddr => $addr,
44             PeerPort => $port,
45             Proto => 'tcp',
46             Type => SOCK_STREAM,
47             Timeout => 10,
48             ) or carp "Couldn't connect to $addr:$port : $@\n";
49             } # end if tcp
50 0         0 elsif (lc($proto) eq 'unix' || lc($proto) eq 'local') {
51 0 0       0 if ($DEBUG==1) {print STDERR "\topen unix socket\n";}
  0         0  
52 1     1   1485 use IO::Socket::UNIX;
  1         3  
  1         8  
53 0 0       0 $sock = new IO::Socket::UNIX (Peer => $addr,
54             Type => SOCK_STREAM,
55             Timeout => $port
56             ) or carp "Couldn't connect to unix socket on $addr : $@\n";
57             } # end if unix
58             else {carp "$proto is unknown to me\n";}
59              
60 0 0       0 if (!defined($sock)) {return 0;}
  0         0  
61             else {
62 0         0 $self->{socket} = $sock;
63 0         0 return 1;
64             }
65              
66             } # end sub open
67             ############
68              
69             ############
70             sub protocol_negotiation {
71             # negotiate with the filter as to what options to use
72 0     0 1 0 my $self = shift;
73            
74 0         0 my (%options) = @_;
75              
76 0 0       0 if ($DEBUG==1) {print STDERR "protocol_negotiation\n";}
  0         0  
77              
78             # set up the bit mask of allowed actions
79 0         0 my (@action_types) = @{$self->{action_types}};
  0         0  
80 0         0 my (@content_types) = @{$self->{content_types}};
  0         0  
81              
82 0         0 my ($count,$action,$content);
83              
84 0 0       0 if ($DEBUG==1) {print STDERR "\tsetting bits\n";}
  0         0  
85              
86 0         0 my $action_field = 0;
87              
88 0         0 $count=0;
89 0         0 while ($action = shift(@action_types)) {
90 0 0 0     0 if (defined($options{$action}) && $options{$action}==0) {
91             # do nothing
92             }
93             else {
94 0         0 $action_field = $action_field | (2**$count);
95             }
96              
97 0         0 $count++;
98             } # end while
99              
100              
101             # set up the bit mask for possible protocols
102 0         0 my $protocol_field = 0;
103              
104 0         0 $count=0;
105 0         0 while ($content = shift(@content_types)) {
106 0 0 0     0 if (defined($options{$content}) && $options{$content}==1) {
107 0         0 $protocol_field = $protocol_field | 2**$count;
108             }
109             else {
110             # do nothing
111             }
112              
113 0         0 $count++;
114             } # end while
115            
116             ### hmmm this bit might not be right on 64 bit architecture
117             # we want a 32 bit unsigned integer in network order
118 0         0 my $smfi_version = 2; # version of protocol
119 0         0 my $length = 13;
120              
121 0 0       0 if ($DEBUG==1) {print STDERR "\tpacking\n";}
  0         0  
122              
123 0         0 $action_field = $self->_pack_number($action_field);
124 0         0 $protocol_field = $self->_pack_number($protocol_field);
125 0         0 if (PROTOCOL_NEGATION == 1) {$protocol_field = ~$protocol_field;}
126 0         0 $smfi_version = $self->_pack_number($smfi_version);
127 0         0 $length = $self->_pack_number($length);
128              
129 0 0       0 if ($DEBUG==1) {print STDERR "\tsendsubing\n";}
  0         0  
130              
131 0         0 $self->{socket}->send($length);
132 0         0 $self->{socket}->send('O');
133 0         0 $self->{socket}->send($smfi_version);
134 0         0 $self->{socket}->send($action_field);
135 0         0 $self->{socket}->send($protocol_field);
136            
137              
138 0 0       0 if ($DEBUG==1) {print STDERR "\treceiving\n";}
  0         0  
139              
140 0         0 my ($command,$data)=$self->_receive();
141              
142 0 0       0 if ($command ne 'O') {carp "error in protocol negotiation \n";}
  0         0  
143              
144 0         0 my($ret_version,$ret_actions,$ret_protocol)=unpack "NNN",$data;
145            
146 0 0       0 if ($DEBUG==1) {print STDERR "\treturned version : $ret_version\n";}
  0         0  
147 0 0       0 if ($DEBUG==1) {printf STDERR "\treturned actions : %8b\n", $ret_actions;}
  0         0  
148 0 0       0 if ($DEBUG==1) {printf STDERR "\treturned protocol : %7b\n", $ret_protocol;}
  0         0  
149            
150             # translate returned bit mask into fields
151 0 0       0 if ($DEBUG==1) {print STDERR "\ttranslating bit mask\n";}
  0         0  
152              
153 0         0 my (@returned_actions, @returned_protocol);
154              
155 0         0 $count=0;
156 0         0 while ($action = shift(@action_types)) {
157 0 0       0 if ($ret_actions & 2**$count) {
158 0         0 push @returned_actions,$action;
159             }
160 0         0 $count++;
161             } # end while
162              
163 0         0 $count=0;
164 0         0 while ($content = shift(@content_types)) {
165 0 0       0 if ($ret_protocol & 2**$count) {
166 0         0 push @returned_protocol,$content;
167             }
168 0         0 $count++;
169             } # end while
170              
171              
172              
173 0         0 return ($ret_version,\@returned_actions,\@returned_protocol);
174             } # end sub protocol_negotiation
175             ############
176              
177             ############
178             sub send_abort {
179             # send an abort command, SMFIC_ABORT
180             # no response expected
181             # but dont close the connection
182 0 0   0 1 0 if ($DEBUG==1) {print STDERR "send_abort\n";}
  0         0  
183 0         0 my $self = shift;
184 0         0 $self->_send('A');
185              
186             } # end sub send_abort
187             ############
188              
189             ############
190             sub send_body {
191             # send body chunk of message, SMFIC_BODY
192              
193 0     0 1 0 my $self = shift;
194 0         0 my $body = shift;
195 0 0       0 if ($DEBUG==1) {print STDERR "send_body\n";}
  0         0  
196             # restrict body size to max allowable
197            
198 0 0       0 if ($DEBUG==1) {print STDERR "\tsending".substr($body,0,5).'...'."\n";}
  0         0  
199              
200 0 0       0 if (length ($body)>65535) {
201 0         0 warn "the message body is too big; its length must be less than 65536 bytes";
202 0         0 $self->_send('B',substr($body,0,65535));
203 0         0 $body = substr($body,65535);
204             }
205             else {
206 0         0 $self->_send('B',$body);
207             }
208            
209 0 0       0 if ($DEBUG==1) {print STDERR "\treceiving from body\n";}
  0         0  
210              
211             # get response
212 0         0 my (@replies)=$self->_retrieve_responses();
213 0         0 return(@replies);
214              
215             } # end sub send_body
216             ############
217              
218             ############
219             sub send_end_body {
220             # send body chunk of message, SMFIC_BODY
221              
222 0     0 1 0 my $self = shift;
223 0         0 my $body = shift;
224 0 0       0 if ($DEBUG==1) {print STDERR "send end_body\n";}
  0         0  
225              
226 0         0 $self->_send('E');
227 0 0       0 if ($DEBUG==1) {print STDERR "\treceiving\n";}
  0         0  
228              
229             # get response
230 0         0 my (@replies)=$self->_retrieve_responses();
231 0         0 return(@replies);
232              
233             } # end sub send_end_body
234             ############
235              
236             ############
237             sub send_connect {
238             # send connect message, SMFIC_CONNECT
239              
240 0     0 1 0 my $self = shift;
241 0         0 my ($hostname,$family,$port,$ip_address) = @_;
242              
243 0         0 my ($protocol_family);
244              
245 0         0 $hostname .="\0";
246 0         0 $ip_address .="\0";
247              
248 0 0       0 if ($DEBUG==1) {print STDERR "send connect\n";}
  0         0  
249              
250 0 0       0 if (lc($family) eq 'unix') {$protocol_family='L';}
  0 0       0  
  0 0       0  
251 0         0 elsif (lc($family) eq 'tcp4') {$protocol_family='4';}
252 0         0 elsif (lc($family) eq 'tcp6') {$protocol_family='6';}
253             else {$protocol_family='U';}
254              
255 0         0 $port = pack "n",$port;
256              
257 0 0       0 if ($DEBUG==1) {print STDERR "\tsending\n";}
  0         0  
258              
259 0         0 $self->_send('C',$hostname,$protocol_family,$port,$ip_address);
260              
261 0         0 my (@replies)=$self->_retrieve_responses();
262 0         0 return (@replies);
263             } # end sub send_connect
264             ############
265              
266             ############
267             sub send_helo {
268             # send helo string, SMFIC_HELO
269 0     0 1 0 my $self=shift;
270 0         0 my $helo_string = shift;
271 0 0       0 if ($DEBUG==1) {print STDERR "send_helo\n";}
  0         0  
272              
273 0         0 $helo_string .="\0";
274 0         0 $self->_send('H',$helo_string);
275              
276 0 0       0 if ($DEBUG==1) {print STDERR "\treceiving\n";}
  0         0  
277              
278 0         0 my (@replies)=$self->_retrieve_responses();
279 0         0 return (@replies);
280             } # end sub send_helo
281             ############
282              
283             ############
284             sub send_header {
285             # send a header name and value from message, SMFIC_HEADER
286              
287 0     0 1 0 my $self=shift;
288 0         0 my $header_name = shift;
289 0         0 my $header_value = shift;
290              
291 0 0       0 if ($DEBUG==1) {print STDERR "send_header\n";}
  0         0  
292              
293 0         0 $header_name.="\0";
294 0         0 $header_value.="\0";
295              
296 0         0 $self->_send('L',$header_name,$header_value);
297              
298 0         0 my (@replies)=$self->_retrieve_responses();
299 0         0 return (@replies);
300             } # end sub send_header
301             ############
302              
303             ############
304             sub send_mail_from {
305             # send MAIL FROM information from message, SMFIC_MAIL
306              
307 0     0 1 0 my $self=shift;
308 0         0 my $mail_from = shift;
309              
310 0 0       0 if ($DEBUG==1) {print STDERR "send_mail_from\n";}
  0         0  
311              
312 0         0 $mail_from.="\0";
313              
314 0         0 $self->_send('M',$mail_from);
315              
316 0         0 my (@replies)=$self->_retrieve_responses();
317 0         0 return (@replies);
318             } # end sub send_mail_from
319             ############
320              
321             ############
322             sub send_end_headers {
323             # send end of headers marker, SMFIC_EOH
324              
325 0     0 1 0 my $self=shift;
326              
327 0 0       0 if ($DEBUG==1) {print STDERR "send_end_headers\n";}
  0         0  
328              
329 0         0 $self->_send('N');
330              
331 0         0 my (@replies)=$self->_retrieve_responses();
332 0         0 return (@replies);
333             } # end sub send_end_headers
334             ############
335              
336             ############
337             sub send_rcpt_to {
338             # send RCPT TO information from message, SMFIC_RCPT
339              
340 0     0 1 0 my $self=shift;
341 0         0 my $rcpt_to = shift;
342              
343 0 0       0 if ($DEBUG==1) {print STDERR "send_rcpt_to\n";}
  0         0  
344              
345 0         0 $rcpt_to.="\0";
346              
347 0         0 $self->_send('R',$rcpt_to);
348              
349 0         0 my (@replies)=$self->_retrieve_responses();
350 0         0 return (@replies);
351             } # end sub send_rcpt_to
352             ############
353              
354             ############
355             sub send_quit {
356             # send a quit command, SMFIC_QUIT
357             # no response expected
358             # close the connection
359 0     0 1 0 my $self=shift;
360              
361 0 0       0 if ($DEBUG==1) {print STDERR "send_quit\n";}
  0         0  
362              
363 0         0 $self->_send('Q');
364              
365 0         0 $self->{socket}->close;
366              
367             } # end sub send_quit
368             ############
369              
370             ############
371             sub _send {
372             # concerned with the details of sending stuff
373              
374 0     0   0 my $self = shift;
375 0         0 my $command = shift;
376 0         0 my (@data) = @_;
377            
378 0 0       0 if ($DEBUG==1) {print STDERR "send\n";}
  0         0  
379              
380 0         0 my $data = join '',@data;
381 0         0 my $length = length($data);
382 0         0 $length += 1;
383              
384 0 0       0 if ($DEBUG==1) {
385 0         0 print STDERR "sending - command : $command\tlength : $length";
386 0 0       0 if (length($data)<100) {print STDERR "\tdata : $data\n";}
  0         0  
  0         0  
387             else {print STDERR "\n";}
388             }
389              
390 0         0 $length = $self->_pack_number($length);
391              
392 0 0       0 if (!defined($self->{socket})) {carp "can't connect no connection defined !\n";}
  0         0  
393 0         0 $self->_io_send($length);
394 0         0 $self->_io_send($command);
395 0 0       0 $self->_io_send($data) if (length($data) > 0);
396              
397            
398             } # end sub _send
399             ############
400              
401             ############
402             sub _receive {
403             # concerned with the details of receiving stuff
404              
405 1     1   5231 use IO::Select;
  1         2096  
  1         3189  
406              
407 0     0   0 my $self = shift;
408              
409 0 0       0 if ($DEBUG==1) {print STDERR "_receive\n";}
  0         0  
410              
411 0         0 my $length = $self->_io_recv(4);
412 0         0 my $command = $self->_io_recv(1);
413 0         0 $length = $self->_unpack_number($length);
414 0 0       0 if ($DEBUG==1) {print STDERR "\tcommand : $command\n\tlength : $length\n";}
  0         0  
415 0         0 $length -= 1;
416              
417 0         0 my $data;
418 0 0       0 if ($length > 0) {
419 0         0 $data = $self->_io_recv($length);
420             }
421              
422 0         0 return ($command,$data);
423             } # end sub _receive
424             ############
425              
426             ############
427             sub _pack_number {
428             # single place to pack numbers
429 0     0   0 my $self = shift;
430 0         0 my $number = shift;
431              
432 0 0       0 if ($DEBUG==1) {print STDERR "_pack_number\n";}
  0         0  
433              
434 0         0 my $ret_number = pack "N",$number;
435              
436 0         0 return ($ret_number);
437             } # end sub _pack_number
438             ############
439              
440             ############
441             sub _unpack_number {
442             # single place to unpack numbers
443 0     0   0 my $self = shift;
444 0         0 my $number = shift;
445              
446 0 0       0 if ($DEBUG==1) {print STDERR "_unpack_number\n";}
  0         0  
447              
448 0         0 my $ret_number = unpack "N",$number;
449              
450 0         0 return ($ret_number);
451             } # end sub _unpack_number
452             ############
453              
454             ############
455             sub _translate_response {
456             # turn what we get from the filter into something more manageable
457              
458 0     0   0 my $self = shift;
459 0         0 my ($command,$data)=@_;
460              
461 0 0       0 if ($DEBUG==1) {
462 0         0 print STDERR "_translate_response\n";
463 0         0 print STDERR "\tcommand : $command\n";
464 0 0 0     0 if (defined($data) && $command !~/[hm]/) {print STDERR "\tdata : $data\n";}
  0         0  
465             }
466              
467              
468 0         0 my %reply=();
469              
470 0         0 $reply{command}=$command;
471              
472 0 0       0 if ($command eq '+') {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
473 0         0 $reply{explanation}='Add a recipient';
474 0         0 $reply{header}='To';
475 0         0 $reply{action}='add';
476 0         0 $reply{value}=$data;
477             }
478              
479             elsif ($command eq '-') {
480 0         0 $reply{explanation}='Remove a recipient';
481 0         0 $reply{header}='To';
482 0         0 $reply{action}='delete';
483 0         0 $reply{value}=$data;
484             }
485              
486             elsif ($command eq 'a') {
487 0         0 $reply{explanation}='Accept message completely';
488 0         0 $reply{action}='accept';
489             }
490              
491             elsif ($command eq 'b') {
492 0         0 $reply{explanation}='Replace body chunk';
493 0         0 $reply{header}='body';
494 0         0 $reply{action}='replace';
495 0         0 $reply{value}=$data;
496             }
497              
498             elsif ($command eq 'c') {
499 0         0 $reply{explanation}='Accept and continue';
500 0         0 $reply{action}='continue';
501             }
502              
503             elsif ($command eq 'd') {
504 0         0 $reply{explanation}='Reject message completely';
505 0         0 $reply{action}='reject';
506             }
507              
508             elsif ($command eq 'h') {
509 0         0 $reply{explanation}='Add header';
510 0         0 ($reply{header},$reply{value},undef)=split(/\0/,$data);
511 0         0 $reply{action}='add';
512             }
513              
514             elsif ($command eq 'm') {
515 0         0 $reply{explanation}='Replace body header';
516 0         0 $reply{index}=$self->_unpack_number(substr($data,0,4));
517 0         0 $data = substr($data,4);
518 0         0 ($reply{header},$reply{value},undef)=split(/\0/,$data);
519 0         0 $reply{action}='replace';
520             }
521              
522             elsif ($command eq 'p') {
523 0         0 $reply{explanation}='Progress';
524 0         0 $reply{action}='continue';
525             }
526              
527             elsif ($command eq 'r') {
528 0         0 $reply{explanation}='Reject command with 5xx error';
529 0         0 $reply{action}='reject';
530 0         0 $reply{value}=5;
531             }
532              
533             elsif ($command eq 't') {
534 0         0 $reply{explanation}='Reject command with 4xx error';
535 0         0 $reply{action}='reject';
536 0         0 $reply{value}=4;
537             }
538              
539             elsif ($command eq 'y') {
540 0         0 $reply{explanation}='Reject command with xxx error';
541 0         0 $reply{action}='reject';
542 0         0 $reply{value}=$data;
543             }
544              
545              
546 0         0 return (\%reply);
547             } # end sub _translate_response
548             ############
549              
550             ############
551             sub _retrieve_responses {
552              
553 0     0   0 my $self = shift;
554              
555 0         0 my (@replies,$command,$data,$reply_ref);
556              
557 0 0       0 if ($DEBUG==1) {print STDERR "_retrieve_response\n";}
  0         0  
558              
559 0         0 while () {
560 0 0       0 if ($DEBUG==1) {print STDERR "\twaiting for response\n";}
  0         0  
561 0         0 ($command,$data)=$self->_receive();
562 0         0 ($reply_ref)=$self->_translate_response($command,$data);
563            
564 0         0 push @replies,$reply_ref;
565              
566 0 0       0 if ($DEBUG==1) {print STDERR "\tcommand : $$reply_ref{command}";}
  0         0  
567 0 0       0 if ($$reply_ref{command} eq 'c') {last;}
  0 0       0  
  0 0       0  
    0          
    0          
    0          
568 0         0 elsif ($$reply_ref{command} eq 'a') {last;}
569 0         0 elsif ($$reply_ref{command} eq 'r') {last;}
570 0         0 elsif ($$reply_ref{command} eq 't') {last;}
571 0         0 elsif ($$reply_ref{command} eq 'y') {last;}
572             elsif ($$reply_ref{command} eq 'd') {last;}
573             } # end while
574              
575 0         0 return (@replies);
576             } # end sub retrieve_responses
577             ############
578              
579             ############
580             sub send_macros {
581 0     0 1 0 my $self=shift;
582 0         0 my %macros = @_;
583              
584 0 0       0 if ($DEBUG==1) {print STDERR "retrieve_response\n";}
  0         0  
585              
586 0         0 my (@data);
587              
588 0 0       0 if ($DEBUG==1) {
589 0         0 foreach (keys(%macros)) {
590 0         0 print STDERR "\tmacro : $_ = $macros{$_}\n";
591             }
592             } # end if DEBUG
593              
594 0 0       0 if (defined($macros{j})) {push @data,'j'."\0".$macros{j}."\0";}
  0         0  
595 0 0       0 if (defined($macros{_})) {push @data,'_'."\0",$macros{_}."\0";}
  0         0  
596 0 0       0 if (defined($macros{'{daemon_name}'})) {push @data,'{daemon_name}'."\0".$macros{'{daemon_name}'}."\0";}
  0         0  
597 0 0       0 if (defined($macros{'{if_name}'})) {push @data,'{if_name}'."\0".$macros{'{if_name}'}."\0";}
  0         0  
598 0 0       0 if (defined($macros{'{if_addr}'})) {push @data,'{if_addr}'."\0".$macros{'{if_addr}'}."\0";}
  0         0  
599              
600 0 0       0 if (@data) {
601 0 0       0 if ($DEBUG==1) {print STDERR "\tsending D,C\n";}
  0         0  
602 0         0 $self->_send('D','C',@data);
603             }
604              
605 0         0 @data=();
606 0 0       0 if (defined($macros{'{tls_version}'})) {push @data,'{tls_version}'."\0".$macros{'{tls_version}'}."\0";}
  0         0  
607 0 0       0 if (defined($macros{'{cipher}'})) {push @data,'{cipher}'."\0".$macros{'{cipher}'}."\0";}
  0         0  
608 0 0       0 if (defined($macros{'{cipher_bits}'})) {push @data,'{cipher_bits}'."\0".$macros{'{cipher_bits}'}."\0";}
  0         0  
609 0 0       0 if (defined($macros{'{cert_subject}'})) {push @data,'{cert_subject}'."\0".$macros{'{cert_subject}'}."\0";}
  0         0  
610 0 0       0 if (defined($macros{'{cert_issuer}'})) {push @data,'{cert_issuer}'."\0".$macros{'{cert_issuer}'}."\0";}
  0         0  
611              
612 0 0       0 if (@data) {
613 0 0       0 if ($DEBUG==1) {print STDERR "\tsending D,H\n";}
  0         0  
614 0         0 $self->_send('D','H',@data);
615             }
616              
617              
618              
619 0         0 @data=();
620 0 0       0 if (defined($macros{i})) {push @data,'i'."\0".$macros{i}."\0";}
  0         0  
621 0 0       0 if (defined($macros{'{auth_type}'})) {push @data,'{auth_type}'."\0".$macros{'{auth_type}'}."\0";}
  0         0  
622 0 0       0 if (defined($macros{'{auth_authen}'})) {push @data,'{auth_authen}'."\0".$macros{'{auth_authen}'}."\0";}
  0         0  
623 0 0       0 if (defined($macros{'{auth_ssf}'})) {push @data,'{auth_ssf}'."\0".$macros{'{auth_ssf}'}."\0";}
  0         0  
624 0 0       0 if (defined($macros{'{auth_author}'})) {push @data,'{auth_author}'."\0".$macros{'{auth_author}'}."\0";}
  0         0  
625 0 0       0 if (defined($macros{'{mail_mailer}'})) {push @data,'{mail_mailer}'."\0".$macros{'{mail_mailer}'}."\0";}
  0         0  
626 0 0       0 if (defined($macros{'{mail_host}'})) {push @data,'{mail_host}'."\0".$macros{'{mail_host}'}."\0";}
  0         0  
627 0 0       0 if (defined($macros{'{mail_addr}'})) {push @data,'{mail_addr}'."\0".$macros{'{mail_addr}'}."\0";}
  0         0  
628              
629 0 0       0 if (@data) {
630 0 0       0 if ($DEBUG==1) {print STDERR "\tsending D,M\n";}
  0         0  
631 0         0 $self->_send('D','M',@data);
632             }
633              
634              
635 0         0 @data=();
636 0 0       0 if (defined($macros{'{rcpt_mailer}'})) {push @data,'{rcpt_mailer}'."\0".$macros{'{rcpt_mailer}'}."\0";}
  0         0  
637 0 0       0 if (defined($macros{'{rcpt_host}'})) {push @data,'{rcpt_host}'."\0".$macros{'{rcpt_host}'}."\0";}
  0         0  
638 0 0       0 if (defined($macros{'{rcpt_addr}'})) {push @data,'{rcpt_addr}'."\0".$macros{'{rcpt_addr}'}."\0";}
  0         0  
639              
640 0 0       0 if (@data) {
641 0 0       0 if ($DEBUG==1) {print STDERR "\tsending D,R\n";}
  0         0  
642 0         0 $self->_send('D','R',@data);
643             }
644              
645              
646             # no response after sending macros
647 0         0 return 1;
648              
649             } # end sub send_macros
650             ############
651              
652             ############
653             sub _io_send {
654 0     0   0 my $self = shift;
655 0         0 my ($data) = @_;
656            
657 0         0 my $must_send = length($data);
658 0         0 my $did_send = 0;
659 0         0 while ($did_send < $must_send) {
660 0         0 my $len = $self->{socket}->send(substr($data, $did_send));
661 0 0       0 if (defined($len)) {
662 0         0 $did_send += $len;
663             }
664             else {
665 0         0 carp "Error while writing to the socket: $!";
666             }
667             }
668            
669 0         0 return 1;
670             }
671             ############
672              
673             ############
674             sub _io_recv {
675 0     0   0 my $self = shift;
676 0         0 my ($must_recv) = @_;
677            
678 0         0 my $did_recv = 0;
679 0         0 my $data = "";
680 0         0 while ($did_recv < $must_recv) {
681 0         0 my $len = $self->{socket}->sysread($data, $must_recv-$did_recv, $did_recv);
682 0 0       0 if (defined($len)) {
683 0         0 $did_recv += $len;
684             }
685             else {
686 0         0 carp "Error while reading from the socket: $!";
687             }
688             }
689            
690 0         0 return $data;
691             }
692             ############
693              
694             ############
695             sub DESTROY {
696 1     1   409 my $self = shift;
697 1 50       111 if (defined($self->{socket})) {
698 0           $self->{socket}->close;
699             } # end if
700              
701             } # end sub DESTROY
702             ############
703              
704             1;
705              
706              
707             __END__