Code

Added sieve vacation script from Frank Möller
authorhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Fri, 13 Jul 2007 12:44:09 +0000 (12:44 +0000)
committerhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Fri, 13 Jul 2007 12:44:09 +0000 (12:44 +0000)
git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@6860 594d385d-05f5-0310-b6e9-bd551577e9d8

contrib/scripts/sieve_vacation/IMAP/Sieve.pm [new file with mode: 0644]
contrib/scripts/sieve_vacation/update-vacation.pl [new file with mode: 0755]

diff --git a/contrib/scripts/sieve_vacation/IMAP/Sieve.pm b/contrib/scripts/sieve_vacation/IMAP/Sieve.pm
new file mode 100644 (file)
index 0000000..ec10808
--- /dev/null
@@ -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 (executable)
index 0000000..63d1d2b
--- /dev/null
@@ -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 = <FILE>;
+       }
+       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";
+       }
+}