Code

Updated locales
[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 MIME::Base64;
34 use GOsaSI::GosaSupportDaemon;
36 use Exporter;
38 our @ISA = qw(Exporter);
40 my @events = (
41     "get_events",
42     "mailqueue_query",
43     "mailqueue_hold",
44     "mailqueue_unhold",
45     "mailqueue_requeue",
46     "mailqueue_del",
47     "mailqueue_header",
48     );
50 our @EXPORT = @events;
52 BEGIN {}
54 END {}
57 ###############################################################################
58 =over 
60 =item B<get_events ()>
62 =over
64 =item description 
66     Reports all provided functions.
68 =item parameter
70     None.
72 =item return 
74     \@events - ARRAYREF - array containing all functions 
76 =back
78 =back
80 =cut
81 ###############################################################################
82 sub get_events { return \@events; }
85 ###############################################################################
86 =over 
88 =item B<mailqueue_query ($$)>
90 =over
92 =item description 
94     Executes /usr/sbin/mailq, parse the informations and return them
96 =item parameter
98     $msg - STRING - complete GOsa-si message
99     $msg_hash - HASHREF - content of GOsa-si message in a hash
101 =item GOsa-si message xml content
103     None.
105 =item return 
107     $out_msg - STRING - GOsa-SI valid xml message containing msg_id, msg_hold, msg_size, arrival_time, sender and recipient.
109 =back
111 =back
113 =cut
114 ###############################################################################
115 sub mailqueue_query {
116     my ($msg, $msg_hash) = @_;
117     my $header = @{$msg_hash->{'header'}}[0];
118     my $source = @{$msg_hash->{'source'}}[0];
119     my $target = @{$msg_hash->{'target'}}[0];
120     my $session_id = @{$msg_hash->{'session_id'}}[0];
121     # q_tag can be: msg_id | msg_hold | msg_size | arrival_time | sender | recipient
122     my $q_tag = exists $msg_hash->{'q_tag'} ? @{$msg_hash->{'q_tag'}}[0] : undef ;
123     # q_operator can be: eq | gt | lt
124     my $q_operator = exists $msg_hash->{'q_operator'} ? @{$msg_hash->{'q_operator'}}[0] : undef ;
125     my $q_value = exists $msg_hash->{'q_value'} ? @{$msg_hash->{'q_value'}}[0] : undef ;
126     my $error = 0;
127     my $error_string;
128     my $msg_id;
129 #my $msg_hold;
130 #my $msg_size;
131 #my $arrival_time;
132     my $sender;
133     my $recipient;
134 #my $status_message;
135     my $out_hash;
136     my $out_msg;
138     &main::daemon_log("DEBUG: run /usr/bin/mailq\n", 7); 
139     my $result = qx("/usr/bin/mailq");
140     my @result_l = split(/([0-9A-Z]{10,12})/, $result);
142     if (length($result) == 0) {
143         $error = 1;
144         $error_string = "/usr/bin/mailq has no result";
145         &main::daemon_log("ERROR: $error_string : $msg", 1);
146     }
148     my $result_collection = {};
149     if (not $error) {
150         # parse information
151         my $result_length = @result_l;
152         my $j = 0;
153         for (my $i = 1; $i < $result_length; $i+=2) {
155             # Fetch and prepare all information 
156             my $act_result;
157             $act_result->{'msg_id'} = $result_l[$i];
158             $result_l[$i+1] =~ /^([\!| ])\s+(\d+)\s+(\w{3}\s+\w{3}\s+\d+\s+\d+:\d+:\d+)\s+([\w.-]+@[\w.-]+)\s+/ ;
159             $act_result->{'msg_hold'} =  $1 eq "!" ? 1 : 0 ;
160             $act_result->{'msg_size'} = $2;
161             $act_result->{'arrival_time'} = $3;
162             $act_result->{'sender'} = $4;
163             my @info_l = split(/\n/, $result_l[$i+1]);
164             $act_result->{'recipient'} = $info_l[2] =~ /([\w.-]+@[\w.-]+)/ ? $1 : 'unknown' ;
165             $act_result->{'msg_status'} = $info_l[1] =~ /^([\s\S]*)$/ ? $1 : 'unknown' ;
167             # If all query tags exists, perform the selection
168             my $query_positiv = 0;
169             if (defined $q_tag && defined $q_operator && defined $q_value) {
171                 # Query for message id
172                 if ( $q_tag eq 'msg_id') {
173                     if (not $q_operator eq 'eq') {
174                         &main::daemon_log("$session_id WARNING: query option '$q_operator' is not allowed with query tag '$q_tag'".
175                                 ", return return complete mail queue as fallback", 3);
176                         &main::daemon_log("$session_id DEBUG: \n$msg", 9); 
177                         $query_positiv++;
178                     } else {
179                         if ( &_exec_op($act_result->{'msg_id'}, $q_operator, $q_value) ) { 
180                             $query_positiv++; 
181                         }
182                     }
184                 # Query for message size
185                 } elsif ($q_tag eq 'msg_size') {
186                     my $result_size = int($act_result->{'msg_size'});
187                     my $query_size = int($q_value);
188                     if ( &_exec_op($result_size, $q_operator, $query_size) ) {
189                         $query_positiv++;
190                     }
192                 # Query for arrival time
193                 } elsif ($q_tag eq 'arrival_time') {
194                     my $result_time = int(&_parse_mailq_time($act_result->{'arrival_time'}));
195                     my $query_time = int($q_value);
197                     if ( &_exec_op($result_time, $q_operator, $query_time) ) {
198                         $query_positiv++;
199                     }
201                 # Query for sender
202                 }elsif ($q_tag eq 'sender') {
203                     if (not $q_operator eq 'eq') {
204                         &main::daemon_log("$session_id WARNING: query option '$q_operator' is not allowed with query tag '$q_tag'".
205                                 ", return return complete mail queue as fallback", 3);
206                         &main::daemon_log("$session_id DEBUG: \n$msg", 9); 
207                         $query_positiv++;
208                     } else {
209                         if ( &_exec_op($act_result->{'sender'}, $q_operator, $q_value)) { 
210                             $query_positiv++; 
211                         }
212                     }
214                 # Query for recipient
215                 } elsif ($q_tag eq 'recipient') {
216                     if (not $q_operator eq 'eq') {
217                         &main::daemon_log("$session_id WARNING: query option '$q_operator' is not allowed with query tag '$q_tag'".
218                                 ", return return complete mail queue as fallback", 3);
219                         &main::daemon_log("$session_id DEBUG: \n$msg", 9); 
220                         $query_positiv++;
221                     } else {
222                         if ( &_exec_op($act_result->{'recipient'}, $q_operator, $q_value)) { 
223                             $query_positiv++; 
224                         }
225                     }
226                 }
227             
228             # If no query tag exists, return all mails in mailqueue
229             } elsif ((not defined $q_tag) && (not defined $q_operator) && (not defined $q_value)) {
230                 $query_positiv++; 
232             # If query tags are not complete return error message
233             } elsif ((not defined $q_tag) || (not defined $q_operator) || (not defined $q_value)) {
234                 $error++;
235                 $error_string = "'mailqueue_query'-msg is not complete, some query tags (q_tag, q_operator, q_value) are missing";
236                 &main::daemon_log("$session_id WARNING: $error_string", 3);
237             }           
239             # If query was successful, add results to answer
240             if ($query_positiv) {
241                 $j++;
242                 foreach my $key (keys %{ $act_result }) {
243                         $act_result->{$key} =~ s/\</\&lt\;/g;
244                         $act_result->{$key} =~ s/\>/\&gt\;/g;
245                 }
246                 $result_collection->{$j} = $act_result;    
247             }
248         }
249     }
251     #create outgoing msg
252     $out_hash = &main::create_xml_hash("answer_$session_id", $target, $source);
253     &add_content2xml_hash($out_hash, "session_id", $session_id);
254     &add_content2xml_hash($out_hash, "error", $error);
255     if (defined @{$msg_hash->{'forward_to_gosa'}}[0]){
256         &add_content2xml_hash($out_hash, "forward_to_gosa", @{$msg_hash->{'forward_to_gosa'}}[0]);
257     }
259     # add error infos to outgoing msg
260     if ($error) {
261         &add_content2xml_hash($out_hash, "error_string", $error_string);
262         $out_msg = &main::create_xml_string($out_hash);
264     # add mail infos to outgoing msg
265     } else {
266         my $collection_string = &db_res2xml($result_collection);
267         $out_msg = &main::create_xml_string($out_hash);
268         $out_msg =~ s/<\/xml>/$collection_string<\/xml>/
269     }
270     
271     return $out_msg;
276 ###############################################################################
277 =over 
279 =item B<mailqueue_hold ($$)>
281 =over
283 =item description 
285     Executes '/usr/sbin/postsuper -h' and set mail to hold. 
287 =item parameter
289     $msg - STRING - complete GOsa-si message
290     $msg_hash - HASHREF - content of GOsa-si message in a hash
292 =item GOsa-si message xml content
294     <msg_id> - STRING - postfix mail id
296 =item return 
298     Nothing.
300 =back
302 =back
304 =cut
305 ###############################################################################
306 sub mailqueue_hold {
307     my ($msg, $msg_hash) = @_;
308     my $header = @{$msg_hash->{'header'}}[0];
309     my $source = @{$msg_hash->{'source'}}[0];
310     my $target = @{$msg_hash->{'target'}}[0];
311     my $session_id = @{$msg_hash->{'session_id'}}[0];
312     my $error = 0;
313     my $error_string;
315     # sanity check of input
316     if (not exists $msg_hash->{'msg_id'}) {
317         $error_string = "Message doesn't contain a XML tag 'msg_id"; 
318         &main::daemon_log("ERROR: $error_string : $msg", 1);
319         $error = 1;
320     } elsif (ref @{$msg_hash->{'msg_id'}}[0] eq "HASH") { 
321         $error_string = "XML tag 'msg_id' is empty";
322         &main::daemon_log("ERROR: $error_string : $msg", 1);
323         $error = 1;
324     }
326     if (not $error) {
327         my @msg_ids = @{$msg_hash->{'msg_id'}};
328         foreach my $msg_id (@msg_ids) {
329             my $error = 0;   # clear error status
331             # sanity check of each msg_id
332             if (not $msg_id =~ /^[0-9A-Z]{10,12}$/) {
333                 $error = 1;
334                 $error_string = "message ID is not valid ([0-9A-Z]{10,12}) : $msg_id";
335                 &main::daemon_log("ERROR: $error_string : $msg", 1);
336             }
338             if (not $error) {
339                 my $cmd = "/usr/sbin/postsuper -h $msg_id 2>&1";
340                 &main::daemon_log("DEBUG: run $cmd", 7); 
341                 my $result = qx($cmd);
342                 if ($result =~ /^postsuper: ([0-9A-Z]{10}): placed on hold/ ) {
343                     &main::daemon_log("INFO: Mail $msg_id placed on hold", 5);
344                 } elsif ($result eq "") {
345                     &main::daemon_log("INFO: Mail $msg_id is alread placed on hold", 5);
346                 
347                 } else {
348                     &main::daemon_log("ERROR: '$cmd' failed : $result", 1); 
349                 }
350             }
351         }
352     }
354     return;
357 ###############################################################################
358 =over 
360 =item B<mailqueue_unhold ($$)>
362 =over
364 =item description 
366     Executes '/usr/sbin/postsuper -H' and set mail to unhold. 
368 =item parameter
370     $msg - STRING - complete GOsa-si message
371     $msg_hash - HASHREF - content of GOsa-si message in a hash
373 =item GOsa-si message xml content
375     <msg_id> - STRING - postfix mail id
377 =item return 
379 Nothing.
381 =back
383 =back
385 =cut
386 ###############################################################################
387 sub mailqueue_unhold {
388     my ($msg, $msg_hash) = @_;
389     my $header = @{$msg_hash->{'header'}}[0];
390     my $source = @{$msg_hash->{'source'}}[0];
391     my $target = @{$msg_hash->{'target'}}[0];
392     my $session_id = @{$msg_hash->{'session_id'}}[0];
393     my $error = 0;
394     my $error_string;
395     
396     # sanity check of input
397     if (not exists $msg_hash->{'msg_id'}) {
398         $error_string = "Message doesn't contain a XML tag 'msg_id'"; 
399         &main::daemon_log("ERROR: $error_string : $msg", 1);
400         $error = 1;
401     } elsif (ref @{$msg_hash->{'msg_id'}}[0] eq "HASH") { 
402         $error_string = "XML tag 'msg_id' is empty";
403         &main::daemon_log("ERROR: $error_string : $msg", 1);
404         $error = 1;
405     }
406         
407     if (not $error) {
408         my @msg_ids = @{$msg_hash->{'msg_id'}};
409         foreach my $msg_id (@msg_ids) {
410             my $error = 0;   # clear error status
412             # sanity check of each msg_id
413             if (not $msg_id =~ /^[0-9A-Z]{10,12}$/) {
414                 $error = 1;
415                 $error_string = "message ID is not valid ([0-9A-Z]{10,12}) : $msg_id";
416                 &main::daemon_log("ERROR: $error_string : $msg", 1);
417             }
419             if (not $error) {
420                 my $cmd = "/usr/sbin/postsuper -H $msg_id 2>&1";
421                 &main::daemon_log("DEBUG: run $cmd\n", 7); 
422                 my $result = qx($cmd);
423                 if ($result =~ /^postsuper: ([0-9A-Z]{10}): released from hold/ ) {
424                     &main::daemon_log("INFO: Mail $msg_id released from on hold", 5);
425                 } elsif ($result eq "") {
426                     &main::daemon_log("INFO: Mail $msg_id is alread released from hold", 5);
428                 } else {
429                     &main::daemon_log("ERROR: '$cmd' failed : $result", 1); 
430                 }
432             }
433         }
434     }
436     return;
439 ###############################################################################
440 =over 
442 =item B<mailqueue_requeue ($$)>
444 =over
446 =item description 
448     Executes '/usr/sbin/postsuper -r' and requeue the mail.
450 =item parameter
452     $msg - STRING - complete GOsa-si message
453     $msg_hash - HASHREF - content of GOsa-si message in a hash
455 =item GOsa-si message xml content
457     <msg_id> - STRING - postfix mail id
459 =item return 
461 Nothing.
463 =back
465 =back
467 =cut
468 ###############################################################################
469 sub mailqueue_requeue {
470     my ($msg, $msg_hash) = @_;
471     my $header = @{$msg_hash->{'header'}}[0];
472     my $source = @{$msg_hash->{'source'}}[0];
473     my $target = @{$msg_hash->{'target'}}[0];
474     my $session_id = @{$msg_hash->{'session_id'}}[0];
475     my @msg_ids = @{$msg_hash->{'msg_id'}};
476     my $error = 0;
477     my $error_string;  
479     # sanity check of input
480     if (not exists $msg_hash->{'msg_id'}) {
481         $error_string = "Message doesn't contain a XML tag 'msg_id'"; 
482         &main::daemon_log("ERROR: $error_string : $msg", 1);
483         $error = 1;
484     } elsif (ref @{$msg_hash->{'msg_id'}}[0] eq "HASH") { 
485         $error_string = "XML tag 'msg_id' is empty";
486         &main::daemon_log("ERROR: $error_string : $msg", 1);
487         $error = 1;
488     }
489         
490     if (not $error) {
491         my @msg_ids = @{$msg_hash->{'msg_id'}};
492         foreach my $msg_id (@msg_ids) {
493             my $error = 0;   # clear error status
495             # sanity check of each msg_id
496             if (not $msg_id =~ /^[0-9A-Z]{10,12}$/) {
497                 $error = 1;
498                 $error_string = "message ID is not valid ([0-9A-Z]{10,12}) : $msg_id";
499                 &main::daemon_log("ERROR: $error_string : $msg", 1);
500             }
502             if (not $error) {
503                 my $cmd = "/usr/sbin/postsuper -r $msg_id 2>&1";
504                 &main::daemon_log("DEBUG: run '$cmd'", 7); 
505                 my $result = qx($cmd);
506                 if ($result =~ /^postsuper: ([0-9A-Z]{10}): requeued/ ) {
507                     &main::daemon_log("INFO: Mail $msg_id requeued", 5);
508                 } elsif ($result eq "") {
509                     &main::daemon_log("WARNING: Cannot requeue mail '$msg_id', mail not found!", 3);
511                 } else {
512                     &main::daemon_log("ERROR: '$cmd' failed : $result", 1); 
513                 }
515             }
516         }
517     }
519     return;
523 ###############################################################################
524 =over 
526 =item B<mailqueue_del ($$)>
528 =over
530 =item description 
532     Executes '/usr/sbin/postsuper -d' and deletes mail from queue.
534 =item parameter
536     $msg - STRING - complete GOsa-si message
537     $msg_hash - HASHREF - content of GOsa-si message in a hash
539 =item GOsa-si message xml content
541     <msg_id> - STRING - postfix mail id
543 =item return 
545 Nothing.
547 =back
549 =back
551 =cut
552 ###############################################################################
553 sub mailqueue_del {
554     my ($msg, $msg_hash) = @_;
555     my $header = @{$msg_hash->{'header'}}[0];
556     my $source = @{$msg_hash->{'source'}}[0];
557     my $target = @{$msg_hash->{'target'}}[0];
558     my $session_id = @{$msg_hash->{'session_id'}}[0];
559     my @msg_ids = @{$msg_hash->{'msg_id'}};
560     my $error = 0;
561     my $error_string;
563     # sanity check of input
564     if (not exists $msg_hash->{'msg_id'}) {
565         $error_string = "Message doesn't contain a XML tag 'msg_id'"; 
566         &main::daemon_log("ERROR: $error_string : $msg", 1);
567         $error = 1;
568     } elsif (ref @{$msg_hash->{'msg_id'}}[0] eq "HASH") { 
569         $error_string = "XML tag 'msg_id' is empty";
570         &main::daemon_log("ERROR: $error_string : $msg", 1);
571         $error = 1;
572     }
573         
574     if (not $error) {
575         my @msg_ids = @{$msg_hash->{'msg_id'}};
576         foreach my $msg_id (@msg_ids) {
577             my $error = 0;   # clear error status
579             # sanity check of each msg_id
580             if (not $msg_id =~ /^[0-9A-Z]{10,12}$/) {
581                 $error = 1;
582                 $error_string = "message ID is not valid ([0-9A-Z]{10,12}) : $msg_id";
583                 &main::daemon_log("ERROR: $error_string : $msg", 1);
584             }
586             if (not $error) {
587                 my $cmd = "/usr/sbin/postsuper -d $msg_id 2>&1";
588                 &main::daemon_log("DEBUG: run '$cmd'", 7); 
589                 my $result = qx($cmd);
590                 if ($result =~ /^postsuper: ([0-9A-Z]{10}): removed/ ) {
591                     &main::daemon_log("INFO: Mail $msg_id deleted", 5);
592                 } elsif ($result eq "") {
593                     &main::daemon_log("WARNING: Cannot remove mail '$msg_id', mail not found!", 3);
595                 } else {
596                     &main::daemon_log("ERROR: '$cmd' failed : $result", 1); 
597                 }
599             }
600         }
601     }
603     return;
606 ###############################################################################
607 =over 
609 =item B<mailqueue_header ($$)>
611 =over
613 =item description 
615     Executes 'postcat -q', parse the informations and return them. 
617 =item parameter
619     $msg - STRING - complete GOsa-si message
620     $msg_hash - HASHREF - content of GOsa-si message in a hash
622 =item GOsa-si message xml content
624     <msg_id> - STRING - postfix mail id
626 =item return 
628     $out_msg - STRING - GOsa-si valid xml message containing recipient, sender and subject.
630 =back
632 =back
634 =cut
635 ###############################################################################
636 sub mailqueue_header {
637     my ($msg, $msg_hash) = @_;
638     my $header = @{$msg_hash->{'header'}}[0];
639     my $source = @{$msg_hash->{'source'}}[0];
640     my $target = @{$msg_hash->{'target'}}[0];
641     my $session_id = @{$msg_hash->{'session_id'}}[0];
642     my $error = 0;
643     my $error_string;
644     my $sender;
645     my $recipient;
646     my $subject;
647     my $out_hash;
648     my $out_msg;
650     # sanity check of input
651     if (not exists $msg_hash->{'msg_id'}) {
652         $error_string = "Message doesn't contain a XML tag 'msg_id'"; 
653         &main::daemon_log("ERROR: $error_string : $msg", 1);
654         $error = 1;
655     } elsif (ref @{$msg_hash->{'msg_id'}}[0] eq "HASH") { 
656         $error_string = "XML tag 'msg_id' is empty";
657         &main::daemon_log("ERROR: $error_string : $msg", 1);
658         $error = 1;
659     }
661     # sanity check of each msg_id
662     my $msg_id;
663     if (not $error) {
664         $msg_id = @{$msg_hash->{'msg_id'}}[0];
665         if (not $msg_id =~ /^[0-9A-Z]{10,12}$/) {
666             $error = 1;
667             $error_string = "message ID is not valid ([0-9A-Z]{10,12}) : $msg_id";
668             &main::daemon_log("ERROR: $error_string : $msg", 1);
669         }
670     }
672     # parsing information
673     my $msg_header;
674     if (not $error) {
675         my $cmd = "postcat -q $msg_id";
676         &main::daemon_log("DEBUG: run '$cmd'", 7); 
677         my $result = qx($cmd);
679         my @header_l = split(/\n\n/, $result);
680         $msg_header = $header_l[0];
681     }       
683     # create outgoing msg
684     $out_hash = &main::create_xml_hash("answer_$session_id", $target, $source);
685     &add_content2xml_hash($out_hash, "session_id", $session_id);
686     &add_content2xml_hash($out_hash, "error", $error);
687     if (defined @{$msg_hash->{'forward_to_gosa'}}[0]){
688         &add_content2xml_hash($out_hash, "forward_to_gosa", @{$msg_hash->{'forward_to_gosa'}}[0]);
689     }
691     # add error infos to outgoing msg
692     if ($error) {
693         &add_content2xml_hash($out_hash, "error_string", $error_string);
694         $out_msg = &main::create_xml_string($out_hash);
696     # add mail infos to outgoing msg
697     } else {
698         #&add_content2xml_hash($out_hash, "msg_header", &decode_base64($msg_header));        
699         &add_content2xml_hash($out_hash, "msg_header", $msg_header);        
700         $out_msg = &main::create_xml_string($out_hash);
701     }
702  
703     return $out_msg;
706 sub _exec_op {
707     my ($a, $op, $b) = @_ ;
708     my $res;
710     if ($op eq "eq") {
711         $res = $a =~ /$b/ ? 1 : 0 ;
712     } elsif ($op eq "gt") {
713         $res = $a > $b ? 1 : 0 ;
714     } elsif ($op eq "lt") {
715         $res = $a < $b ? 1 : 0 ;
716     } 
718     return $res;
721 my $mo_hash = { "Jan"=>'01', "Feb"=>'02',"Mar"=>'03',"Apr"=>'04',"May"=>'05',"Jun"=>'06',
722     "Jul"=>'07',"Aug"=>'08',"Sep"=>'09',"Oct"=>'10',"Nov"=>'11',"Dec"=>'12'};
724 sub _parse_mailq_time {
725     my ($time) = @_ ;
727     my $local_time = &get_time();
728     my $local_year = substr($local_time,0,4);     
730     my ($dow, $mo, $dd, $date) = split(/\s/, $time);
731     my ($hh, $mi, $ss) = split(/:/, $date);
732     my $mailq_time = $local_year.$mo_hash->{$mo}."$dd$hh$mi$ss"; 
734     # This is realy nasty
735     if (int($local_time) < int($mailq_time)) {
736         # Mailq_time is in the future, this cannot be possible, so mail must be from last year
737         $mailq_time = int($local_year) - 1 .$mo_hash->{$mo}."$dd$hh$mi$ss";
738     }
740     return $mailq_time;
743 # vim:ts=4:shiftwidth:expandtab
745 1;