Code

Reimplemented automatic scrolling
[gosa.git] / gosa-si / client / events / mailqueue.pm
2 =head1 NAME
4 mailqueue.pm
6 =head1 SYNOPSIS
8 use GOSA::GosaSupportDaemon;
10 =head1 DESCRIPTION
12 This module contains all GOsa-SI-client processing instructions concerning the mailqueue in GOsa.
14 =head1 VERSION
16 Version 1.0
18 =head1 AUTHOR
20 Andreas Rettenberger <rettenberger at gonicus dot de>
22 =head1 FUNCTIONS
24 =cut
27 package mailqueue;
30 use strict;
31 use warnings;
33 use Exporter;
34 use GOSA::GosaSupportDaemon;
35 use MIME::Base64;
37 @ISA = qw(Exporter);
38 my @events = (
39     "get_events",
40     "mailqueue_query",
41     "mailqueue_hold",
42     "mailqueue_unhold",
43     "mailqueue_requeue",
44     "mailqueue_del",
45     "mailqueue_header",
46     );
47 @EXPORT = @events;
49 BEGIN {}
51 END {}
54 ###############################################################################
55 =over 
57 =item B<get_events ()>
59 =over
61 =item description 
63     Reports all provided functions.
65 =item parameter
67     None.
69 =item return 
71     \@events - ARRAYREF - array containing all functions 
73 =back
75 =back
77 =cut
78 ###############################################################################
79 sub get_events { return \@events; }
82 ###############################################################################
83 =over 
85 =item B<mailqueue_query ($$)>
87 =over
89 =item description 
91     Executes /usr/sbin/mailq, parse the informations and return them
93 =item parameter
95     $msg - STRING - complete GOsa-si message
96     $msg_hash - HASHREF - content of GOsa-si message in a hash
98 =item GOsa-si message xml content
100     None.
102 =item return 
104     $out_msg - STRING - GOsa-SI valid xml message containing msg_id, msg_hold, msg_size, arrival_time, sender and recipient.
106 =back
108 =back
110 =cut
111 ###############################################################################
112 sub mailqueue_query {
113     my ($msg, $msg_hash) = @_;
114     my $header = @{$msg_hash->{'header'}}[0];
115     my $source = @{$msg_hash->{'source'}}[0];
116     my $target = @{$msg_hash->{'target'}}[0];
117     my $session_id = @{$msg_hash->{'session_id'}}[0];
118     # q_tag can be: msg_id | msg_hold | msg_size | arrival_time | sender | recipient
119     my $q_tag = exists $msg_hash->{'q_tag'} ? @{$msg_hash->{'q_tag'}}[0] : undef ;
120     # q_operator can be: eq | gt | lt
121     my $q_operator = exists $msg_hash->{'q_operator'} ? @{$msg_hash->{'q_operator'}}[0] : undef ;
122     my $q_value = exists $msg_hash->{'q_value'} ? @{$msg_hash->{'q_value'}}[0] : undef ;
123     my $error = 0;
124     my $error_string;
125     my $msg_id;
126 #my $msg_hold;
127 #my $msg_size;
128 #my $arrival_time;
129     my $sender;
130     my $recipient;
131 #my $status_message;
132     my $out_hash;
133     my $out_msg;
135         &main::daemon_log("DEBUG: run /usr/bin/mailq\n", 7); 
136     my $result = qx("/usr/bin/mailq");
137     my @result_l = split(/([0-9A-Z]{10,12})/, $result);
139     if (length($result) == 0) {
140         $error = 1;
141         $error_string = "/usr/bin/mailq has no result";
142         &main::daemon_log("ERROR: $error_string : $msg", 1);
143     }
145     my $result_collection = {};
146     if (not $error) {
147         # parse information
148         my $result_length = @result_l;
149         my $j = 0;
150         for (my $i = 1; $i < $result_length; $i+=2) {
152             # Fetch and prepare all information 
153             my $act_result;
154             $act_result->{'msg_id'} = $result_l[$i];
155             $result_l[$i+1] =~ /^([\!| ])\s+(\d+)\s+(\w{3}\s+\w{3}\s+\d+\s+\d+:\d+:\d+)\s+([\w.-]+@[\w.-]+)\s+/ ;
156             $act_result->{'msg_hold'} =  $1 eq "!" ? 1 : 0 ;
157             $act_result->{'msg_size'} = $2;
158             $act_result->{'arrival_time'} = $3;
159             $act_result->{'sender'} = $4;
160             my @info_l = split(/\n/, $result_l[$i+1]);
161             $act_result->{'recipient'} = $info_l[2] =~ /([\w.-]+@[\w.-]+)/ ? $1 : 'unknown' ;
162             $act_result->{'msg_status'} = $info_l[1] =~ /^([\s\S]*)$/ ? $1 : 'unknown' ;
164             # If all query tags exists, perform the selection
165             my $query_positiv = 0;
166             if (defined $q_tag && defined $q_operator && defined $q_value) {
168                 # Query for message id
169                 if ( $q_tag eq 'msg_id') {
170                     if (not $q_operator eq 'eq') {
171                         &main::daemon_log("$session_id WARNING: query option '$q_operator' is not allowed with query tag '$q_tag'".
172                                 ", return return complete mail queue as fallback", 3);
173                         &main::daemon_log("$session_id DEBUG: \n$msg", 9); 
174                         $query_positiv++;
175                     } else {
176                         if ( &_exec_op($act_result->{'msg_id'}, $q_operator, $q_value) ) { 
177                             $query_positiv++; 
178                         }
179                     }
181                 # Query for message size
182                 } elsif ($q_tag eq 'msg_size') {
183                     my $result_size = int($act_result->{'msg_size'});
184                     my $query_size = int($q_value);
185                     if ( &_exec_op($result_size, $q_operator, $query_size) ) {
186                         $query_positiv++;
187                     }
189                 # Query for arrival time
190                 } elsif ($q_tag eq 'arrival_time') {
191                     my $result_time = int(&_parse_mailq_time($act_result->{'arrival_time'}));
192                     my $query_time = int($q_value);
194                     if ( &_exec_op($result_time, $q_operator, $query_time) ) {
195                         $query_positiv++;
196                     }
198                 # Query for sender
199                 }elsif ($q_tag eq 'sender') {
200                     if (not $q_operator eq 'eq') {
201                         &main::daemon_log("$session_id WARNING: query option '$q_operator' is not allowed with query tag '$q_tag'".
202                                 ", return return complete mail queue as fallback", 3);
203                         &main::daemon_log("$session_id DEBUG: \n$msg", 9); 
204                         $query_positiv++;
205                     } else {
206                         if ( &_exec_op($act_result->{'sender'}, $q_operator, $q_value)) { 
207                             $query_positiv++; 
208                         }
209                     }
211                 # Query for recipient
212                 } elsif ($q_tag eq 'recipient') {
213                     if (not $q_operator eq 'eq') {
214                         &main::daemon_log("$session_id WARNING: query option '$q_operator' is not allowed with query tag '$q_tag'".
215                                 ", return return complete mail queue as fallback", 3);
216                         &main::daemon_log("$session_id DEBUG: \n$msg", 9); 
217                         $query_positiv++;
218                     } else {
219                         if ( &_exec_op($act_result->{'recipient'}, $q_operator, $q_value)) { 
220                             $query_positiv++; 
221                         }
222                     }
223                 }
224             
225             # If no query tag exists, return all mails in mailqueue
226             } elsif ((not defined $q_tag) && (not defined $q_operator) && (not defined $q_value)) {
227                 $query_positiv++; 
229             # If query tags are not complete return error message
230             } elsif ((not defined $q_tag) || (not defined $q_operator) || (not defined $q_value)) {
231                 $error++;
232                 $error_string = "'mailqueue_query'-msg is not complete, some query tags (q_tag, q_operator, q_value) are missing";
233                 &main::daemon_log("$session_id WARNING: $error_string", 3);
234             }           
236             # If query was successful, add resutls to answer
237             if ($query_positiv) {
238                 $j++;   
239                 $result_collection->{$j} = $act_result;    
240             }
241         }
242     }
244     #create outgoing msg
245     $out_hash = &main::create_xml_hash("answer_$session_id", $target, $source);
246     &add_content2xml_hash($out_hash, "session_id", $session_id);
247     &add_content2xml_hash($out_hash, "error", $error);
248     if (defined @{$msg_hash->{'forward_to_gosa'}}[0]){
249         &add_content2xml_hash($out_hash, "forward_to_gosa", @{$msg_hash->{'forward_to_gosa'}}[0]);
250     }
252     # add error infos to outgoing msg
253     if ($error) {
254         &add_content2xml_hash($out_hash, "error_string", $error_string);
255         $out_msg = &main::create_xml_string($out_hash);
257     # add mail infos to outgoing msg
258     } else {
259         my $collection_string = &db_res2xml($result_collection);
260         $out_msg = &main::create_xml_string($out_hash);
261         $out_msg =~ s/<\/xml>/$collection_string<\/xml>/
262     }
263     
264     return $out_msg;
269 ###############################################################################
270 =over 
272 =item B<mailqueue_hold ($$)>
274 =over
276 =item description 
278     Executes '/usr/sbin/postsuper -h' and set mail to hold. 
280 =item parameter
282     $msg - STRING - complete GOsa-si message
283     $msg_hash - HASHREF - content of GOsa-si message in a hash
285 =item GOsa-si message xml content
287     <msg_id> - STRING - postfix mail id
289 =item return 
291     Nothing.
293 =back
295 =back
297 =cut
298 ###############################################################################
299 sub mailqueue_hold {
300     my ($msg, $msg_hash) = @_;
301     my $header = @{$msg_hash->{'header'}}[0];
302     my $source = @{$msg_hash->{'source'}}[0];
303     my $target = @{$msg_hash->{'target'}}[0];
304     my $session_id = @{$msg_hash->{'session_id'}}[0];
305     my $error = 0;
306     my $error_string;
308     # sanity check of input
309     if (not exists $msg_hash->{'msg_id'}) {
310         $error_string = "Message doesn't contain a XML tag 'msg_id"; 
311         &main::daemon_log("ERROR: $error_string : $msg", 1);
312         $error = 1;
313     } elsif (ref @{$msg_hash->{'msg_id'}}[0] eq "HASH") { 
314         $error_string = "XML tag 'msg_id' is empty";
315         &main::daemon_log("ERROR: $error_string : $msg", 1);
316         $error = 1;
317     }
319     if (not $error) {
320         my @msg_ids = @{$msg_hash->{'msg_id'}};
321         foreach my $msg_id (@msg_ids) {
322             my $error = 0;   # clear error status
324             # sanity check of each msg_id
325             if (not $msg_id =~ /^[0-9A-Z]{10,12}$/) {
326                 $error = 1;
327                 $error_string = "message ID is not valid ([0-9A-Z]{10,12}) : $msg_id";
328                 &main::daemon_log("ERROR: $error_string : $msg", 1);
329             }
331             if (not $error) {
332                 my $cmd = "/usr/sbin/postsuper -h $msg_id 2>&1";
333                 &main::daemon_log("DEBUG: run $cmd", 7); 
334                 my $result = qx($cmd);
335                 if ($result =~ /^postsuper: ([0-9A-Z]{10}): placed on hold/ ) {
336                     &main::daemon_log("INFO: Mail $msg_id placed on hold", 5);
337                 } elsif ($result eq "") {
338                     &main::daemon_log("INFO: Mail $msg_id is alread placed on hold", 5);
339                 
340                 } else {
341                     &main::daemon_log("ERROR: '$cmd' failed : $result", 1); 
342                 }
343             }
344         }
345     }
347     return;
350 ###############################################################################
351 =over 
353 =item B<mailqueue_unhold ($$)>
355 =over
357 =item description 
359     Executes '/usr/sbin/postsuper -H' and set mail to unhold. 
361 =item parameter
363     $msg - STRING - complete GOsa-si message
364     $msg_hash - HASHREF - content of GOsa-si message in a hash
366 =item GOsa-si message xml content
368     <msg_id> - STRING - postfix mail id
370 =item return 
372 Nothing.
374 =back
376 =back
378 =cut
379 ###############################################################################
380 sub mailqueue_unhold {
381     my ($msg, $msg_hash) = @_;
382     my $header = @{$msg_hash->{'header'}}[0];
383     my $source = @{$msg_hash->{'source'}}[0];
384     my $target = @{$msg_hash->{'target'}}[0];
385     my $session_id = @{$msg_hash->{'session_id'}}[0];
386     my $error = 0;
387     my $error_string;
388     
389     # sanity check of input
390     if (not exists $msg_hash->{'msg_id'}) {
391         $error_string = "Message doesn't contain a XML tag 'msg_id'"; 
392         &main::daemon_log("ERROR: $error_string : $msg", 1);
393         $error = 1;
394     } elsif (ref @{$msg_hash->{'msg_id'}}[0] eq "HASH") { 
395         $error_string = "XML tag 'msg_id' is empty";
396         &main::daemon_log("ERROR: $error_string : $msg", 1);
397         $error = 1;
398     }
399         
400     if (not $error) {
401         my @msg_ids = @{$msg_hash->{'msg_id'}};
402         foreach my $msg_id (@msg_ids) {
403             my $error = 0;   # clear error status
405             # sanity check of each msg_id
406             if (not $msg_id =~ /^[0-9A-Z]{10,12}$/) {
407                 $error = 1;
408                 $error_string = "message ID is not valid ([0-9A-Z]{10,12}) : $msg_id";
409                 &main::daemon_log("ERROR: $error_string : $msg", 1);
410             }
412             if (not $error) {
413                 my $cmd = "/usr/sbin/postsuper -H $msg_id 2>&1";
414                 &main::daemon_log("DEBUG: run $cmd\n", 7); 
415                 my $result = qx($cmd);
416                 if ($result =~ /^postsuper: ([0-9A-Z]{10}): released from hold/ ) {
417                     &main::daemon_log("INFO: Mail $msg_id released from on hold", 5);
418                 } elsif ($result eq "") {
419                     &main::daemon_log("INFO: Mail $msg_id is alread released from hold", 5);
421                 } else {
422                     &main::daemon_log("ERROR: '$cmd' failed : $result", 1); 
423                 }
425             }
426         }
427     }
429     return;
432 ###############################################################################
433 =over 
435 =item B<mailqueue_requeue ($$)>
437 =over
439 =item description 
441     Executes '/usr/sbin/postsuper -r' and requeue the mail.
443 =item parameter
445     $msg - STRING - complete GOsa-si message
446     $msg_hash - HASHREF - content of GOsa-si message in a hash
448 =item GOsa-si message xml content
450     <msg_id> - STRING - postfix mail id
452 =item return 
454 Nothing.
456 =back
458 =back
460 =cut
461 ###############################################################################
462 sub mailqueue_requeue {
463     my ($msg, $msg_hash) = @_;
464     my $header = @{$msg_hash->{'header'}}[0];
465     my $source = @{$msg_hash->{'source'}}[0];
466     my $target = @{$msg_hash->{'target'}}[0];
467     my $session_id = @{$msg_hash->{'session_id'}}[0];
468     my @msg_ids = @{$msg_hash->{'msg_id'}};
469     my $error = 0;
470     my $error_string;  
472     # sanity check of input
473     if (not exists $msg_hash->{'msg_id'}) {
474         $error_string = "Message doesn't contain a XML tag 'msg_id'"; 
475         &main::daemon_log("ERROR: $error_string : $msg", 1);
476         $error = 1;
477     } elsif (ref @{$msg_hash->{'msg_id'}}[0] eq "HASH") { 
478         $error_string = "XML tag 'msg_id' is empty";
479         &main::daemon_log("ERROR: $error_string : $msg", 1);
480         $error = 1;
481     }
482         
483     if (not $error) {
484         my @msg_ids = @{$msg_hash->{'msg_id'}};
485         foreach my $msg_id (@msg_ids) {
486             my $error = 0;   # clear error status
488             # sanity check of each msg_id
489             if (not $msg_id =~ /^[0-9A-Z]{10,12}$/) {
490                 $error = 1;
491                 $error_string = "message ID is not valid ([0-9A-Z]{10,12}) : $msg_id";
492                 &main::daemon_log("ERROR: $error_string : $msg", 1);
493             }
495             if (not $error) {
496                 my $cmd = "/usr/sbin/postsuper -r $msg_id 2>&1";
497                 &main::daemon_log("DEBUG: run '$cmd'", 7); 
498                 my $result = qx($cmd);
499                 if ($result =~ /^postsuper: ([0-9A-Z]{10}): requeued/ ) {
500                     &main::daemon_log("INFO: Mail $msg_id requeued", 5);
501                 } elsif ($result eq "") {
502                     &main::daemon_log("WARNING: Cannot requeue mail '$msg_id', mail not found!", 3);
504                 } else {
505                     &main::daemon_log("ERROR: '$cmd' failed : $result", 1); 
506                 }
508             }
509         }
510     }
512     return;
516 ###############################################################################
517 =over 
519 =item B<mailqueue_del ($$)>
521 =over
523 =item description 
525     Executes '/usr/sbin/postsuper -d' and deletes mail from queue.
527 =item parameter
529     $msg - STRING - complete GOsa-si message
530     $msg_hash - HASHREF - content of GOsa-si message in a hash
532 =item GOsa-si message xml content
534     <msg_id> - STRING - postfix mail id
536 =item return 
538 Nothing.
540 =back
542 =back
544 =cut
545 ###############################################################################
546 sub mailqueue_del {
547     my ($msg, $msg_hash) = @_;
548     my $header = @{$msg_hash->{'header'}}[0];
549     my $source = @{$msg_hash->{'source'}}[0];
550     my $target = @{$msg_hash->{'target'}}[0];
551     my $session_id = @{$msg_hash->{'session_id'}}[0];
552     my @msg_ids = @{$msg_hash->{'msg_id'}};
553     my $error = 0;
554     my $error_string;
556     # sanity check of input
557     if (not exists $msg_hash->{'msg_id'}) {
558         $error_string = "Message doesn't contain a XML tag 'msg_id'"; 
559         &main::daemon_log("ERROR: $error_string : $msg", 1);
560         $error = 1;
561     } elsif (ref @{$msg_hash->{'msg_id'}}[0] eq "HASH") { 
562         $error_string = "XML tag 'msg_id' is empty";
563         &main::daemon_log("ERROR: $error_string : $msg", 1);
564         $error = 1;
565     }
566         
567     if (not $error) {
568         my @msg_ids = @{$msg_hash->{'msg_id'}};
569         foreach my $msg_id (@msg_ids) {
570             my $error = 0;   # clear error status
572             # sanity check of each msg_id
573             if (not $msg_id =~ /^[0-9A-Z]{10,12}$/) {
574                 $error = 1;
575                 $error_string = "message ID is not valid ([0-9A-Z]{10,12}) : $msg_id";
576                 &main::daemon_log("ERROR: $error_string : $msg", 1);
577             }
579             if (not $error) {
580                 my $cmd = "/usr/sbin/postsuper -d $msg_id 2>&1";
581                 &main::daemon_log("DEBUG: run '$cmd'", 7); 
582                 my $result = qx($cmd);
583                 if ($result =~ /^postsuper: ([0-9A-Z]{10}): removed/ ) {
584                     &main::daemon_log("INFO: Mail $msg_id deleted", 5);
585                 } elsif ($result eq "") {
586                     &main::daemon_log("WARNING: Cannot remove mail '$msg_id', mail not found!", 3);
588                 } else {
589                     &main::daemon_log("ERROR: '$cmd' failed : $result", 1); 
590                 }
592             }
593         }
594     }
596     return;
599 ###############################################################################
600 =over 
602 =item B<mailqueue_header ($$)>
604 =over
606 =item description 
608     Executes 'postcat -q', parse the informations and return them. 
610 =item parameter
612     $msg - STRING - complete GOsa-si message
613     $msg_hash - HASHREF - content of GOsa-si message in a hash
615 =item GOsa-si message xml content
617     <msg_id> - STRING - postfix mail id
619 =item return 
621     $out_msg - STRING - GOsa-si valid xml message containing recipient, sender and subject.
623 =back
625 =back
627 =cut
628 ###############################################################################
629 sub mailqueue_header {
630     my ($msg, $msg_hash) = @_;
631     my $header = @{$msg_hash->{'header'}}[0];
632     my $source = @{$msg_hash->{'source'}}[0];
633     my $target = @{$msg_hash->{'target'}}[0];
634     my $session_id = @{$msg_hash->{'session_id'}}[0];
635     my $error = 0;
636     my $error_string;
637     my $sender;
638     my $recipient;
639     my $subject;
640     my $out_hash;
641     my $out_msg;
643     # sanity check of input
644     if (not exists $msg_hash->{'msg_id'}) {
645         $error_string = "Message doesn't contain a XML tag 'msg_id'"; 
646         &main::daemon_log("ERROR: $error_string : $msg", 1);
647         $error = 1;
648     } elsif (ref @{$msg_hash->{'msg_id'}}[0] eq "HASH") { 
649         $error_string = "XML tag 'msg_id' is empty";
650         &main::daemon_log("ERROR: $error_string : $msg", 1);
651         $error = 1;
652     }
654     # sanity check of each msg_id
655     my $msg_id;
656     if (not $error) {
657         $msg_id = @{$msg_hash->{'msg_id'}}[0];
658         if (not $msg_id =~ /^[0-9A-Z]{10,12}$/) {
659             $error = 1;
660             $error_string = "message ID is not valid ([0-9A-Z]{10,12}) : $msg_id";
661             &main::daemon_log("ERROR: $error_string : $msg", 1);
662         }
663     }
665     # parsing information
666     my $msg_header;
667     if (not $error) {
668         my $cmd = "postcat -q $msg_id";
669         &main::daemon_log("DEBUG: run '$cmd'", 7); 
670         my $result = qx($cmd);
672         my @header_l = split(/\n\n/, $result);
673         $msg_header = $header_l[0];
674     }       
676     # create outgoing msg
677     $out_hash = &main::create_xml_hash("answer_$session_id", $target, $source);
678     &add_content2xml_hash($out_hash, "session_id", $session_id);
679     &add_content2xml_hash($out_hash, "error", $error);
680     if (defined @{$msg_hash->{'forward_to_gosa'}}[0]){
681         &add_content2xml_hash($out_hash, "forward_to_gosa", @{$msg_hash->{'forward_to_gosa'}}[0]);
682     }
684     # add error infos to outgoing msg
685     if ($error) {
686         &add_content2xml_hash($out_hash, "error_string", $error_string);
687         $out_msg = &main::create_xml_string($out_hash);
689     # add mail infos to outgoing msg
690     } else {
691         #&add_content2xml_hash($out_hash, "msg_header", &decode_base64($msg_header));        
692         &add_content2xml_hash($out_hash, "msg_header", $msg_header);        
693         $out_msg = &main::create_xml_string($out_hash);
694     }
695  
696     return $out_msg;
699 sub _exec_op {
700     my ($a, $op, $b) = @_ ;
701     my $res;
703     if ($op eq "eq") {
704         $res = $a =~ /$b/ ? 1 : 0 ;
705     } elsif ($op eq "gt") {
706         $res = $a > $b ? 1 : 0 ;
707     } elsif ($op eq "lt") {
708         $res = $a < $b ? 1 : 0 ;
709     } 
711     return $res;
714 my $mo_hash = { "Jan"=>'01', "Feb"=>'02',"Mar"=>'03',"Apr"=>'04',"May"=>'05',"Jun"=>'06',
715     "Jul"=>'07',"Aug"=>'08',"Sep"=>'09',"Oct"=>'10',"Nov"=>'11',"Dec"=>'12'};
717 sub _parse_mailq_time {
718     my ($time) = @_ ;
720     my $local_time = &get_time();
721     my $local_year = substr($local_time,0,4);     
723     my ($dow, $mo, $dd, $date) = split(/\s/, $time);
724     my ($hh, $mi, $ss) = split(/:/, $date);
725     my $mailq_time = $local_year.$mo_hash->{$mo}."$dd$hh$mi$ss"; 
727     # This is realy nasty
728     if (int($local_time) < int($mailq_time)) {
729         # Mailq_time is in the future, this cannot be possible, so mail must be from last year
730         $mailq_time = int($local_year) - 1 .$mo_hash->{$mo}."$dd$hh$mi$ss";
731     }
733     return $mailq_time;
736 # vim:ts=4:shiftwidth:expandtab
738 1;