From 312ca478fb59805a3966b1d29b10a7b753f1d3f2 Mon Sep 17 00:00:00 2001 From: hickert Date: Fri, 13 Jul 2007 12:44:09 +0000 Subject: [PATCH] =?utf8?q?Added=20sieve=20vacation=20script=20from=20Frank?= =?utf8?q?=20M=C3=B6ller?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@6860 594d385d-05f5-0310-b6e9-bd551577e9d8 --- contrib/scripts/sieve_vacation/IMAP/Sieve.pm | 401 +++++++++++++++ .../scripts/sieve_vacation/update-vacation.pl | 477 ++++++++++++++++++ 2 files changed, 878 insertions(+) create mode 100644 contrib/scripts/sieve_vacation/IMAP/Sieve.pm create mode 100755 contrib/scripts/sieve_vacation/update-vacation.pl diff --git a/contrib/scripts/sieve_vacation/IMAP/Sieve.pm b/contrib/scripts/sieve_vacation/IMAP/Sieve.pm new file mode 100644 index 000000000..ec108083c --- /dev/null +++ b/contrib/scripts/sieve_vacation/IMAP/Sieve.pm @@ -0,0 +1,401 @@ +# $Id: Sieve.pm,v 0.4.9b 2001/06/15 19:25:00 alain Exp $ + +package IMAP::Sieve; + +use strict; +use Carp; +use IO::Select; +use IO::Socket; +use IO::Socket::INET; +#use Text::ParseWords qw(parse_line); +use Cwd; + +use vars qw($VERSION); + +$VERSION = '0.4.9b'; + +sub new { + my $class = shift; + my $self = {}; + bless $self, $class; + if ((scalar(@_) % 2) != 0) { + croak "$class called with incorrect number of arguments"; + } + while (@_) { + my $key = shift(@_); + my $value = shift(@_); + $self->{$key} = $value; + } + $self->{'CLASS'} = $class; + $self->_initialize; + return $self; +} + +sub _initialize { + my $self = shift; + my ($len,$userpass,$encode); + if (!defined($self->{'Server'})) { + croak "$self->{'CLASS'} not initialized properly : Server parameter missing"; + } + if (!defined($self->{'Port'})) { + $self->{'Port'} = 2000; # default sieve port; + } + if (!defined($self->{'Login'})) { + croak "$self->{'CLASS'} not initialized properly : Login parameter missing"; + } + if (!defined($self->{'Password'})) { + croak "$self->{'CLASS'} not initialized properly : Password parameter missing"; + } + if (!defined($self->{'Proxy'})) { + $self->{'Proxy'} = ''; # Proxy; + } + if (defined($self->{'SSL'})) { + my $cwd= cwd; + my %ssl_defaults = ( + 'SSL_use_cert' => 0, + 'SSL_verify_mode' => 0x00, + 'SSL_key_file' => $cwd."/certs/client-key.pem", + 'SSL_cert_file' => $cwd."/certs/client-cert.pem", + 'SSL_ca_path' => $cwd."/certs", + 'SSL_ca_file' => $cwd."/certs/ca-cert.pem", + ); + my @ssl_options; + my $ssl_key; + my $key; + foreach $ssl_key (keys(%ssl_defaults)) { + if (!defined($self->{$ssl_key})) { + $self->{$ssl_key} = $ssl_defaults{$ssl_key}; + } + } + foreach $ssl_key (keys(%{$self})) { + if ($ssl_key =~ /^SSL_/) { + push @ssl_options, $ssl_key,$self->{$ssl_key}; + } + } + my $SSL_try="use IO::Socket::SSL"; + eval $SSL_try; + if (!eval {$self->{'Socket'} = + IO::Socket::SSL->new(PeerAddr => $self->{'Server'}, + PeerPort => $self->{'Port'}, + Proto => 'tcp', + Reuse => 1, + Timeout => 5, + @ssl_options);}) { + $self->_error("initialize", "couldn't establish a sieve SSL connection to",$self->{'Server'}, "[$!]","path=$cwd"); + delete $self->{'Socket'}; + return; + } + } + else { + + if (!eval {$self->{'Socket'} = IO::Socket::INET->new(PeerAddr => $self->{'Server'}, + PeerPort => $self->{'Port'}, + Proto => 'tcp', + Reuse => 1); }) + { + $self->_error("initialize", "could'nt establish a Sieve connection to",$self->{'Server'}); + return; + } + } # if SSL + + my $fh = $self->{'Socket'}; + $_ = $self->_read; #get banner + my $try=$_; + if (!/timsieved/i) { + $self->close; + $self->_error("initialize","bad response from",$self->{'Server'},$try); + return; + } + chomp; + if (/\r$/) { + chop; + } + if (/IMPLEMENTATION/) { + $self->{'Implementation'}=$1 if /^"IMPLEMENTATION" +"(.*)"/; + #version 2 of cyrus imap/timsieved + # get capability + # get OK as well + $_=$self->_read; + while (!/^OK/) { + $self->{'Capability'}=$1 if /^"SASL" +"(.*)"/; + $self->{'Sieve'}=$1 if /^"SIEVE" +"(.*)"/; + $_ = $self->_read; +## $_=$self->_read; + } + } + else { + $self->{'Capability'}=$_; + } + $userpass = "$self->{'Proxy'}\x00".$self->{'Login'}."\x00".$self->{'Password'}; + $encode=encode_base64($userpass); + $len=length($encode); + print $fh "AUTHENTICATE \"PLAIN\" {$len+}\r\n"; + + print $fh "$encode\r\n"; + + $_ = $self->_read; + $try=$_; + if ($try=~/NO/) { + $self->close; + $self->_error("Login incorrect while connecting to $self->{'Server'}", $try); + return; + } elsif (/OK/) { + $self->{'Error'}= "No Errors"; + return; + } else { + #croak "$self->{'CLASS'}: Unknown error -- $_"; + $self->_error("Unknown error",$try); + return; + } + $self->{'Error'}="No Errors"; + return; +} +sub encode_base64 ($;$) +{ + my $res = ""; + my $eol = $_[1]; + $eol = "\n" unless defined $eol; + pos($_[0]) = 0; # ensure start at the beginning + while ($_[0] =~ /(.{1,45})/gs) { + $res .= substr(pack('u', $1), 1); + chop($res); + } + $res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs + # fix padding at the end + my $padding = (3 - length($_[0]) % 3) % 3; + $res =~ s/.{$padding}$/'=' x $padding/e if $padding; + # break encoded string into lines of no more than 76 characters each + if (length $eol) { + $res =~ s/(.{1,76})/$1$eol/g; + } + $res; +} + + +sub _error { + my $self = shift; + my $func = shift; + my @error = @_; + + $self->{'Error'} = join(" ",$self->{'CLASS'}, "[", $func, "]:", @error); +} + +sub _read { + my $self = shift; + my $buffer =""; + my $char = ""; + my $bytes= 1; + while ($bytes == 1) { + $bytes = sysread $self->{'Socket'},$char,1; + if ($bytes == 0) { + if (length ($buffer) != 0) { + return $buffer; + } + else { + return; + } + } + else { + if (($char eq "\n") or ($char eq "\r")) { + if (length($buffer) ==0) { + # remove any cr or nl leftover + } + else { + return $buffer; + } + } + else { + $buffer.=$char; + } + } + } +} + + +sub close { + my $self = shift; + if (!defined($self->{'Socket'})) { + return 0; + } + my $fh =$self->{'Socket'}; + print $fh "LOGOUT\r\n"; + close($self->{'Socket'}); + delete $self->{'Socket'}; +} + +sub putscript { + my $self = shift; + my $len; + + if (scalar(@_) != 2) { + $self->_error("putscript", "incorrect number of arguments"); + return 1; + } + + my $scriptname = shift; + my $script = shift; + + if (!defined($self->{'Socket'})) { + $self->_error("putscript", "no connection open to", $self->{'Server'}); + return 1; + } + $len=length($script); + my $fh = $self->{'Socket'}; + print $fh "PUTSCRIPT \"$scriptname\" {$len+}\r\n"; + print $fh "$script\r\n"; + $_ = $self->_read; + if (/^OK/) { + $self->{'Error'} = 'No Errors'; + return 0; + } else { + $self->_error("putscript", "couldn't save script", $scriptname, ":", $_); + return 1; + } +} + +sub deletescript { + my $self = shift; + + if (scalar(@_) != 1) { + $self->_error("deletescript", "incorrect number of arguments"); + return 1; + } + my $script = shift; + if (!defined($self->{'Socket'})) { + $self->_error("deletescript", "no connection open to", $self->{'Server'}); + return 1; + } + my $fh = $self->{'Socket'}; + print $fh "DELETESCRIPT \"$script\"\r\n"; + $_ = $self->_read; + if (/^OK/) { + $self->{'Error'} = 'No Errors'; + return 0; + } else { + $self->_error("deletescript", "couldn't delete", $script, ":", $_); + return 1; + } +} +sub getscript { # returns a string + my $self = shift; + my $allscript; + + if (scalar(@_) != 1) { + $self->_error("getscript", "incorrect number of arguments"); + return 1; + } + my $script = shift; + if (!defined($self->{'Socket'})) { + $self->_error("getscript", "no connection open to", $self->{'Server'}); + return 1; + } + my $fh = $self->{'Socket'}; + print $fh "GETSCRIPT \"$script\"\r\n"; + $_ = $self->_read; + if (/^{.*}/) { $_ = $self->_read; } # remove file size line + + # should probably use the file size to calculate how much to read in + while ((!/^OK/) && (!/^NO/)) { + $_.="\n" if $_ !~/\n.*$/; # replace newline that _read removes + $allscript.=$_; + $_ = $self->_read; + } + if (/^OK/) { + return $allscript; + } else { + $self->_error("getscript", "couldn't get script", $script, ":", $_); + return; + } +} + +sub setactive { + my $self = shift; + + if (scalar(@_) != 1) { + $self->_error("setactive", "incorrect number of arguments"); + return 1; + } + my $script = shift; + if (!defined($self->{'Socket'})) { + $self->_error("setactive", "no connection open to", $self->{'Server'}); + return 1; + } + my $fh = $self->{'Socket'}; + print $fh "SETACTIVE \"$script\"\r\n"; + $_ = $self->_read; + if (/^OK/) { + $self->{'Error'} = "No Errors"; + return 0; + } else { + $self->_error("setactive", "couldn't set as active", $script, ":", $_); + return 1; + } +} + + +sub noop { + my $self = shift; + my ($id, $acl); + + if (!defined($self->{'Socket'})) { + $self->_error("noop", "no connection open to", $self->{'Server'}); + return 1; + } + my $fh = $self->{'Socket'}; + print $fh "NOOP\r\n"; + $_ = $self->_read; + if (!/^OK/) { + $self->_error("noop", "couldn't do noop" + ); + return 1; + } + $self->{'Error'} = 'No Errors'; + return 0; +} + + +sub listscripts { + my $self = shift; + my (@scripts); + + if (!defined($self->{'Socket'})) { + $self->_error("listscripts", "no connection open to", $self->{'Server'}); + return; + } + + #send the command + $self->{'Socket'}->print ("LISTSCRIPTS\r\n"); + + # While we have more to read + while (defined ($_ = $self->_read)) { + + # Exit the loop if we're at the end of the text + last if (m/^OK.*/); + + # Select the stuff between the quotes (without the asterisk) + # m/^"([^"]+?)\*?"\r?$/; + # Select including the asterisk (to determine the default script) +# m/^"([^"]+?\*?)"\r?$/; + $_=~s/"//g; + # Get the name of the script + push @scripts, $_; + } + + if (/^OK/) { + return @scripts; + } else { + + + + } + if (/^OK/) { + return @scripts; + } else { + $self->_error("list", "couldn't get list for", ":", $_); + return; + } +} + +1; +__END__ + diff --git a/contrib/scripts/sieve_vacation/update-vacation.pl b/contrib/scripts/sieve_vacation/update-vacation.pl new file mode 100755 index 000000000..63d1d2b53 --- /dev/null +++ b/contrib/scripts/sieve_vacation/update-vacation.pl @@ -0,0 +1,477 @@ +#!/usr/bin/perl -w -I. +# +# This code is part of GOsa (https://gosa.gonicus.de) +# Copyright (C) 2007 Frank Moeller +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +use strict; +use IMAP::Sieve; +use XML::Simple; +use Data::Dumper; +use Net::LDAP; +use utf8; +use Getopt::Std; +use vars qw/ %opt /; + +# +# Definitions +# +my $gosa_config = "/etc/gosa/gosa.conf"; +my $opt_string = 'l:h'; +my $location = ""; +my $today = time (); +# default mailMethod = kolab +my $server_attribute = "kolabHomeServer"; +my $alternate_address_attribute = "alias"; +my $gosa_sieve_script_name = "gosa"; +my $simple_bind_dn = ""; +my $simple_bind_dn_pwd = ""; +my $gosa_sieve_script_status = "FALSE"; +my $sieve_vacation = ""; +my $gosa_sieve_spam_header = "Sort mails with higher spam level"; + +# +# Templates +# +my $gosa_sieve_header = "\#\#\#GOSA\nrequire\ \[\"fileinto\",\ \"reject\",\ \"vacation\"\]\;\n\n"; +my $vacation_header_template = "\# Begin vacation message"; +my $vacation_footer_template = "\# End vacation message"; + +# +# Usage +# +sub usage { + die "Usage:\nperl $0 [option]\n\n\tOptions:\n\t\t-l <\"location name\">\tuse special location\n\t\t-h\t\t\tthis help \n"; +} + +# +# Config import +# +sub read_config { + my $input = shift || die "need config file: $!"; + my $stream = ""; + open ( FILE, "< $input" ) or die "Error opening file $input: $! \n"; + { + local $/ = undef; + $stream = ; + } + close ( FILE ); + return $stream; +} + +# +# XML parser +# +sub parseconfig { + my $c_location = shift; + my $xmldata = shift; + my $xml = new XML::Simple (); + my $c_data = $xml -> XMLin( $xmldata ); + my $config = {}; + my $server = $c_data->{main}->{location}->{$c_location}->{server}; + my $config_base = $c_data->{main}->{location}->{$c_location}->{config}; + my $ldap_admin = $c_data->{main}->{location}->{$c_location}->{referral}->{admin}; + my $ldap_admin_pwd = $c_data->{main}->{location}->{$c_location}->{referral}->{password}; + my $mailMethod = $c_data->{main}->{location}->{$c_location}->{mailMethod}; + $config->{server} = $server; + $config->{config_base} = $config_base; + $config->{mailMethod} = $mailMethod; + $config->{ldap_admin} = $ldap_admin; + $config->{ldap_admin_pwd} = $ldap_admin_pwd; + + return $config; +} + +# +# Get default location +# +sub get_default_location { + my $xmldata = shift; + my $xml = new XML::Simple ( RootName=>'conf' ); + my $c_data = $xml -> XMLin( $xmldata ); + my $default = $c_data->{main}->{default}; + + return $default; +} + +# +# LDAP error handling +# +sub ldap_error { + my ($from, $mesg) = @_; + print "Return code: ", $mesg->code; + print "\tMessage: ", $mesg->error_name; + print " :", $mesg->error_text; + print "MessageID: ", $mesg->mesg_id; + print "\tDN: ", $mesg->dn; +} + + +# +# LDAP search +# +sub ldap_search { + my $url = shift; + my $searchString = shift; + my $scope = shift; + my $base = shift; + my $attrs = shift; + my $bind_dn = shift; + my $bind_dn_pwd = shift; + + if ( $base eq "NULL" ) { + $base = ""; + } + my $ldap = Net::LDAP->new( $url ) or die "$@"; + if ( ( ! ( $bind_dn ) ) || ( ! ( $bind_dn_pwd ) ) ) { + $ldap->bind; + } else { + $ldap->bind ( $bind_dn, password => $bind_dn_pwd ); + } + + my $result = $ldap->search ( base => "$base", + scope => "$scope", + filter => "$searchString", + attrs => $attrs + ); + if ( $result->code ) { + ldap_error ( "Searching", $result ); + } + + $ldap->unbind; + + return $result; +} + +# +# Retrieve LDAP base +# +sub get_ldap_base { + my $url = shift; + my $config_base = shift; + my $bind_dn = shift; + my $bind_dn_pwd = shift; + my $filter = "(objectClass=*)"; + my $init_base = "NULL"; + my $scope = "base"; + my $attributes = [ 'namingcontexts' ]; + my $entry = {}; + my $base = ""; + + $config_base =~ s/\,\ +/\,/g; + print $url."\n"; + print $config_base."\n"; + my $result = ldap_search ( $url, $filter, $scope, $init_base, $attributes, $bind_dn, $bind_dn_pwd ); + my @entries = $result->entries; + my $noe = @entries; + print $noe."\n"; + foreach $entry ( @entries ) { + my $tmp = $entry->get_value ( 'namingcontexts' ); + print $tmp."\n"; + $tmp =~ s/\,\ +/\,/g; + if ( $config_base =~ m/$tmp/ ) { + $base = $entry->get_value ( 'namingcontexts' ); + } + } + + return $base; +} + +# +# SIEVE functions +# +sub opensieve { + my $admin = shift; + my $pass = shift; + my $user = shift; + my $server = shift; + my $port = shift; + + print ( "##### Proxy => $user, Server => $server, Login => $admin, Password => $pass, Port => $port ####\n" ); + + my $sieve = IMAP::Sieve->new ( 'Proxy' => $user, 'Server' => $server, 'Login' => $admin, 'Password' => $pass, 'Port' => $port ); + return $sieve; +} + +sub closesieve { + my $sieve = shift; + + if ($sieve) {$sieve->close}; +} + +sub listscripts { + my $sieve = shift; + + my @scripts = $sieve->listscripts; + my $script_list = join("\n",@scripts)."\n"; + return $script_list; +} + +sub getscript { + my $sieve = shift; + my $script = shift; + my $scriptfile; + chomp $script; + #print "$sieve\n"; + #print "$script\n"; + + $scriptfile = $sieve->getscript($script); + return $scriptfile; +} + +sub putscript { + my $sieve = shift; + my $scriptname = shift; + my $script = shift; + print "$sieve\n"; + print "$scriptname\n"; + print "$script\n"; + + my $res=$sieve->putscript($scriptname,$script); + if ($res) {print $sieve->{'Error'}} + return; +} + +sub setactive { + my $sieve = shift; + my $script = shift; + + my $res=$sieve->setactive($script); + if ($res) { print $sieve->{'Error'};} + return; +} + +# +# main () +# +# read options +getopts( "$opt_string", \%opt ); + +# read GOsa config +my $input_stream = read_config ( $gosa_config ); + +# get location +if ( $opt{l} ) { + $location = $opt{l}; +} elsif ( $opt{h} ) { + usage (); + exit (0); +} else { + $location = get_default_location ( $input_stream ); +} +print "$location\n"; + +# parse config +my $config = parseconfig ( $location, $input_stream ); +my $ldap_url = $config->{server}; +my $gosa_config_base = $config->{config_base}; +my $bind_dn = $config->{ldap_admin}; +my $bind_dn_pwd = $config->{ldap_admin_pwd}; +my $mailMethod = $config->{mailMethod}; +utf8::encode($ldap_url); +utf8::encode($gosa_config_base); +utf8::encode($mailMethod); + +if ( $mailMethod =~ m/cyrus/i ) { + my $server_attribute = "gosaMailServer"; + my $alternate_address_attribute = "gosaMailAlternateAddress"; +} + +# determine LDAP base +my $ldap_base = get_ldap_base ( $ldap_url, $gosa_config_base, $simple_bind_dn, $simple_bind_dn_pwd ); + +# retrieve user informations with activated vacation feature +my $filter = "(&(objectClass=gosaMailAccount)(gosaMailDeliveryMode=*V*)(!(gosaMailDeliveryMode=*C*)))"; +my $list_of_attributes = [ 'uid', 'mail', $alternate_address_attribute, 'gosaVacationMessage', 'gosaVacationStart', 'gosaVacationStop', $server_attribute ]; +my $search_scope = "sub"; +my $result = ldap_search ( $ldap_url, $filter, $search_scope, $ldap_base, $list_of_attributes, $simple_bind_dn, $simple_bind_dn_pwd ); + +my @entries = $result->entries; +my $entry = {}; +foreach $entry ( @entries ) { + my $uid_v = $entry->get_value ( 'uid' ); + my $mail_v = $entry->get_value ( 'mail' ); + my @mailalternate = $entry->get_value ( $alternate_address_attribute ); + my $vacation = $entry->get_value ( 'gosaVacationMessage' ); + my $start_v = $entry->get_value ( 'gosaVacationStart' ); + my $stop_v = $entry->get_value ( 'gosaVacationStop' ); + my $server_v = $entry->get_value ( $server_attribute ); + if ( ! ( $uid_v ) ) { + $uid_v = ""; + } + if ( ! ( $mail_v ) ) { + $mail_v = ""; + } + my @mailAddress = ($mail_v); + my $alias = ""; + foreach $alias ( @mailalternate ) { + push @mailAddress, $alias; + } + my $addresses = ""; + foreach $alias ( @mailAddress ) { + $addresses .= "\"" . $alias . "\", "; + } + $addresses =~ s/\ *$//; + $addresses =~ s/\,$//; + if ( ! ( $vacation ) ) { + $vacation = ""; + } + if ( ! ( $start_v ) ) { + $start_v = 0; + } + if ( ! ( $stop_v ) ) { + $stop_v = 0; + } + if ( ! ( $server_v ) ) { + $server_v = ""; + next; + } + print $uid_v . " | " . + $addresses . " | " . + "\n"; + + my ($sieve_user, $tmp) = split ( /\@/, $mail_v ); + + if ( ( $today >= $start_v ) && ( $today < $stop_v ) ) { + print "activating vacation for user $uid_v\n"; + + my $srv_filter = "(&(goImapName=$server_v)(objectClass=goImapServer))"; + my $srv_list_of_attributes = [ 'goImapSieveServer', 'goImapSievePort', 'goImapAdmin', 'goImapPassword' ]; + my $srv_result = ldap_search ( $ldap_url, $srv_filter, $search_scope, $ldap_base, $srv_list_of_attributes, $bind_dn, $bind_dn_pwd ); + my @srv_entries = $srv_result->entries; + my $srv_entry = {}; + my $noe = @srv_entries; + if ( $noe == 0 ) { + printf STDERR "Error: no $server_attribute defined! Aboarting..."; + } elsif ( $noe > 1 ) { + printf STDERR "Error: multiple $server_attribute defined! Aboarting..."; + } else { + my $goImapSieveServer = $srv_entries[0]->get_value ( 'goImapSieveServer' ); + my $goImapSievePort = $srv_entries[0]->get_value ( 'goImapSievePort' ); + my $goImapAdmin = $srv_entries[0]->get_value ( 'goImapAdmin' ); + my $goImapPassword = $srv_entries[0]->get_value ( 'goImapPassword' ); + if ( ( $goImapSieveServer ) && ( $goImapSievePort ) && ( $goImapAdmin ) && ( $goImapPassword ) ) { + my $sieve = opensieve ( $goImapAdmin, $goImapPassword, $sieve_user, $goImapSieveServer, $goImapSievePort); + my @sieve_scripts = listscripts ( $sieve ); + my $script_name = ""; + if ( @sieve_scripts ) { + foreach $script_name ( @sieve_scripts ) { + if ( $script_name =~ m/$gosa_sieve_script_name/ ) { + $gosa_sieve_script_status = "TRUE"; + } + } + if ( $gosa_sieve_script_status eq "TRUE" ) { + print "retrieving and modifying gosa sieve script\n"; + # requirements + my $sieve_script = getscript( $sieve, $gosa_sieve_script_name ); + #print "$sieve_script\n"; + if ( ! ( $sieve_script ) ) { + print "No Sieve Script! Creating New One!\n"; + $sieve_script = $gosa_sieve_header; + } + if ( $sieve_script =~ m/require.*\[.*["|'] *vacation *["|'].*\]/ ) { + print "require vacation ok\n"; + } else { + print "require vacation not ok\n"; + print "modifying require statement\n"; + $sieve_script =~ s/require(.*\[.*)\]/require$1\, "vacation"\]/; + } + if ( ! ( $sieve_script =~ m/$vacation_header_template/ ) ) { + print "no match header template\n"; + $sieve_vacation = $vacation_header_template . + "\n" . + "vacation :addresses [$addresses]\n" . + "\"" . + $vacation . + "\n\"\;" . + "\n" . + $vacation_footer_template . + "\n\n"; + } + #print ( "$sieve_vacation\n" ); + #print ( "$sieve_script\n" ); + # including vacation message + if ( $sieve_script =~ m/$gosa_sieve_spam_header/ ) { + print "MATCH\n"; + $sieve_script =~ s/($gosa_sieve_spam_header[^{}]*{[^{}]*})/$1\n\n$sieve_vacation/; + } else { + $sieve_script =~ s/require(.*\[.*\])/require$1\n\n$sieve_vacation/; + } + print ( "START SIEVE $sieve_script\nSTOP SIEVE" ); + # uploading new sieve script + putscript( $sieve, $gosa_sieve_script_name, $sieve_script ); + # activating new sieve script + setactive( $sieve, $gosa_sieve_script_name ); + } else { + print "no gosa script available, creating new one"; + my $sieve_script = $gosa_sieve_header . "\n\n" . $sieve_vacation; + # uploading new sieve script + putscript( $sieve, $gosa_sieve_script_name, $sieve_script ); + # activating new sieve script + setactive( $sieve, $gosa_sieve_script_name ); + } + } + } + } + } elsif ( $today >= $stop_v ) { + print "deactivating vacation for user $uid_v\n"; + + my $srv_filter = "(&(goImapName=$server_v)(objectClass=goImapServer))"; + my $srv_list_of_attributes = [ 'goImapSieveServer', 'goImapSievePort', 'goImapAdmin', 'goImapPassword' ]; + my $srv_result = ldap_search ( $ldap_url, $srv_filter, $search_scope, $ldap_base, $srv_list_of_attributes, $bind_dn, $bind_dn_pwd ); + my @srv_entries = $srv_result->entries; + my $srv_entry = {}; + my $noe = @srv_entries; + if ( $noe == 0 ) { + printf STDERR "Error: no $server_attribute defined! Aboarting..."; + } elsif ( $noe > 1 ) { + printf STDERR "Error: multiple $server_attribute defined! Aboarting..."; + } else { + my $goImapSieveServer = $srv_entries[0]->get_value ( 'goImapSieveServer' ); + my $goImapSievePort = $srv_entries[0]->get_value ( 'goImapSievePort' ); + my $goImapAdmin = $srv_entries[0]->get_value ( 'goImapAdmin' ); + my $goImapPassword = $srv_entries[0]->get_value ( 'goImapPassword' ); + if ( ( $goImapSieveServer ) && ( $goImapSievePort ) && ( $goImapAdmin ) && ( $goImapPassword ) ) { + my $sieve = opensieve ( $goImapAdmin, $goImapPassword, $sieve_user, $goImapSieveServer, $goImapSievePort); + my @sieve_scripts = listscripts ( $sieve ); + my $script_name = ""; + if ( @sieve_scripts ) { + foreach $script_name ( @sieve_scripts ) { + if ( $script_name =~ m/$gosa_sieve_script_name/ ) { + $gosa_sieve_script_status = "TRUE"; + } + } + if ( $gosa_sieve_script_status eq "TRUE" ) { + # removing vacation part + my $sieve_script = getscript( $sieve, $gosa_sieve_script_name ); + if ( $sieve_script ) { + print "OLD SIEVE SCRIPT:\n$sieve_script\n\n"; + #$sieve_script =~ s/$vacation_header_template[^#]Yp.*$vacation_footer_template//; + $sieve_script =~ s/$vacation_header_template[^#]*$vacation_footer_template//; + print "NEW SIEVE SCRIPT:\n$sieve_script\n\n"; + # uploading new sieve script + putscript( $sieve, $gosa_sieve_script_name, $sieve_script ); + # activating new sieve script + setactive( $sieve, $gosa_sieve_script_name ); + } + } + } + } + } + } else { + print "no vacation process necessary\n"; + } +} -- 2.30.2