ACC SHELL

Path : /var/lib/ntp/proc/self/root/usr/share/YaST2/modules/YaPI/
File Upload :
Current File : //var/lib/ntp/proc/self/root/usr/share/YaST2/modules/YaPI/MailServer.pm

=head1 NAME

YaPI::MailServer

=head1 PREFACE

This package is the public Yast2 API to configure the postfix.
Representation of the configuration of mail-server.
Input and output routines.

=head1 SYNOPSIS

use YaPI::MailServer


=head1 DESCRIPTION

B<YaPI::MailServer>  is a collection of functions that implement a mail server
configuration API to for Perl programs.

=over 2

=cut




package YaPI::MailServer;

use strict;
use vars qw(@ISA);

use ycp;
use YaST::YCP;
use YaPI;
@YaPI::MailServer::ISA = qw( YaPI );

use POSIX;     # Needed for setlocale()
use Data::Dumper;
use Net::IMAP;

textdomain("mail");
our %TYPEINFO;
our @CAPABILITIES = (
                     'SLES10'
                    );
our $VERSION="2.2.0";

YaST::YCP::Import ("SCR");
YaST::YCP::Import ("Service");
YaST::YCP::Import ("Ldap");
YaST::YCP::Import ("NetworkInterfaces");

##
 #
my $proposal_valid = 0;

##
 # Some global variables
my $imapadm  = "cyrus";
my $imaphost = "localhost";
my $aconf    = "/etc/amavisd.conf";

##
 # Write only, used during autoinstallation.
 # Don't run services and SuSEconfig, it's all done at one place.
 #
my $write_only = 0;

BEGIN { $TYPEINFO{ReadMasterCF}  =["function", "any"  ]; }
sub ReadMasterCF {
    my $MasterCf  = SCR->Read('.mail.postfix.mastercf');

    return $MasterCf;
}

BEGIN { $TYPEINFO{findService}  =["function", "any"  ]; }
sub findService {
    my ($service, $command ) = @_;

    my $services  = SCR->Read('.mail.postfix.mastercf.findService', $service, $command);

    return $services;
}
=item *
C<$GlobalSettings = ReadGlobalSettings($$AdminPassword)>

 Dump the mail-server Global Settings to a single hash
 Return hash Dumped settings (later acceptable by WriteGlobalSettings ())

 $GlobalSettings is a pointer to a hash containing the basic settings of 
 the mail server.

 %GlobalSettings = (
       'Changed'               => 0,
            Shows if the hash was changed. Possible values are 0 (no) or 1 (yes).

       'MaximumMailSize'       => 0,
            Shows the maximum message size in bytes, the mail server will accept 
            to deliver. Setting this value 0 means there is no limit.

       'Banner'                => '$myhostname ESMTP $mail_name'
            The smtpd_banner parameter specifies the text that follows the 220
            code in the SMTP server's greeting banner. Some people like to see
            the mail version advertised. By default, Postfix shows no version.
            You MUST specify $myhostname at the start of the text. That is an
            RFC requirement. Postfix itself does not care.

       'Interfaces'            => ''
            The inet_interfaces parameter specifies the network interface
            addresses that this mail system receives mail on.  By default,
            the software claims all active interfaces on the machine. The
            parameter also controls delivery of mail to user@[ip.address]
       
       'SendingMail'           => {
            In this hash you can define the type of delivery of outgoing emails.
	    
            'Type'          => '',
                Shows the type of the delivery of the outgoing mails. Possible 
                values are: 
	        DNS : Delivery via DNS lookup of the MX records of the
		      destination domain.
		relayhost : Delivery using a relay host
		NONE : There is no delivery of outgoing mails. In this case
		       some other funcions are not avaiable. For example
		       setting of mail transport.
		       
            'TLS'           => '',
	        If delivery via DNS is used you can set how TLS will be used
		for security. Possible values are:
		NONE    : don't use TLS.
		MAY     : TLS will used when offered by the server.
		MUST    : Only connection with TLS will be accepted.
		MUST_NOPEERMATCH  : Only connection with TLS will be accepted, but
		          no strict peername checking accours.
			  
            'RelayHost'     => {
	        If the type of delivery of outgoing emails is set to "relayhost",
		then you have to define the relyhost in this hash.
		
                  'Name'     => '',
		        DNS name or IP address of the relay host.
			
                  'Auth'     => 0,
		        Sets if SASL authentication will be used for the relayhost.
			Possible values are: 0 (no) and 1 (yes).
			
                  'Account'  => '',
		        The account name of the SASL account.
			
                  'Password' => ''
		        The SASL account password
                }
          }
     );

EXAMPLE:

use MailServer;

    my $AdminPassword   = "VerySecure";


=cut

BEGIN { $TYPEINFO{ReadGlobalSettings}  =["function", ["map", "string", "any" ], "string"]; }
sub ReadGlobalSettings {
    my $self            = shift;
    my $AdminPassword   = shift;

    my %GlobalSettings = ( 
                'Changed'               => YaST::YCP::Boolean(0),
                'MaximumMailSize'       => 0,
                'Banner'                => '$myhostname ESMTP $mail_name',
                'SendingMail'           => { 
                         'Type'          => 'DNS',
                         'TLS'           => 'NONE',
                         'RelayHost'     => {
                                'Name'     => '',
                                'Auth'     => 0,
                                'Account'  => '',
                                'Password' => ''
                              }
                         
                       }
          );

    my $MainCf    = SCR->Read('.mail.postfix.main.table');
    my $SaslPaswd = SCR->Read('.mail.postfix.saslpasswd.table');
    if( ! SCR->Read('.mail.postfix.mastercf') )
    {
         return $self->SetError( summary =>"Couln't open master.cf",
                                 code    => "PARAM_CHECK_FAILED" );
    }

    # Reading maximal size of transported messages
    $GlobalSettings{'MaximumMailSize'}  = read_attribute($MainCf,'message_size_limit');

    #
    chomp( $GlobalSettings{'Banner'}     = `postconf -h smtpd_banner`);
    chomp($GlobalSettings{'Interfaces'}  = `postconf -h inet_interfaces`);

    # Determine if relay host is used
    $GlobalSettings{'SendingMail'}{'RelayHost'}{'Name'} = read_attribute($MainCf,'relayhost');

    if($GlobalSettings{'SendingMail'}{'RelayHost'}{'Name'} ne '')
    {
      # If relay host is used read & set some parameters
            $GlobalSettings{'SendingMail'}{'Type'} = 'relayhost';
        
        # Determine if relay host need sasl authentication
        my $tmp = read_attribute($SaslPaswd,$GlobalSettings{'SendingMail'}{'RelayHost'}{'Name'}); 
        if( $tmp )
	{
            ($GlobalSettings{'SendingMail'}{'RelayHost'}{'Account'},$GlobalSettings{'SendingMail'}{'RelayHost'}{'Password'}) 
	                 = split /:/,$tmp;
        }
        if($GlobalSettings{'SendingMail'}{'RelayHost'}{'Account'}  ne '')
	{
           $GlobalSettings{'SendingMail'}{'RelayHost'}{'Auth'} = 1;
        }
    }
    else
    {
	my $smtpsrv = SCR->Execute('.mail.postfix.mastercf.findService',
		{ 'service' => 'smtp',
		  'command' => 'smtp' });
        if( defined $smtpsrv )
	{
            $GlobalSettings{'SendingMail'}{'Type'} = 'DNS';
	}
	else
	{   
            $GlobalSettings{'SendingMail'}{'Type'} = 'NONE';
	}    
    }
    if( $GlobalSettings{'SendingMail'}{'Type'} ne 'NONE')
    {
	    my $USE_TLS          = read_attribute($MainCf,'smtp_use_tls');
	    my $ENFORCE_TLS      = read_attribute($MainCf,'smtp_enforce_tls');
	    my $ENFORCE_PEERNAME = read_attribute($MainCf,'smtp_tls_enforce_peername');
	    if($USE_TLS eq 'no' && $ENFORCE_TLS ne 'yes')
	    {
               $GlobalSettings{'SendingMail'}{'TLS'} = 'NONE';
	    }
	    elsif( $ENFORCE_TLS eq 'yes')
	    {
	      if( $ENFORCE_PEERNAME eq 'no')
	      {
                 $GlobalSettings{'SendingMail'}{'TLS'} = 'MUST_NOPEERMATCH';
	      }
	      else
	      {
                 $GlobalSettings{'SendingMail'}{'TLS'} = 'MUST';
	      } 
	    }
	    else
	    {
                 $GlobalSettings{'SendingMail'}{'TLS'} = 'MAY';
	    }
    }	    
    
    return \%GlobalSettings;
}

=item *
C<boolean = WriteGlobalSettings($GlobalSettings)>

Write the mail-server Global Settings from a single hash
@param settings The YCP structure to be imported.
@return boolean True on success

EXAMPLE:

This example shows the setting up of the mail server bsic configuration
using a relay host with SASL authetication and TLS security.
Furthermore there will be set the maximum mail size, which the mail server
will be accept to deliver, to 10MB.

use MailServer;

    my $AdminPassword   = "VerySecure";

    my %GlobalSettings = (
                   'Changed'               => 1,
                   'MaximumMailSize'       => 10485760,
                   'Banner'                => '$myhostname ESMTP $mail_name',
                   'SendingMail'           => {
                           'Type'          => 'relayhost',
                           'TLS'           => 'MUST',
                           'RelayHost'     => {
                                   'Name'     => 'mail.domain.de',
                                   'Auth'     => 1,
                                   'Account'  => 'user',
                                   'Password' => 'password'
                                 }
                         }
             );

   if( ! WriteGlobalSettings(\%GlobalSettings,$AdminPassword) ) {
        print "ERROR in WriteGlobalSettings\n";
   }

=cut

BEGIN { $TYPEINFO{WriteGlobalSettings}  =["function", "boolean",  ["map", "string", "any" ], "string"]; }
sub WriteGlobalSettings {
    my $self               = shift;
    my $GlobalSettings     = shift;
    my $AdminPassword      = shift;

    if(! $GlobalSettings->{'Changed'})
    {
         return $self->SetError( summary =>"Nothing to do",
                                 code    => "PARAM_CHECK_FAILED" );
    }
    y2milestone("-- WriteGlobalSettings --");

    my $MaximumMailSize    = $GlobalSettings->{'MaximumMailSize'};
    my $Interfaces         = $GlobalSettings->{'Interfaces'}  || 'all';
    my $SendingMailType    = $GlobalSettings->{'SendingMail'}{'Type'};
    my $SendingMailTLS     = $GlobalSettings->{'SendingMail'}{'TLS'};
    my $RelayHostName      = $GlobalSettings->{'SendingMail'}{'RelayHost'}{'Name'};
    my $RelayHostAuth      = $GlobalSettings->{'SendingMail'}{'RelayHost'}{'Auth'};
    my $RelayHostAccount   = $GlobalSettings->{'SendingMail'}{'RelayHost'}{'Account'};
    my $RelayHostPassword  = $GlobalSettings->{'SendingMail'}{'RelayHost'}{'Password'};
    my $MainCf             = SCR->Read('.mail.postfix.main.table');
    my $SaslPasswd         = SCR->Read('.mail.postfix.saslpasswd.table');
    if( ! SCR->Read('.mail.postfix.mastercf') )
    {
         return $self->SetError( summary =>"Couln't open master.cf",
                                 code    => "PARAM_CHECK_FAILED" );
    }
    
    # Parsing attributes 
    if($MaximumMailSize =~ /[^\d+]/)
    {
         return $self->SetError( summary =>"Maximum Mail Size value may only contain decimal number in byte",
                                 code    => "PARAM_CHECK_FAILED" );
    }
    # If SendingMailType ne NONE we have to have a look 
    # at master.cf if smt is started
    if($SendingMailType ne 'NONE')
    {
       my $smtpsrv = SCR->Execute('.mail.postfix.mastercf.findService',
                   { 'service' => 'smtp',
                     'command' => 'smtp' });
       if(! defined $smtpsrv )
       {
           SCR->Execute('.mail.postfix.mastercf.addService', { 'service' => 'smtp',
                        'type'    => 'inet',
                        'private' => 'n',
                        'unpriv'  => '-',
                        'chroot'  => 'n',
                        'wakeup'  => '-',
                        'maxproc' => '-',
                        'command' => 'smtpd' });
       }
    }
    
    if($SendingMailType eq 'DNS')
    {
        #Make direkt mail sending
        #looking for relayhost setting from the past 
        my $tmp = read_attribute($MainCf,'relayhost');
        if( $tmp ne '' )
	{
            write_attribute($MainCf,'relayhost','');
            write_attribute($SaslPasswd,$tmp,'');
        }
    }
    elsif ($SendingMailType eq 'relayhost')
    {
        write_attribute($MainCf,'relayhost',$RelayHostName);
        if($RelayHostAuth)
	{
           write_attribute($SaslPasswd,$RelayHostName,"$RelayHostAccount:$RelayHostPassword");
           write_attribute($MainCf,'smtp_sasl_auth_enable','yes');
           write_attribute($MainCf,'smtp_sasl_password_maps','hash:/etc/postfix/sasl_passwd');
        }
    }
    elsif ($SendingMailType eq 'NONE')
    {
	SCR->Execute('.mail.postfix.mastercf.deleteService', { 'service' => 'smtp', 'command' => 'smtp' });
    }
    else
    {
      return $self->SetError( summary =>"Unknown mail sending type. Allowed values are:".
                                          " NONE | DNS | relayhost",
                              code    => "PARAM_CHECK_FAILED" );
    }
    #Now we write TLS settings if needed
    if($SendingMailTLS eq 'NONE')
    {
      write_attribute($MainCf,'smtp_use_tls','no');
      write_attribute($MainCf,'smtp_enforce_tls','no');
      write_attribute($MainCf,'smtp_tls_enforce_peername','no');
    }
    elsif($SendingMailTLS eq 'MAY')
    {
      write_attribute($MainCf,'smtp_use_tls','yes');
      write_attribute($MainCf,'smtp_enforce_tls','no');
      write_attribute($MainCf,'smtp_tls_enforce_peername','yes');
    }
    elsif($SendingMailTLS eq 'MUST')
    {
      write_attribute($MainCf,'smtp_use_tls','yes');
      write_attribute($MainCf,'smtp_enforce_tls','yes');
      write_attribute($MainCf,'smtp_tls_enforce_peername','yes');
    }
    elsif($SendingMailTLS eq 'MUST_NOPEERMATCH')
    {
      write_attribute($MainCf,'smtp_use_tls','yes');
      write_attribute($MainCf,'smtp_enforce_tls','yes');
      write_attribute($MainCf,'smtp_tls_enforce_peername','no');
    }
    else
    {
      return $self->SetError( summary =>"Unknown mail sending TLS type. Allowed values are:".
                                          " NONE | MAY | MUST | MUST_NOPEERMATCH",
                              code    => "PARAM_CHECK_FAILED" );
    }

    write_attribute($MainCf,'inet_interfaces',$Interfaces);
    write_attribute($MainCf,'message_size_limit',$MaximumMailSize);
    write_attribute($MainCf,'smtpd_banner',$GlobalSettings->{'Banner'});
    write_attribute($MainCf,'smtp_sasl_security_options','noanonymous');

    SCR->Write('.mail.postfix.main.table',$MainCf);
    SCR->Write('.mail.postfix.main',undef);
    SCR->Write('.mail.postfix.saslpasswd.table',$SaslPasswd);
    SCR->Write('.mail.postfix.saslpasswd',undef);
    SCR->Write('.mail.postfix.mastercf',undef);

    return 1;
}

=item *
C<$Canonical = ReadCanonical($AdminPassword)>

  Dump the mail-server Mail Transport to a single hash
  @return hash Dumped settings (later acceptable by WriteCanonical ())

=cut

BEGIN { $TYPEINFO{ReadCanonical}  =["function", ["map", "string", "any"]  , "string"]; }
sub ReadCanonical
{
    my $self            = shift;
    my $AdminPassword   = shift;


    my %Canonicals       = ( 
                           'Changed'          => YaST::YCP::Boolean(0),
                           'CanonicalTable'   => [], 
                           'CanonicalClasses' => [] 
                          );


    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }
    my $MainCf           = SCR->Read('.mail.postfix.main.table');
    my $CanonicalClasses = read_attribute($MainCf,'transport_maps');
    $CanonicalClasses    =~ s/ //g;
    push @{$Canonicals{CanonicalClasses}}, split /,/,$CanonicalClasses;

    my %SearchMap       = (
                               'base_dn'    => $ldapMap->{'mail_config_dn'},
                               'filter'     => "objectClass=suseCanonicalTable",
                               'scope'      => 2,
                               'map'        => 1,
                               'attributes' => ['tableKey',
			                        'tableValue',
						'valueType',
						'description' ]
                          );

                             
    # Searching all the transport lists
    my $ret = SCR->Read('.ldap.search',\%SearchMap);

    # filling up our array
    foreach my $dn (keys %{$ret})
    {
       my $Canonical       = {};
       $Canonical->{'key'}     = $ret->{$dn}->{'tableKey'}->[0];
       $Canonical->{'value'}   = $ret->{$dn}->{'tableValue'}->[0];
       $Canonical->{'type'}    = $ret->{$dn}->{'valueType'}->[0];
       if( defined $ret->{$dn}->{'description'}->[0] )
       {
         $Canonical->{'description'} = $ret->{$dn}->{'description'}->[0];
       }
       push @{$Canonicals{'CanonicalTable'}}, $Canonical;
    }
    #now we return the result
    return \%Canonicals;
}

=item *
C<$MailTransports = ReadMailTransports($AdminPassword)>

  Dump the mail-server Mail Transport to a single hash
  @return hash Dumped settings (later acceptable by WriteMailTransport ())

  $MailTransports is a pointer to a hash containing the mail transport
  definitions.

  %MailTransports  = (
       'Changed'      => 0,
             Shows if the hash was changed. Possible values are 0 (no) or 1 (yes).

       'Transports'  => [],
             Poiter to an array containing the mail transport table entries.
		       
       'TLSSites'  => {},
             Poiter to an hash containing the mail transport TLS per site table entries.
       'SASLAccounts'  => {},
             Poiter to an hash containing the client side authentication accounts.
		       
   );
   
   Each element of the arry 'Transports' has following syntax:

   %Transport       = (
       'Destination'  => '',
           This field contains a search pattern for the mail destination.
           Patterns are tried in the order as listed below:

           user+extension@domain
              Mail for user+extension@domain is delivered through
              transport to nexthop.

           user@domain
              Mail for user@domain is delivered through transport
              to nexthop.

           domain
              Mail  for  domain is delivered through transport to
              nexthop.

           .domain
              Mail for  any  subdomain  of  domain  is  delivered
              through  transport  to  nexthop.  This applies only
              when the string transport_maps is not listed in the
              parent_domain_matches_subdomains configuration set-
              ting.  Otherwise, a domain name matches itself  and
              its subdomains.

           Note 1: the special pattern * represents any address (i.e.
           it functions as the wild-card pattern).

           Note 2:  the  null  recipient  address  is  looked  up  as
           $empty_address_recipient@$myhostname (default: mailer-dae-
           mon@hostname).

       'Nexthop'      => '',
           This field has the format transport:nexthop and shows how
           the mails for the corresponding destination will be
	   delivered.

           The transport field specifies the name of a mail  delivery
           transport (the first name of a mail delivery service entry
           in the Postfix master.cf file).
           
           The interpretation  of  the  nexthop  field  is  transport
           dependent. In the case of SMTP, specify host:service for a
           non-default server port, and use [host] or [host]:port  in
           order  to  disable MX (mail exchanger) DNS lookups. The []
           form is required when you specify an IP address instead of
           a hostname.
           
           A  null  transport  and  null nexthop result means "do not
           change": use the delivery transport and  nexthop  informa-
           tion  that  would  be used when the entire transport table
           did not exist.
           
           A non-null transport  field  with  a  null  nexthop  field
           resets the nexthop information to the recipient domain.
           
           A  null  transport  field with non-null nexthop field does
           not modify the transport information.

	   For a detailed description have a look in man 5 trnsport.
			  
    );

    %TLSSites       = {
    
       'TLSSite'          => ''
                The name or IP of the mail server (nexthop).

       'TLSMode'          => '',
	     You can set how TLS will be used for security. Possible values are:
		NONE    : don't use TLS.
		MAY     : TLS will used when offered by the server.
		MUST    : Only connection with TLS will be accepted.
		MUST_NOPEERMATCH  : Only connection with TLS will be accepted, but
		          no strict peername checking accours.
    };

    %SASLAccounts = {
       'Server1' => ['Account1','Password1'],
       'Server2' => ['Account2','Password2']
    }


    


EXAMPLE:

use MailServer;

    my $AdminPassword   = "VerySecure";

    my $MailTransorts   = [];

    if (! $MailTransorts = ReadMailTransports($AdminPassword) ) {
       print "ERROR in ReadMailTransports\n";
    } else {
       foreach my $Transport (@{$MailTransports->{'Transports'}}){
            print "Destination=> $Transport->{'Destination'}\n";
	    print "    Nexthop=> $Transport->{'Nexthop'}\n";
       }
       foreach my $TLSSite (keys %{$MailTransports->{'TLSSites'}}){
            print "TLSSite: $TLSSite => ";
	    print "TLSMode: $MailTransports->{'TLSSites'}->{$TLSSite}\n";
       }
       foreach my $SASLAccount (keys %{$MailTransports->{'SASLAccounts'}}){
            print "Nexthop: $SASLAccount => ";
	    print "Account: $MailTransports->{'SASLAccounts'}->{$SASLAccount}->[0] ";
	    print "Passord: $MailTransports->{'SASLAccounts'}->{$SASLAccount}->[1]\n";
       }
    }

=cut


BEGIN { $TYPEINFO{ReadMailTransports}  =["function", ["map", "string", "any"]  , "string"]; }
sub ReadMailTransports {
    my $self            = shift;
    my $AdminPassword   = shift;


    my %MailTransports  = ( 
                           'Changed'      => YaST::YCP::Boolean(0),
                           'Use'          => YaST::YCP::Boolean(1), 
                           'Transports'   => [], 
                           'TLSSites'     => {},
                           'SASLAccounts' => {}, 
                          );

    my %NeededServers  = ();

    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }
    my $SaslPaswd       = SCR->Read('.mail.postfix.saslpasswd.table');
    my $MainCf          = SCR->Read('.mail.postfix.main.table');
    my $transport_maps  = read_attribute($MainCf,'transport_maps');
    if($transport_maps !~ /ldap:\/etc\/postfix\/ldaptransport_maps.cf/)
    {
    	$MailTransports{'Use'} = YaST::YCP::Boolean(0);
    }

    my %SearchMap       = (
                               'base_dn'    => $ldapMap->{'mail_config_dn'},
                               'filter'     => "objectClass=suseMailTransport",
                               'scope'      => 2,
                               'map'        => 1,
                               'attributes' => ['suseMailTransportDestination',
			                        'suseMailTransportNexthop']
                          );

                             
    # Searching all the transport lists
    my $ret = SCR->Read('.ldap.search',\%SearchMap);

    # filling up our array
    foreach my $dn (keys %{$ret})
    {
       my $Transport       = {};
       $Transport->{'Destination'}     = $ret->{$dn}->{'suseMailTransportDestination'}->[0];
       if( $ret->{$dn}->{'suseMailTransportNexthop'}->[0] =~ /:/)
       {
         ($Transport->{'Transport'},$Transport->{'Nexthop'}) = split /:/,$ret->{$dn}->{'suseMailTransportNexthop'}->[0];
       }
       else
       {
         $Transport->{'Nexthop'}         = $ret->{$dn}->{'suseMailTransportNexthop'}->[0];
       }
       push @{$MailTransports{'Transports'}}, $Transport;
       if( $Transport->{'Nexthop'} =~ /\[(.*)\]/ )
       {
            $NeededServers{$1} = 1;
       }
       else
       {
            $NeededServers{$Transport->{'Nexthop'}} = 1;
       }
    }
    # looking for SASL Accounts 
    foreach my $Server (keys %NeededServers)
    {
       my $SASLAccount    = '';
       my $SASLPasswd     = '';
       #Looking the type of TSL
       my $tmp = read_attribute($SaslPaswd,$Server);
       if($tmp)
       {
           my @SASLAccount = split /:/, $tmp;
           $MailTransports{'SASLAccounts'}->{$Server} = \@SASLAccount;
       }
    }

    #Looking for TLS per site Accounts
    %SearchMap       = (
                               'base_dn'    => $ldapMap->{'mail_config_dn'},
                               'filter'     => "ObjectClass=suseTLSPerSiteContainer",
                               'scope'      => 2,
                               'map'        => 1,
                               'attributes' => [ 'suseTLSPerSiteMode',
						 'suseTLSPerSitePeer']
                       );
    # Searching all the transport lists
    $ret = SCR->Read('.ldap.search',\%SearchMap);

    # filling up our array
    foreach my $dn (keys %{$ret})
    {
       my $TLSMode         = $ret->{$dn}->{'suseTLSPerSiteMode'}->[0] || "NONE";
       my $TLSSite         = $ret->{$dn}->{'suseTLSPerSitePeer'}->[0] ;
       $MailTransports{'TLSSites'}->{$TLSSite} = $TLSMode;
    }
    
    #print STDERR Dumper(%MailTransports);

    #now we return the result
    return \%MailTransports;
}

=item *
C<boolean = WriteMailTransports($adminpwd,$MailTransports)>

 Write the mail server Mail Transport from a single hash.

 WARNING!

 All transport defintions not contained in the hash will be removed
 from the tranport table.

EXAMPLE:

use MailServer;

    my $AdminPassword   = "VerySecure";

    my %MailTransports  = ( 
                           'Changed' => '1',
                           'Transports'  => [] 
                          );
    my %Transport       = (
                             'Destination'  => 'dom.ain',
                             'Transport'    => 'smtp',
                             'Nexthop'      => '[mail.dom.ain]',
                             'TLS'          => 'MUST',
                             'Auth'         => 1,
                             'Account'      => 'user',
                             'Password'     => 'passwd'
                          );
    push @($MailTransports{Transports}), %Transport; 
    
    %Transport       = (
                             'Destination'  => 'my-domain.de',
                             'Nexthop'      => 'uucp:[mail.my-domain.de]',
                             'TLS'          => 'NONE',
                             'Auth'         => '0'
			);
    push @($MailTransports{Transports}), %Transport; 

    %Transport       = (
                             'Destination'  => 'my-old-domain.de',
                             'Nexthop'      => "error:I've droped this domain"
			);
    push @($MailTransports{Transports}), %Transport; 

    if( ! WriteMailTransports(\%Transports,$AdminPassword) ) {
        print "ERROR in WriteMailTransport\n";
    }

=cut

BEGIN { $TYPEINFO{WriteMailTransports}  =["function", "boolean", ["map", "string", "any"], "string"]; }
sub WriteMailTransports {
    my $self            = shift;
    my $MailTransports  = shift;
    my $AdminPassword   = shift;
   
    # Map for the Transport Entries
    my %Entries        = (); 
    my $ldapMap       = {}; 
    my $NeededServers  = {};

    # If no changes we haven't to do anything
    if(! $MailTransports->{'Changed'})
    {
         return $self->SetError( summary =>"Nothing to do",
                                 code    => "PARAM_CHECK_FAILED" );
    }
    y2milestone("-- WriteMailTransports --");
#print STDERR Dumper($MailTransports);
    
    # Make LDAP Connection 
    $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }
    
    # Search hash to find all the Transport Objects
    my %SearchMap       = (
                               'base_dn' => $ldapMap->{'mail_config_dn'},
                               'filter'  => "objectClass=suseMailTransport",
                               'map'     => 1,
                               'scope'   => 2,
			       'attrs'   => ['suseMailTransportDestination' ]
                          );

    my $ret = SCR->Read('.ldap.search',\%SearchMap);

    # Now let's work
    foreach my $Transport (@{$MailTransports->{'Transports'}})
    {
       if( $Transport->{'Destination'} =~ /[^-\w\*\.\@\+]/ )
       {
	    return $self->SetError( summary     => 'Wrong Value for Mail Transport Destination. '.
	                                           'This field may contain only the charaters [-a-zA-Z.*@]',
				    code        => 'PARAM_CHECK_FAILED'
				  );
       }
       my $Destination =  $Transport->{'Destination'};
          $Destination =~ s#\+#\\+#;
       my $dn	= 'suseMailTransportDestination='.$Destination.','.$ldapMap->{'mail_config_dn'};
       $Entries{$dn}->{'suseMailTransportDestination'} = $Transport->{'Destination'};
       if(defined $Transport->{'Transport'} )
       {
          $Entries{$dn}->{'suseMailTransportNexthop'}  = $Transport->{'Transport'}.':'.$Transport->{'Nexthop'};
       }
       else
       {
          $Entries{$dn}->{'suseMailTransportNexthop'}  = $Transport->{'Nexthop'};
       }
       if( $Transport->{'Nexthop'} =~ /\[(.*)\]/ )
       {
            $NeededServers->{$1} = 1;
       }
       else
       {
            $NeededServers->{$Transport->{'Nexthop'}} = 1;
       }
    }


    #have a look if our table is OK. If not make it to work!
    my $MainCf             = SCR->Read('.mail.postfix.main.table');
    check_ldap_configuration('transport_maps',$ldapMap);
    check_ldap_configuration('smtp_tls_per_site',$ldapMap);
    if( $MailTransports->{Use} )
    {
	write_attribute($MainCf,'transport_maps','ldap:/etc/postfix/ldaptransport_maps.cf');
	write_attribute($MainCf,'smtp_tls_per_site','ldap:/etc/postfix/ldapsmtp_tls_per_site.cf');
    }
    else
    {
	write_attribute($MainCf,'transport_maps','');
	write_attribute($MainCf,'smtp_tls_per_site','');
    }

    # If there is no ERROR we do the changes
    # First we clean all the transport lists
    foreach my $key (keys %{$ret})
    {
       if(! SCR->Write('.ldap.delete',{'dn'=>$key}))
       {
          my $ldapERR = SCR->Read(".ldap.error");
          return $self->SetError(summary     => "LDAP delete failed",
                                 code        => "SCR_WRITE_FAILED",
                                 description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
       }
    }

    foreach my $dn (keys %Entries)
    {
       my $DN  = { 'dn' => $dn };
       my $tmp = { 'Objectclass'                  => [ 'suseMailTransport' ],
                   'suseMailTransportDestination' => $Entries{$dn}->{'suseMailTransportDestination'},
                   'suseMailTransportNexthop'     => $Entries{$dn}->{'suseMailTransportNexthop'}
                 };
       if(! SCR->Write('.ldap.add',$DN,$tmp))
       {
          my $ldapERR = SCR->Read(".ldap.error");
          return $self->SetError(summary     => "LDAP add failed",
                                 code        => "SCR_WRITE_FAILED",
                                 description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
       }
    }
    # Done Create new Transports

    #Creating the new TLS per Site entries
    %Entries = ();
    foreach my $TLSSite (keys %{$MailTransports->{'TLSSites'}})
    {
       if( ! defined $NeededServers->{$TLSSite} )
       {
             next;
       }
       my $dn	= 'suseTLSPerSitePeer='.$TLSSite.','.$ldapMap->{'mail_config_dn'};
       $Entries{$dn}->{'suseTLSPerSiteMode'}           = 'NONE';

       if($MailTransports->{'TLSSites'}->{$TLSSite} =~ /NONE|MAY|MUST|MUST_NOPEERMATCH/)
       {
            $Entries{$dn}->{'suseTLSPerSitePeer'}      = $TLSSite;
            $Entries{$dn}->{'suseTLSPerSiteMode'}      = $MailTransports->{'TLSSites'}->{$TLSSite};
       }
       else
       {
	    return $self->SetError( summary     => 'Wrong Value for suseTLSPerSiteMode',
				    code        => 'PARAM_CHECK_FAILED'
				  );
       }
    }
    # Search hash to find all the TLSSites Objects
    %SearchMap       = (
                               'base_dn' => $ldapMap->{'mail_config_dn'},
                               'filter'  => "objectClass=suseTLSPerSiteContainer",
                               'map'     => 1,
                               'scope'   => 2,
			       'attrs'   => []
                          );
    $ret = SCR->Read('.ldap.search',\%SearchMap);
    # First we clean all the TLSSites
    foreach my $key (keys %{$ret})
    {
       if(! SCR->Write('.ldap.delete',{'dn'=>$key}))
       {
          my $ldapERR = SCR->Read(".ldap.error");
          return $self->SetError(summary     => "LDAP delete failed",
                                 code        => "SCR_WRITE_FAILED",
                                 description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
       }
    }
    #And now we add the new TLSSites
    foreach my $dn (keys %Entries)
    {
       my $DN  = { 'dn' => $dn };
       my $tmp = { 'Objectclass'                  => [ 'suseTLSPerSiteContainer' ],
                   'suseTLSPerSiteMode'           => $Entries{$dn}->{'suseTLSPerSiteMode'},
                   'suseTLSPerSitePeer'           => $Entries{$dn}->{'suseTLSPerSitePeer'}
                 };
       if(! SCR->Write('.ldap.add',$DN,$tmp))
       {
          my $ldapERR = SCR->Read(".ldap.error");
          return $self->SetError(summary     => "LDAP add failed",
                                 code        => "SCR_WRITE_FAILED",
                                 description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
       }
    }

    # Now we create the new SaslPasswd entries
    # We have to save the entry for the relay host
    # We'll need the sasl passwords entries
    my $OldSaslPasswd = SCR->Read('.mail.postfix.saslpasswd.table');
    my $SaslPasswd    = SCR->Read('.mail.postfix.saslpasswd.table');

    my $RelayHost = read_attribute($MainCf,'relayhost');
    foreach(@{$OldSaslPasswd})
    {
      if($_->{"key"} eq $RelayHost)
      {
         next;
      }
      elsif( ! defined $MailTransports->{'SASLAccounts'}->{$_->{"key"}})
      {
         write_attribute($SaslPasswd,$_->{"key"},"");
      }
    }
    foreach(keys %{$MailTransports->{'SASLAccounts'}})
    {
         my $Account  = $MailTransports->{'SASLAccounts'}->{$_}->[0];
         my $Password = $MailTransports->{'SASLAccounts'}->{$_}->[1];
         write_attribute($SaslPasswd,$_,"$Account:$Password");
    }
    if( scalar(keys(%{$MailTransports->{'SASLAccounts'}})) > 0 )
    {
         write_attribute($MainCf,'smtp_sasl_auth_enable','yes');
         write_attribute($MainCf,'smtp_sasl_password_maps','hash:/etc/postfix/sasl_passwd');
    }
    write_attribute($MainCf,'smtp_sasl_security_options','noanonymous');

    SCR->Write('.mail.postfix.saslpasswd.table',$SaslPasswd);
    SCR->Write('.mail.postfix.saslpasswd',undef);
    SCR->Write('.mail.postfix.main.table',$MainCf);
    SCR->Write('.mail.postfix.main',undef);

    return 1;
}

=item *
C<$MailPrevention = ReadMailPrevention($adminpwd)>

 Dump the mail-server prevention to a single hash
 @return hash Dumped settings (later acceptable by WriteMailPrevention())

 Postfix offers a variety of parameters that limit the delivery of 
 unsolicited commercial email (UCE). 

 By default, the Postfix SMTP server will accept mail only from or to the
 local network or domain, or to domains that are hosted by Postfix, so that
 your system can't be used as a mail relay to forward bulk mail from random strangers.

 There is a lot of combination of the postfix configuration parameter 
 you can set. To make the setup easier we have defined three kind of predefined
 settings: 
   off:
        1. Accept connections from all clients even if the client IP address has no 
           PTR (address to name) record in the DNS. 
        2. Accept all eMails has RCPT a local destination or the client is in the
           local network.
        3. Mail adresses via access table can be rejected.
   medium:
        1. Accept connections from all clients even if the client IP address has no 
           PTR (address to name) record in the DNS. 
        2. Accept all eMails has RCPT a local destination and the sender domain is
           a valid domain. Furthermore mails from clients from local network will
           be accepted.
        3. 
   hard:

 $MailPrevention is a pointer to a hash containing the mail server
 basic prevention settings. This hash has following structure:


 my %MailPrevention      = (
           'Changed'               => 0,
             Shows if the hash was changed. Possible values are 0 (no) or 1 (yes).

           'BasicProtection'       => 'hard',
           'RBLList'               => [],
           'AccessList'            => [],
           'VirusScanning'         => 1,
           'VSCount'               => 10
           'SpamLearning'          => 1
                          );

   AccessList is a pointer to an array of %AccessEntry hashes.

 my %AccessEntry         = (  'ClientAddress' => '',
                              'ClientAccess'  => ''
			   );

EXAMPLE:

use MailServer;

    my $AdminPassword   = "VerySecure";
    my $MailPrevention  = [];

    if( $MailPrevention = ReadMailPrevention($AdminPassword) ) {
        print "Basic BasicProtection : $MailPrevention->{BasicProtection}\n";
        foreach(@{$MailPrevention->{RBLList}}) {
          print "Used RBL Server: $_\n";
        }
        foreach(@{$MailPrevention->{AccessList}}) {
          print "Access for  $_{MailClient} is $_{MailAction}\n";
        }
        if($MailPrevention->{VirusScanning}){
          print "Virus scanning is activated\n";
        } else {
          print "Virus scanning isn't activated\n";
        }
    } else {
        print "ERROR in ReadMailPrevention\n";
    }

=cut

BEGIN { $TYPEINFO{ReadMailPrevention}  =["function", "any", "string" ]; }
sub ReadMailPrevention {
    my $self            = shift;
    my $AdminPassword   = shift;

    my %MailPrevention  = (
                               'Changed'                    => YaST::YCP::Boolean(0),
			       'BasicProtection'            => 'hard',
			       'RBLList'                    => [],
			       'AccessList'                 => [],
			       'VirusScanning'              => YaST::YCP::Boolean(0),
			       'VSCount'                    => YaST::YCP::Integer(5),
			       'SpamLearning'               => YaST::YCP::Boolean(0)
                          );

    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }

    # First we read the main.cf and master.cf 
    my $MainCf             = SCR->Read('.mail.postfix.main.table');

    if( ! SCR->Read('.mail.postfix.mastercf') )
    {
         return $self->SetError( summary =>"Couln't open master.cf",
                                 code    => "PARAM_CHECK_FAILED" );
    }

    # We ar looking for the BasicProtection Basic Prevention
    my $smtpd_helo_restrictions = read_attribute($MainCf,'smtpd_helo_restrictions');
    if( $smtpd_helo_restrictions !~ /reject_invalid_hostname/ )
    {
       my $smtpd_helo_required  = read_attribute($MainCf,'smtpd_helo_required');
       if( $smtpd_helo_required =~ /no/ )
       {
         $MailPrevention{'BasicProtection'} =  'off';    
       }
       else
       {
         $MailPrevention{'BasicProtection'} =  'medium';
       }
    }

    # If the BasicProtection Basic Prevention is not off we collect the list of the RBL hosts
    if($MailPrevention{'BasicProtection'} ne 'off')
    {
       my $smtpd_client_restrictions = read_attribute($MainCf,'smtpd_client_restrictions');
       foreach(split /, |,/, $smtpd_client_restrictions)
       {
          if(/reject_rbl_client (.*)/)
	  {
	    push @{$MailPrevention{'RBLList'}}, $1;
	  }
       }
    }

    #Now we read the access table
    my %SearchMap = (
                   'base_dn' => $ldapMap->{'mail_config_dn'},
                   'filter'  => "ObjectClass=suseMailAccess",
                   'scope'   => 2,
                   'attrs'   => ['suseMailClient','suseMailAction']
                 );
    my $ret = SCR->Read('.ldap.search',\%SearchMap);
    foreach my $entry (@{$ret})
    {  
       my $AccessEntry = {};
       $AccessEntry->{'MailClient'} = $entry->{'suseMailClient'}->[0];
       $AccessEntry->{'MailAction'} = $entry->{'suseMailAction'}->[0];
       push @{$MailPrevention{'AccessList'}}, $AccessEntry;
    }

    # Now we looking for if vscan (virusscanning) is started.
    my $vscanin = SCR->Execute('.mail.postfix.mastercf.findService',
		{ 'service' => 'localhost:10025',
		  'command' => 'smtpd'} );
    my $vscanout = SCR->Execute('.mail.postfix.mastercf.findService',
		{ 'service' => 'amavis',
		  'command' => 'lmtp'} );
    my $content_filter = read_attribute($MainCf,'content_filter');

    if( $content_filter eq 'amavis:[127.0.0.1]:10024' && $vscanin && $vscanout)
    {
        $MailPrevention{'VirusScanning'} = YaST::YCP::Boolean(1);
        if( ! open(IN,$aconf) )
        {
           return "Error: $!";
        }
        my @ACONF = <IN>;
        close(IN);
        my $ismax = 0;
        foreach ( @ACONF )
        {
        	s/\s+//g;
		if ( /^\$max_servers=(\d+)/ )
		{
		    $MailPrevention{'VSCount'} = YaST::YCP::Integer($1);
		}
		$ismax = 1;
        }
        if( !$ismax )
        {
            $MailPrevention{'VSCount'} = YaST::YCP::Integer(2);
        }
    }
    # make IMAP connection
    my $imap = new Net::IMAP($imaphost, Debug => 0);
    if( $imap )
    {
        $ret = $imap->login($imapadm, $AdminPassword);
	if($$ret{Status} eq "ok") {
	    $ret = $imap->select('NewSpam'); 
	    if( $ret->{Status} eq 'ok' )
	    {
	        $MailPrevention{'SpamLearning'} = YaST::YCP::Boolean(1);
	    }
	}
	$imap->logout();
    }
    
    return \%MailPrevention;
}

##
 # Write the mail-server Mail Prevention from a single hash
 #
BEGIN { $TYPEINFO{WriteMailPrevention}  =["function", "boolean", ["map", "string", "any"], "string"]; }
sub WriteMailPrevention {
    my $self            = shift;
    my $MailPrevention  = shift;
    my $AdminPassword   = shift;

    if(! $MailPrevention->{'Changed'})
    {
         return $self->SetError( summary =>"Nothing to do",
                                 code    => "PARAM_CHECK_FAILED" );
    }
   
    y2milestone("-- WriteMailPrevention --");
    #print STDERR Dumper( $MailPrevention );
    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }

    # First we read the main.cf
    my $MainCf             = SCR->Read('.mail.postfix.main.table');

    if( ! SCR->Read('.mail.postfix.mastercf') )
    {
         return $self->SetError( summary =>"Couln't open master.cf",
                                 code    => "PARAM_CHECK_FAILED" );
    }

    #Collect the RBL host list
    my $clnt_restrictions = '';
    foreach(@{$MailPrevention->{'RBLList'}})
    {
      if($clnt_restrictions eq '')
      {
          $clnt_restrictions="reject_rbl_client $_";
      }
      else
      {
          $clnt_restrictions="$clnt_restrictions, reject_rbl_client $_";
      }
    }

    my $smtpd_recipient_restrictions = read_attribute($MainCf,'smtpd_recipient_restrictions');
    if( $smtpd_recipient_restrictions =~ /permit_sasl_authenticated/)
    {
        $smtpd_recipient_restrictions = "permit_sasl_authenticated, ";
    }
    else
    {
        $smtpd_recipient_restrictions = "";
    }
    write_attribute($MainCf,'smtpd_recipient_restrictions',$smtpd_recipient_restrictions.'permit_auth_destination, permit_mynetworks, reject_unauth_destination, reject');
    if($MailPrevention->{'BasicProtection'} eq 'hard')
    {
      #Write hard settings 
       write_attribute($MainCf,'smtpd_helo_required','yes');   
       write_attribute($MainCf,'smtpd_helo_restrictions','permit_mynetworks, reject_invalid_hostname');   
       write_attribute($MainCf,'strict_rfc821_envelopes','yes');   
       if( $clnt_restrictions ne '')
       {
          write_attribute($MainCf,'smtpd_client_restrictions',"permit_mynetworks, $clnt_restrictions, ldap:/etc/postfix/ldapaccess.cf, reject_unknown_client");
       }
       else
       {
          write_attribute($MainCf,'smtpd_client_restrictions','permit_mynetworks, ldap:/etc/postfix/ldapaccess.cf, reject_unknown_client');
       }
    }
    elsif($MailPrevention->{'BasicProtection'} eq 'medium')
    {
      #Write medium settings  
       write_attribute($MainCf,'smtpd_helo_required','yes');   
       write_attribute($MainCf,'smtpd_helo_restrictions','');   
       write_attribute($MainCf,'strict_rfc821_envelopes','no');   
       if( $clnt_restrictions ne '')
       {
          write_attribute($MainCf,'smtpd_client_restrictions',"$clnt_restrictions, ldap:/etc/postfix/ldapaccess.cf");
       }
       else
       {
          write_attribute($MainCf,'smtpd_client_restrictions','ldap:/etc/postfix/ldapaccess.cf');
       }
    }
    elsif($MailPrevention->{'BasicProtection'} eq 'off')
    {
      # Write off settings  
       write_attribute($MainCf,'smtpd_helo_required','no');   
       write_attribute($MainCf,'smtpd_helo_restrictions','');   
       write_attribute($MainCf,'strict_rfc821_envelopes','no');   
       write_attribute($MainCf,'smtpd_client_restrictions','ldap:/etc/postfix/ldapaccess.cf');
    }
    else
    {
      # Error no such value
         return $self->SetError( summary =>"Unknown BasicProtection mode. Allowed values are: hard, medium, off",
                                 code    => "PARAM_CHECK_FAILED" );
    }
    #Now we have a look on the access table
    my %SearchMap = (
                   'base_dn' => $ldapMap->{'mail_config_dn'},
                   'filter'  => "objectClass=suseMailAccess",
                   'scope'   => 2,
                   'map'     => 1
                 );
    my $ret = SCR->Read('.ldap.search',\%SearchMap);
    #First we clean the access table
    foreach my $key (keys %{$ret})
    {
       if(! SCR->Write('.ldap.delete',{'dn'=>$key}))
       {
          my $ldapERR = SCR->Read(".ldap.error");
          return $self->SetError(summary     => "LDAP delete failed",
                                 code        => "SCR_WRITE_FAILED",
                                 description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
       }
    }

    #Now we write the new table
#print STDERR Dumper([$MailPrevention->{'AccessList'}]);
    foreach my $entry (@{$MailPrevention->{'AccessList'}})
    {
       my $dn  = { 'dn' => "suseMailClient=".$entry->{'MailClient'}.','. $ldapMap->{'mail_config_dn'}};
       my $tmp = { 'suseMailClient'   => $entry->{'MailClient'},
                   'suseMailAction'   => $entry->{'MailAction'},
                   'ObjectClass'      => ['suseMailAccess']
                 };
       if(! SCR->Write('.ldap.add',$dn,$tmp))
       {
          my $ldapERR = SCR->Read(".ldap.error");
          return $self->SetError(summary => "LDAP add failed",
                               code => "SCR_INIT_FAILED",
                               description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
       }
    }

    SCR->Read('.mail.postfix.mastercf');
    if( $MailPrevention->{'VirusScanning'} )
    {
	$MailPrevention->{'VSCount'} = 5 if( ! defined $MailPrevention->{'VSCount'});
	my $err = activate_virus_scanner($MailPrevention->{'VSCount'});
	if( $err ne "" )
	{
	    return $self->SetError(summary => "activating virus scanner failed",
				   code => "VIRUS_SCANNER_FAILED",
				   description => "activating the virus scanner failed: $err");
	}
	# This is only for systems updated from SLES10
		my $smtps = SCR->Execute('.mail.postfix.mastercf.findService',
					 { 'service' => 'smtps', 'command' => 'smtpd' });
		if( ref($smtps) eq 'ARRAY' && defined $smtps->[0]->{options} )
		{
		    my $opts = $smtps->[0]->{options};
		    if ( defined $opts->{'content_filter'} )
		    {
			    delete $opts->{'content_filter'};
			    SCR->Execute('.mail.postfix.mastercf.modifyService',
					 { 'service' => 'smtps',
					   'command' => 'smtpd',
					   'maxproc' => '-',
					   'options' => $opts } );
		    }
		}
		my $smtp = SCR->Execute('.mail.postfix.mastercf.findService',
					 { 'service' => 'smtp', 'command' => 'smtpd' });
		if( ref($smtp) eq 'ARRAY' && defined $smtp->[0]->{options} )
		{
		    my $opts = $smtp->[0]->{options};
		    if ( defined $opts->{'content_filter'} )
		    {
			    delete $opts->{'content_filter'};
			    SCR->Execute('.mail.postfix.mastercf.modifyService',
					 { 'service' => 'smtp',
					   'command' => 'smtpd',
					   'maxproc' => '-',
					   'options' => $opts } );
		    }
		}
	# End This is only for systems updated from SLES10
	if( SCR->Execute('.mail.postfix.mastercf.findService',
	    { 'service' => 'localhost:10025', 'command' => 'smtpd' }))
	{
	    SCR->Execute('.mail.postfix.mastercf.deleteService',
	        { 'service' => 'localhost:10025', 'command' => 'smtpd' });
	}
	if( SCR->Execute('.mail.postfix.mastercf.findService',
	    { 'service' => 'amavis', 'command' => 'lmtp' }))
	{
	    SCR->Execute('.mail.postfix.mastercf.deleteService',
	        { 'service' => 'amavis', 'command' => 'lmtp' });
	}
	# create smtpd pocess for getting back the emails
        SCR->Execute('.mail.postfix.mastercf.addService',
		{ 'service' => 'amavis',
		  'command' => 'lmtp',
		  'type'    => 'unix',
		  'private' => '-',
		  'unpriv'  => '-',
		  'chroot'  => '-',
		  'wakeup'  => '-',
		  'maxproc' => $MailPrevention->{'VSCount'},
		  'options' => { lmtp_data_done_timeout     => 1200,
				 lmtp_send_xforward_command => 'yes',
				 disable_dns_lookups        => 'yes',
				 max_use                    => 20 } } );
        SCR->Execute('.mail.postfix.mastercf.addService',
		{ 'service' => 'localhost:10025',
		  'command' => 'smtpd',
		  'type'    => 'inet',
		  'private' => 'n',
		  'unpriv'  => '-',
		  'chroot'  => 'n',
		  'wakeup'  => '-',
		  'maxproc' => '-',
		  'options' => {  content_filter => '',
				  relay_recipient_maps => '',
				  smtpd_delay_reject => 'no',
				  smtpd_restriction_classes => '',
				  smtpd_client_restrictions => '',
				  smtpd_helo_restrictions => '',
				  smtpd_sender_restrictions => '',
				  smtpd_recipient_restrictions => 'permit_mynetworks,reject',
				  smtpd_data_restrictions => 'reject_unauth_pipelining',
				  smtpd_end_of_data_restrictions => '',
				  mynetworks => '127.0.0.0/8',
				  smtpd_error_sleep_time => '0',
				  smtpd_soft_error_limit => '1001',
				  smtpd_hard_error_limit => '1000',
				  smtpd_client_connection_count_limit => '0',
				  smtpd_client_connection_rate_limit => '0',
				  receive_override_options => 'no_header_body_checks,no_unknown_recipient_checks'
		  		} 
		} );
       write_attribute($MainCf,'content_filter','amavis:[127.0.0.1]:10024');   
    }
    else
    {
	SCR->Execute('.mail.postfix.mastercf.deleteService',
	    { 'service' => 'localhost:10025', 'command' => 'smtpd' });
	SCR->Execute('.mail.postfix.mastercf.deleteService',
	    { 'service' => 'amavis', 'command' => 'lmtp' });
	write_attribute($MainCf,'content_filter','');   
	
	Service->Stop('amavis');
	Service->Stop('clamd');
	Service->Disable('amavis');
	Service->Disable('clamd');
    }

    # now we looks if the ldap entries in the main.cf for the access table are OK.
    check_ldap_configuration('access',$ldapMap);
    SCR->Write('.mail.postfix.main.table',$MainCf);
    SCR->Write('.mail.postfix.main',undef);
    SCR->Write('.mail.postfix.mastercf',undef);

    # make IMAP connection
    my $imap = new Net::IMAP($imaphost, Debug => 0);
    if( $imap )
    {
        my $ret = $imap->login($imapadm, $AdminPassword);
	if($$ret{Status} eq "ok")
	{
    	    if( $MailPrevention->{'SpamLearning'} )
	    {
	        $ret = $imap->create('NewSpam'); 
	        $ret = $imap->create('NoSpam'); 
		$ret = $imap->setacl('NewSpam', $imapadm, "lrswipkxtea");
		$ret = $imap->setacl('NoSpam',  $imapadm, "lrswipkxtea");
		$ret = $imap->setacl('NewSpam', 'anyone', "lrswi");
		$ret = $imap->setacl('NoSpam',  'anyone', "lsi");
		my $lernspam = '#!/bin/bash
LOG=/var/log/lern-spam
date +%Y-%m-%d-%H-%M >> $LOG
if [ ! -d /var/spool/imap/NewSpam ]
then
  exit
fi

setfacl -m u:vscan:rx /var/spool/imap /var/spool/imap/{NoSpam,NewSpam}
setfacl -m m::rx /var/spool/imap /var/spool/imap/{NoSpam,NewSpam}

/usr/bin/sa-learn --sync --dbpath /var/spool/amavis/.spamassassin/
(
for i in `ls /var/spool/imap/NewSpam/[0-9]* 2> /dev/null`
do
   setfacl -m user:vscan:r-x $i
   echo $i 
   /usr/bin/sa-learn --spam --dbpath /var/spool/amavis/.spamassassin/ $i
   rm $i
done
) >> $LOG  2>&1
su - cyrus -c "reconstruct NewSpam" &>/dev/null

(
for i in `ls /var/spool/imap/NoSpam/[0-9]* 2> /dev/null`
do
   setfacl -m user:vscan:r-x $i
   echo $i 
   /usr/bin/sa-learn --ham --dbpath /var/spool/amavis/.spamassassin/ $i
   rm $i
done
) >> $LOG  2>&1
su - cyrus -c "reconstruct NoSpam" &>/dev/null
chown -R vscan /var/spool/amavis/.spamassassin/

setfacl -b /var/spool/imap /var/spool/imap/{NoSpam,NewSpam}
';
		SCR->Write(".target.string","/etc/cron.hourly/lern-spam",$lernspam);
		SCR->Execute(".target.bash","chmod 755 /etc/cron.hourly/lern-spam");
	    }
	    $imap->logout();
	}
	else
	{
	    SCR->Execute(".target.bash","test -e /etc/cron.hourly/lern-spam && rm /etc/cron.hourly/lern-spam");
	    $ret = $imap->delete('NewSpam'); 
	    $ret = $imap->delete('NoSpam'); 
	    $imap->logout();
	}
    }
    return  1;
}

=item *
C<$MailRelaying = ReadMailRelaying($adminpwd)>

 Dump the mail-server server side relay settings to a single hash
 @return hash Dumped settings (later acceptable by WriteMailRelaying ())

 $MailRelaying is a pointer to a hash containing the mail server
 relay settings. This hash has following structure:

 %MailRelaying    = (
           'Changed'               => 0,
             Shows if the hash was changed. Possible values are 0 (no) or 1 (yes).

           'TrustedNetworks' => [],
             An array of trusted networks/hosts addresses

           'RequireSASL'     => 1,
             Show if SASL authentication is required for sending external eMails.
 
           'SMTPDTLSMode'    => 'use',
             Shows how TLS will be used for smtpd connection.
             Avaiable values are:
             'none'      : no TLS will be used.
             'use'       : TLS will be used if the client wants.
             'enfoce'    : TLS must be used.
             'auth_only' : TLS will be used only for SASL authentication.

           'UserRestriction' => 0
             If UserRestriction is set, there is possible to make user/group based 
             restrictions for sending and getting eMails. Strickt authotentication
             is requiered. To do so an 2nd interface for sending eMails for internal
             clients will be set up. The system administrator have to care that the
             other interface (external interface) can not be accessed from the internal
             clients
                          );

  

=cut

BEGIN { $TYPEINFO{ReadMailRelaying}  =["function", "any", "string" ]; }
sub ReadMailRelaying {
    my $self            = shift;
    my $AdminPassword   = shift;
    my %MailRelaying    = (
                                'Changed'         => YaST::YCP::Boolean(0),
                                'TrustedNetworks' => [],
                                'RequireSASL'     => 0,
                                'SMTPDTLSMode'    => 'use',
                                'UserRestriction' => 0
                          );

    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }

    # First we read the main.cf
    my $MainCf             = SCR->Read('.mail.postfix.main.table');

    # Now we look if there are manual inclued mynetworks entries
    # my $TrustedNetworks    = read_attribute($MainCf,'mynetworks');
    my $TrustedNetworks = `postconf -h mynetworks`;
    chomp $TrustedNetworks;
    foreach(split /, |,| /, $TrustedNetworks)
    { 
       if(! /ldapmynetworks/ && /\w+/)
       {
          push @{$MailRelaying{'TrustedNetworks'}}, $_;
       }
    }

    #Now we have a look on the mynetworks ldaptable
#    my %SearchMap = (
##                   'base_dn' => $ldapMap->{'mail_config_dn'},
#                   'filter'  => "ObjectClass=suseMailMyNetorks",
#                   'attrs'   => ['suseMailClient']
#                 );
#    my $ret = SCR->Read('.ldap.search',\%SearchMap);
#
#    foreach my $entry (@{$ret}){
#        foreach(@{$entry->{'suseMailClient'}}) {
#          push @{$MailRelaying{'TrustedNetworks'}}, $_;
#        }
#    }

    my $smtpd_recipient_restrictions = read_attribute($MainCf,'smtpd_recipient_restrictions');
    my $smtpd_sasl_auth_enable       = read_attribute($MainCf,'smtpd_sasl_auth_enable');
    my $smtpd_use_tls                = read_attribute($MainCf,'smtpd_use_tls');
    my $smtpd_enforce_tls            = read_attribute($MainCf,'smtpd_enforce_tls')   || 'no';
    my $smtpd_tls_auth_only          = read_attribute($MainCf,'smtpd_tls_auth_only');
    if($smtpd_use_tls eq 'no')
    {
       $MailRelaying{'SMTPDTLSMode'} = 'none';
    }
    if($smtpd_enforce_tls eq 'yes')
    {
       $MailRelaying{'SMTPDTLSMode'} = 'enforce';
    }
    if($smtpd_tls_auth_only eq 'yes')
    {
       $MailRelaying{'SMTPDTLSMode'} = 'auth_only';
    } 
    if($smtpd_sasl_auth_enable eq 'yes')
    {
       $MailRelaying{'RequireSASL'}  = 1;
       if( $smtpd_recipient_restrictions !~ /permit_sasl_authenticated/)
       {
         $self->SetError( summary => 'Postfix configuration mistake: smtpd_sasl_auth_enable is yes, but '.
                                     'smtpd_recipient_restrictions doesn\'t contain permit_sasl_authenticated.',
                                 code    => "PARAM_CHECK_FAILED" );
       }                          
    }

#print STDERR Dumper(%MailRelaying);
    return \%MailRelaying;
}

##
 # Write the mail-server server side relay settings  from a single hash
 #
BEGIN { $TYPEINFO{WriteMailRelaying}  =["function", "boolean",["map", "string", "any"], "string"]; }
sub WriteMailRelaying {
    my $self            = shift;
    my $MailRelaying    = shift;
    my $AdminPassword   = shift;
   
    #If nothing to do we don't do antithing
    if(! $MailRelaying->{'Changed'})
    {
         return $self->SetError( summary =>"Nothing to do",
                                 code    => "PARAM_CHECK_FAILED" );
    }
    
    y2milestone("-- WriteMailRelaying --");
    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }

   # First we read the main.cf
    my $MainCf             = SCR->Read('.mail.postfix.main.table');

    # now we collent the trusted networks;
    my $TrustedNetworks    = '';
    foreach(@{$MailRelaying->{'TrustedNetworks'}})
    {
      if( $TrustedNetworks ne '' )
      {
        $TrustedNetworks = $TrustedNetworks.', '.$_
      }
      else
      {
        $TrustedNetworks = $_;
      }
    }
    write_attribute($MainCf,'mynetworks',$TrustedNetworks);

    my $smtpd_recipient_restrictions = read_attribute($MainCf,'smtpd_recipient_restrictions');      
    if($MailRelaying->{'RequireSASL'})
    {
       write_attribute($MainCf,'smtpd_sasl_auth_enable','yes');
      if( $smtpd_recipient_restrictions !~ /permit_sasl_authenticated/)
      {
          $smtpd_recipient_restrictions = 'permit_sasl_authenticated, '.$smtpd_recipient_restrictions;
          write_attribute($MainCf,'smtpd_recipient_restrictions',$smtpd_recipient_restrictions);
      }
    }
    else
    {
      if( $smtpd_recipient_restrictions =~ s/permit_sasl_authenticated//)
      {
        $smtpd_recipient_restrictions =~ s/,\s*,/,/;
	$smtpd_recipient_restrictions =~ s/^\s*,\s*//;
        write_attribute($MainCf,'smtpd_recipient_restrictions',$smtpd_recipient_restrictions);
      }
      write_attribute($MainCf,'smtpd_sasl_auth_enable','no');
    }

    #now we write TLS settings for the smtpd daemon
    if($MailRelaying->{'SMTPDTLSMode'} eq 'none')
    {
        write_attribute($MainCf,'smtpd_use_tls','no');
        write_attribute($MainCf,'smtp_enforce_tls','no');
        write_attribute($MainCf,'smtpd_tls_auth_only','no');
    }
    elsif($MailRelaying->{'SMTPDTLSMode'} eq 'use')
    {
        write_attribute($MainCf,'smtpd_use_tls','yes');
        write_attribute($MainCf,'smtp_enforce_tls','no');
        write_attribute($MainCf,'smtpd_tls_auth_only','no');
    }
    elsif($MailRelaying->{'SMTPDTLSMode'} eq 'enforce')
    {
        write_attribute($MainCf,'smtpd_use_tls','yes');
        write_attribute($MainCf,'smtp_enforce_tls','yes');
        write_attribute($MainCf,'smtpd_tls_auth_only','no');
    }
    elsif($MailRelaying->{'SMTPDTLSMode'} eq 'auth_only')
    {
        write_attribute($MainCf,'smtpd_use_tls','yes');
        write_attribute($MainCf,'smtp_enforce_tls','no');
        write_attribute($MainCf,'smtpd_tls_auth_only','yes');
    }
    else
    {
         return $self->SetError( summary => 'Bad value for SMTPDTLSMode. Avaiable values are:'.
                                            "\nnone use enforce auth_only",
                                 code    => "PARAM_CHECK_FAILED" );
    }
    # Searching for the tlsmanager service
    if( ! SCR->Read('.mail.postfix.mastercf') )
    {
       return $self->SetError( summary =>"Couln't open master.cf",
                               code    => "PARAM_CHECK_FAILED" );
    }
    my $tlsmgr = SCR->Execute('.mail.postfix.mastercf.findService',
                   { 'service' => 'tlsmgr',
                     'command' => 'tlsmgr' });
    if($MailRelaying->{'SMTPDTLSMode'} ne 'none')
    {
      my $size = SCR->Read(".target.size", '/etc/ssl/servercerts/servercert.pem');
      if ($size <= 0)
      {
          return $self->SetError(summary => "Common server certificate not found.",
                                 code => "PARAM_CHECK_FAILED");
      }
      $size = SCR->Read(".target.size", '/etc/ssl/servercerts/serverkey.pem');
      if ($size <= 0)
      {
          return $self->SetError(summary => "Common private key not found.",
                                 code => "PARAM_CHECK_FAILED");
      }
      write_attribute($MainCf,'smtpd_tls_cert_file','/etc/ssl/servercerts/servercert.pem');
      write_attribute($MainCf,'smtpd_tls_key_file','/etc/ssl/servercerts/serverkey.pem');
      if(SCR->Read(".target.size", '/etc/ssl/certs/YaST-CA.pem') > 0)
      {
          #write_attribute($MainCf,'smtpd_tls_CAfile','/etc/ssl/certs/YaST-CA.pem');
          write_attribute($MainCf,'smtpd_tls_CApath','/etc/ssl/certs');
      }
      if(! defined $tlsmgr )
      {
           SCR->Execute('.mail.postfix.mastercf.addService',
	   { 'service' => 'tlsmgr',
	     'type'    => 'unix',
	     'private' => '-',
	     'unpriv'  => '-',
	     'chroot'  => 'n',
	     'wakeup'  => '1000?',
	     'maxproc' => '1',
	     'command' => 'tlsmgr' });
      }
    }
    else
    {
      if( defined $tlsmgr )
      {
         SCR->Execute('.mail.postfix.mastercf.deleteService', {'service' => 'tlsmgr','command' => 'tlsmgr'});
      }
    }
    SCR->Write('.mail.postfix.mastercf',undef);
    SCR->Write('.mail.postfix.main.table',$MainCf);
    SCR->Write('.mail.postfix.main',undef);

    return 1;

}

##
BEGIN { $TYPEINFO{ReadMailLocalDelivery}  =["function", "any", "string"]; }
sub ReadMailLocalDelivery {
    my $self            = shift;
    my $AdminPassword   = shift;
    my %MailLocalDelivery = (
                                'Changed'         => YaST::YCP::Boolean(0),
                                'Type'            => '',
                                'MailboxSizeLimit'=> 0,
                                'FallBackMailbox' => '',
                                'SpoolDirectory'  => '',
                                'QuotaLimit'      => 90,
                                'HardQuotaLimit'  => 0,
                                'ImapIdleTime'    => 30,
                                'PopIdleTime'     => 10,
			        'Security'        => 0,
                                'AlternateNameSpace'  => ''
                            );

    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }

   # First we read the main.cf
    my $MainCf             = SCR->Read('.mail.postfix.main.table');

    my $MailboxCommand     = read_attribute($MainCf,'mailbox_command');
    my $MailboxTransport   = read_attribute($MainCf,'mailbox_transport');
    my $MailboxSizeLimit   = read_attribute($MainCf,'mailbox_size_limit');
    my $HomeMailbox        = read_attribute($MainCf,'home_mailbox');
    my $MailSpoolDirectory = read_attribute($MainCf,'mail_spool_directory');
    my $LocalTransport     = read_attribute($MainCf,'local_transport');
    my $mydestination      = read_attribute($MainCf,'mydestination');
    
    if( $mydestination eq '' )
    {
	$MailLocalDelivery{'Type'}      = 'none';
    }
    elsif( $MailboxCommand eq '' && $MailboxTransport eq '')
    {
       $MailLocalDelivery{'Type'}      = 'local';
       if( $MailboxSizeLimit =~ /^\d+$/ )
       {
            $MailLocalDelivery{'MailboxSizeLimit'}  = int(($MailboxSizeLimit + 1023) / 1024);
       } 
       if( $HomeMailbox ne '' )
       {
           $MailLocalDelivery{'SpoolDirectory'} = '$HOME/'.$HomeMailbox;
       }
       elsif ( $MailSpoolDirectory ne '' )
       {
           $MailLocalDelivery{'SpoolDirectory'} = $MailSpoolDirectory;
       }
       else
       {
           $MailLocalDelivery{'SpoolDirectory'} = '/var/spool/mail';
       }
    }
    elsif($MailboxCommand =~ /\/usr\/bin\/procmail/)
    {
        $MailLocalDelivery{'Type'} = 'procmail';
    }
    elsif($MailboxTransport =~ /lmtp:unix:\/var\/lib\/imap\/socket\/lmtp/)
    {
        $MailLocalDelivery{'Type'} = 'cyrus';
        $MailLocalDelivery{'MailboxSizeLimit'}         = SCR->Read('.etc.imapd_conf.autocreatequota') || 0;
        $MailLocalDelivery{'QuotaLimit'}               = SCR->Read('.etc.imapd_conf.quotawarn') || 0;
        $MailLocalDelivery{'ImapIdleTime'}             = SCR->Read('.etc.imapd_conf.timeout') || 0;
        $MailLocalDelivery{'PopIdleTime'}              = SCR->Read('.etc.imapd_conf.poptimeout') || 0;
        $MailLocalDelivery{'FallBackMailbox'}          = SCR->Read('.etc.imapd_conf.lmtp_luser_relay') || '';
        if(  SCR->Read('.etc.imapd_conf.altnamespace') eq 'yes' )
	{
            $MailLocalDelivery{'AlternateNameSpace'}   = 1; 
        }
	else
	{
            $MailLocalDelivery{'AlternateNameSpace'}   = 0; 
        }
        if(  SCR->Read('.etc.imapd_conf.lmtp_overquota_perm_failure') eq 'yes' )
	{
            $MailLocalDelivery{'HardQuotaLimit'}       = 1; 
        }
	else
	{
            $MailLocalDelivery{'HardQuotaLimit'}       = 0; 
        }
	SCR->Read('.mail.cyrusconf');
	if( SCR->Read('.etc.imapd_conf.tls_cert_file') && SCR->Read('.etc.imapd_conf.tls_cert_file') ne '' &&
	    SCR->Read('.etc.imapd_conf.tls_key_file')  && SCR->Read('.etc.imapd_conf.tls_key_file')  ne '' &&
	    SCR->Read('.etc.imapd_conf.tls_ca_path')   && SCR->Read('.etc.imapd_conf.tls_ca_path')   ne '' &&
	    SCR->Execute('.mail.cyrusconf.serviceExists','imaps') &&
	    SCR->Execute('.mail.cyrusconf.serviceEnabled','imaps') &&
	    SCR->Execute('.mail.cyrusconf.serviceExists','pop3s') &&
	    SCR->Execute('.mail.cyrusconf.serviceEnabled','pop3s') &&
	    SCR->Read(".target.size", '/etc/ssl/certs/YaST-CA.pem') > 0 )
	{
	    $MailLocalDelivery{'Security'} = 1;
	}
    }
    else
    {
        $MailLocalDelivery{'Type'} = 'none';
    }
    return \%MailLocalDelivery;
}


BEGIN { $TYPEINFO{WriteMailLocalDelivery}  =["function", "boolean",["map", "string", "any"], "string"]; }
sub WriteMailLocalDelivery {
    my $self              = shift;
    my $MailLocalDelivery = shift;
    my $AdminPassword     = shift;

    #If nothing to do we don't do antithing
    if(! $MailLocalDelivery->{'Changed'})
    {
         return $self->SetError( summary =>"Nothing to do",
                                 code    => "PARAM_CHECK_FAILED" );
    }
    
    y2milestone("-- WriteMailLocalDelivery --");
    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }

    # First we read the main.cf
    my $MainCf             = SCR->Read('.mail.postfix.main.table');
#print STDERR Dumper([$MailLocalDelivery]);   
    if(  $MailLocalDelivery->{'Type'} ne 'none')
    {
	write_ldap_maps($MainCf,$ldapMap);
    }
    if(  $MailLocalDelivery->{'Type'} eq 'local')
    {
	write_attribute($MainCf,'mailbox_command','');
	write_attribute($MainCf,'mailbox_transport','');
	if($MailLocalDelivery->{'MailboxSizeLimit'} =~ /^\d+$/)
	{
	     write_attribute($MainCf,'mailbox_size_limit',$MailLocalDelivery->{'MailboxSizeLimit'} * 1024 );     
	}
	else
	{
            return $self->SetError( summary => 'Maximum Mailbox Size value may only contain decimal number in byte',
                                      code    => "PARAM_CHECK_FAILED" );
	}
	if($MailLocalDelivery->{'SpoolDirectory'} =~ /\$HOME\/(.*)/)
	{
	   write_attribute($MainCf,'home_mailbox',$1);
	   write_attribute($MainCf,'mail_spool_directory','');
	}
	elsif(-e $MailLocalDelivery->{'SpoolDirectory'})
	{
	   write_attribute($MainCf,'home_mailbox','');
	   write_attribute($MainCf,'mail_spool_directory',$MailLocalDelivery->{'SpoolDirectory'});
	}
	else
	{
            return $self->SetError( summary => 'Bad value for SpoolDirectory. Possible values are:'.
	                                       '"$HOME/<path>" or a path to an existing directory.',
                                      code  => "PARAM_CHECK_FAILED" );
	}
    }
    elsif( $MailLocalDelivery->{'Type'} eq 'procmail')
    {
        write_attribute($MainCf,'home_mailbox','');     
	write_attribute($MainCf,'mail_spool_directory','');
	write_attribute($MainCf,'mailbox_command','/usr/bin/procmail');
	write_attribute($MainCf,'mailbox_transport','');
    }
    elsif( $MailLocalDelivery->{'Type'} eq 'cyrus')
    {
        write_attribute($MainCf,'home_mailbox','');
	write_attribute($MainCf,'mail_spool_directory','');
	write_attribute($MainCf,'mailbox_command','');
	write_attribute($MainCf,'mailbox_transport','lmtp:unix:/var/lib/imap/socket/lmtp'); 
        SCR->Write('.etc.imapd_conf.autocreatequota',$MailLocalDelivery->{'MailboxSizeLimit'});
        SCR->Write('.etc.imapd_conf.quotawarn',$MailLocalDelivery->{'QuotaLimit'});
        SCR->Write('.etc.imapd_conf.timeout',$MailLocalDelivery->{'ImapIdleTime'});
        SCR->Write('.etc.imapd_conf.poptimeout',$MailLocalDelivery->{'PopIdleTime'});
        SCR->Write('.etc.imapd_conf.allowplaintext','yes');
        SCR->Write('.etc.imapd_conf.unixhierarchysep','yes');
        SCR->Write('.etc.imapd_conf.allowplainwithouttls','yes');
        if($MailLocalDelivery->{'FallBackMailbox'} ne ''  )
	{
           SCR->Write('.etc.imapd_conf.lmtp_luser_relay',$MailLocalDelivery->{'FallBackMailbox'});
        }
	else
	{
           SCR->Write('.etc.imapd_conf.lmtp_luser_relay',undef);
        }
        if( $MailLocalDelivery->{'AlternateNameSpace'} )
	{
	    SCR->Write('.etc.imapd_conf.altnamespace','yes');
	}
	else
	{
	    SCR->Write('.etc.imapd_conf.altnamespace','no');
	}
        if( $MailLocalDelivery->{'HardQuotaLimit'} )
	{
	    SCR->Write('.etc.imapd_conf.lmtp_overquota_perm_failure','yes');
        }
	else
	{
	    SCR->Write('.etc.imapd_conf.lmtp_overquota_perm_failure','no');
        }
        if($MailLocalDelivery->{'Security'} )
	{
	  my $size = SCR->Read(".target.size", '/etc/ssl/servercerts/servercert.pem');
          if ($size <= 0)
	  {
              return $self->SetError(summary => "Common server certificate not found.",
                                     code => "PARAM_CHECK_FAILED");
          }
          $size = SCR->Read(".target.size", '/etc/ssl/servercerts/serverkey.pem');
          if ($size <= 0)
	  {
              return $self->SetError(summary => "Common private key not found.",
                                     code => "PARAM_CHECK_FAILED");
          }
          system("setfacl -m g:mail:r /etc/ssl/servercerts/serverkey.pem");
          SCR->Write('.etc.imapd_conf.tls_cert_file','/etc/ssl/servercerts/servercert.pem');
          SCR->Write('.etc.imapd_conf.tls_key_file','/etc/ssl/servercerts/serverkey.pem');
          if(SCR->Read(".target.size", '/etc/ssl/certs/YaST-CA.pem') > 0)
	  {
              #SCR->Write('.etc.imapd_conf.tls_ca_file','/etc/ssl/certs/YaST-CA.pem');
              SCR->Write('.etc.imapd_conf.tls_ca_path','/etc/ssl/certs');
          }
	  SCR->Read('.mail.cyrusconf');
	  if( SCR->Execute('.mail.cyrusconf.serviceExists', 'imaps') &&
	      ! SCR->Execute('.mail.cyrusconf.serviceEnabled', 'imaps') )
	  {
	      SCR->Execute('.mail.cyrusconf.toggleService', 'imaps');
	  }
	  elsif( ! SCR->Execute('.mail.cyrusconf.serviceExists', 'imaps') )
	  {
	      SCR->Execute('.mail.cyrusconf.addService', { sname => "imaps",
							   sarg  => "imapd -s",
							   sport => "imaps" });
	  }
	  if( SCR->Execute('.mail.cyrusconf.serviceExists', 'pop3s') &&
	      ! SCR->Execute('.mail.cyrusconf.serviceEnabled', 'pop3s') )
	  {
	      SCR->Execute('.mail.cyrusconf.toggleService', 'pop3s');
	  }
	  elsif( ! SCR->Execute('.mail.cyrusconf.serviceExists', 'pop3s') )
	  {
	      SCR->Execute('.mail.cyrusconf.addService', { sname => "pop3s",
							   sarg  => "pop3d -s",
							   sport => "pop3s" });
	  }
      }
      else
      {
	  SCR->Read('.mail.cyrusconf');
	  if( SCR->Execute('.mail.cyrusconf.serviceExists', 'imaps') &&
	      SCR->Execute('.mail.cyrusconf.serviceEnabled', 'imaps') )
	  {
	      SCR->Execute('.mail.cyrusconf.toggleService', 'imaps');
	  }
	  if( SCR->Execute('.mail.cyrusconf.serviceExists', 'pop3s') &&
	      SCR->Execute('.mail.cyrusconf.serviceEnabled', 'pop3s') )
	  {
	      SCR->Execute('.mail.cyrusconf.toggleService', 'pop3s');
	  }
      }
      Service->Enable('saslauthd');
      Service->Enable('cyrus');
      if( !Service->Status('saslauthd') )
      {
          Service->Restart('saslauthd');
      }
      else
      {
          Service->Start('saslauthd');
      }
      if( !Service->Status('cyrus') )
      {
          Service->Restart('cyrus');
      }
      else
      {
          Service->Start('cyrus');
      }
    }
    elsif(  $MailLocalDelivery->{'Type'} eq 'none')
    {
        write_attribute($MainCf,'mydestination','');
        write_attribute($MainCf,'virtual_alias_maps','');
        write_attribute($MainCf,'virtual_alias_domains','');
    }
    else
    {
        return $self->SetError( summary => 'Bad value for MailLocalDeliveryType. Possible values are:'.
                                           '"none", "local", "procmail" or "cyrus".',
                                  code  => "PARAM_CHECK_FAILED" );
    }

    SCR->Write('.mail.postfix.main.table',$MainCf);
    SCR->Write('.mail.postfix.main',undef);
    SCR->Write('.etc.imapd_conf',undef);
    SCR->Write('.mail.cyrusconf',undef);
    return 1;
}

BEGIN { $TYPEINFO{CreateRootMailbox}     =["function", "any", "string"]; }
sub CreateRootMailbox {
    my $self            = shift;
    my $AdminPassword   = shift;

      #Create mailbox for root
      my $imap = new Net::IMAP($imaphost, Debug => 0);
      if( $imap )
      {
	  my $ret = $imap->login($imapadm, $AdminPassword);
	  if($$ret{Status} eq "ok")
	  {
	      $ret = $imap->select('usr/root'); 
	      if( $ret->{Status} ne 'ok' )
	      {
	          $ret = $imap->create('user/root'); 
		  $ret = $imap->setacl('user/root', 'cyrus', "lrswipkxtea");
		  $ret = $imap->setacl('user/root', 'root', "lrswipkxtea");
		  $ret = $imap->setacl('user/root', 'anyone', "" );
	      }
	  }
          $imap->logout();
      }
}

BEGIN { $TYPEINFO{ReadFetchingMail}     =["function", "any", "string"]; }
sub ReadFetchingMail {
    my $self            = shift;
    my $AdminPassword   = shift;

    my %FetchingMail = (
                                'Changed'         => YaST::YCP::Boolean(0),
                                'FetchByDialIn'   => 0,
                                'Interface'       => "",
                                'FetchMailSteady' => 1,
                                'FetchingInterval'=> 30,
				'Items'           => []     
				
                       );
#    my $CronTab                 = SCR->Read('.cron','/etc/crontab',\%FetchingMail);
    my $FetchingInterval        = SCR->Read('.sysconfig.fetchmail.FETCHMAIL_POLLING_INTERVAL') || 0; 
    $FetchingMail{'FetchingInterval'} = $FetchingInterval / 60;

    if(! Service->Enabled('fetchmail'))
    {
        $FetchingMail{'FetchMailSteady'} = 0;
    }

    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }

    $FetchingMail{'Items'} = SCR->Read('.mail.fetchmail.accounts');
    
#print STDERR Dumper(%FetchingMail);    

    return \%FetchingMail;
}

BEGIN { $TYPEINFO{WriteFetchingMail}    =["function", "boolean", ["map", "string", "any"], "string"]; }
sub WriteFetchingMail {
    my $self            = shift;
    my $FetchingMail    = shift;
    my $AdminPassword   = shift;

    #If nothing to do we don't do antithing
    if(! $FetchingMail->{'Changed'})
    {
         return $self->SetError( summary =>"Nothing to do",
                                 code    => "PARAM_CHECK_FAILED" );
    }
   
    y2milestone("-- WriteFetchingMail --");
    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }

#print STDERR Dumper([$FetchingMail]);  
    if($FetchingMail->{'Interface'} ne '')
    {
       NetworkInterfaces->Read();
       if($FetchingMail->{'FetchByDialIn'})
       {
          NetworkInterfaces->SetValue($FetchingMail->{'Interface'},'RUN_POLL_TCPIP','yes');
       }
       else
       {
          NetworkInterfaces->SetValue($FetchingMail->{'Interface'},'RUN_POLL_TCPIP','no');
       }
       NetworkInterfaces->Write('ppp|ipp|dsl');
    }
    if($FetchingMail->{'FetchMailSteady'})
    {
       my $FetchingInterval = $FetchingMail->{'FetchingInterval'} * 60;
       SCR->Write('.sysconfig.fetchmail.FETCHMAIL_POLLING_INTERVAL',$FetchingInterval);
       SCR->Write('.sysconfig.fetchmail',undef);
       Service->Enable('fetchmail');
    }
    else
    {
       Service->Disable('fetchmail');
    }

    SCR->Write('.mail.fetchmail.accounts',$FetchingMail->{'Items'});
    SCR->Write('.mail.fetchmail',undef);
    return 1;
}

BEGIN { $TYPEINFO{ReadMailLocalDomains}  =["function", "any", "string"]; }
sub ReadMailLocalDomains {
    my $self             = shift;
    my $AdminPassword    = shift;
    my %MailLocalDomains = (
                                'Changed'         => YaST::YCP::Boolean(0),
                                'Domains'         => []
                           );

    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }
    my $ret = SCR->Read(".ldap.search", {
                                          "base_dn"      => $ldapMap->{'dns_config_dn'},
                                          "filter"       => '(relativeDomainName=@)',
                                          "scope"        => 2,
                                          "not_found_ok" => 1,
                                          "attrs"        => [ 'zoneName', 'suseMailDomainMasquerading', 'suseMailDomainType' ]
                                         });
    if (! defined $ret)
    {
        my $ldapERR = SCR->Read(".ldap.error");
        return $self->SetError(summary => "LDAP search failed!",
                               description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'},
                               code => "LDAP_SEARCH_FAILED");
    }
    foreach(@{$ret})
    {
       my $domain = {};
       if( $_->{'zoneName'}->[0] !~ /in-addr.arpa$/i)
       {
         $domain->{'Name'}         = $_->{'zoneName'}->[0];
         $domain->{'Type'}         = $_->{'suseMailDomainType'}->[0]         || 'none';
         $domain->{'Masquerading'} = $_->{'suseMailDomainMasquerading'}->[0] || 'yes';
         push @{$MailLocalDomains{'Domains'}}, $domain;
       }
    }
    return \%MailLocalDomains;
}

BEGIN { $TYPEINFO{WriteMailLocalDomains} =["function", "boolean", ["map", "string", "any"], "string"]; }
sub WriteMailLocalDomains {
    my $self             = shift;
    my $MailLocalDomains = shift;
    my $AdminPassword    = shift;

    my $Domains          = {};

    # We have to work with yast2-dns-server together
    if( -e '/etc/sysconfig/named' )
    {
	my $reload_script = SCR->Read (".sysconfig.named.NAMED_INITIALIZE_SCRIPTS") || "";
	my @reload_scripts = split / /, ((defined $reload_script) ? $reload_script:"");
	my $already_present = scalar (grep (/ldapdump/, @reload_scripts)) > 0;
        if (! $already_present)
        {
            push @reload_scripts, "ldapdump";
	    SCR->Write (".sysconfig.named.NAMED_INITIALIZE_SCRIPTS", $reload_script);
	    SCR->Write (".sysconfig.named", undef);
        }
    }

    #If nothing to do we don't do antithing
    if(! $MailLocalDomains->{'Changed'})
    {
         return $self->SetError( summary =>"Nothing to do",
                                 code    => "PARAM_CHECK_FAILED" );
    }
    
    y2milestone("-- WriteMailLocalDomains --");
    # Make LDAP Connection 
    my $ldapMap = $self->ReadLDAPDefaults($AdminPassword);
    if( !$ldapMap )
    {
         return undef;
    }
    foreach(@{$MailLocalDomains->{'Domains'}})
    {
      my $name          = $_->{'Name'};
      my $type          = $_->{'Type'} || 'local';
      my $masquerading  = $_->{'Masquerading'} || 'yes';
      if($type !~ /local|virtual|main|none/)
      {
         return $self->SetError( summary =>"Invalid mail local domain type.".
	                                   " Domain: $name; Type $type".
					   "Allowed values are: local|virtual|main.",
                                 code    => "PARAM_CHECK_FAILED" );
      }
      if($masquerading !~ /yes|no/)
      {
         return $self->SetError( summary =>"Invalid mail local domain masquerading value.".
	                                   " Domain: $name; Masquerading: $masquerading".
					   "Allowed values are: yes|no.",
                                 code    => "PARAM_CHECK_FAILED" );
      }
      my $DN = "zoneName=$name,$ldapMap->{'dns_config_dn'}";
      my $retVal = SCR->Read('.ldap.search',{
                                             "base_dn"      => $DN,
                                             "filter"       => '(objectClass=dNSZone)',
                                             "scope"        => 0,
                                             "not_found_ok" => 0
                                            } ); 

      if( defined $retVal && defined $retVal->[0] && defined $retVal->[0]->{'objectClass'}) 
      {
            my $found = 0;
            foreach my $ojc ( @{$retVal->[0]->{'objectClass'}} )
	    {
                if($ojc =~ /^suseMailDomain$/i) {
                    $found = 1;
                    last;
                }
            }
            if($found && $type eq 'none')
	    {
                # delete objectClass

                $Domains->{$DN}->{'objectClass'}                = ['dNSZone'];
                $Domains->{$DN}->{'suseMailDomainType'}         = [];
                $Domains->{$DN}->{'suseMailDomainMasquerading'} = [];

                if( ! SCR->Write('.ldap.modify',{ "dn" => $DN } , $Domains->{$DN}))
		{
                    my $ldapERR = SCR->Read(".ldap.error");
                    return $self->SetError(summary => "LDAP add failed",
                                           code => "SCR_INIT_FAILED",
                                           description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
                }

            }
	    elsif (!$found && $type eq 'none')
	    {
                # do nothing

            }
	    else
	    {
                # modify

                $Domains->{$DN}->{'objectClass'}                = ['dNSZone','suseMailDomain'];
                $Domains->{$DN}->{'zoneName'}                   = $name;
                $Domains->{$DN}->{'suseMailDomainType'}         = $type;
                $Domains->{$DN}->{'suseMailDomainMasquerading'} = $masquerading;
                
                if( ! SCR->Write('.ldap.modify',{ "dn" => $DN } , $Domains->{$DN}))
		{
                    my $ldapERR = SCR->Read(".ldap.error");
                    return $self->SetError(summary => "LDAP modify failed",
                                           code => "SCR_INIT_FAILED",
                                           description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
                }
            }

        }
	else
	{
		# This is a new domain, we create it. 
		# We create all the DNS attributes. `hostname -f` is the NS and MX entry.
		my $serial = POSIX::strftime("%Y%m%d%H",localtime);
		my $host   = `hostname -f`; chomp $host;
		if( ! $host )
		{
		        $host = `cat /etc/HOSTNAME`; chomp $host;
		        if( ! $host )
		        {
		     	   $host = 'linux.lokal';
		        }
		}
		my $tmp = { 'Objectclass'                  => [ 'dNSZone','suseMailDomain' ],
		      'zoneName'                     => $name,
		      'suseMailDomainType'           => $type,
		      'suseMailDomainMasquerading'   => $masquerading,
		      'relativeDomainName'	     => '@',
		      'dNSClass'	             => 'IN',
		      'dNSTTL'	                     => '86400',
		      'nSRecord'		     => $host.'.',
		      'mXRecord'		     => '40 '.$host.'.',
		      'sOARecord'                    => $host.'. root.'.$host.'. '.$serial.' 10800 3600 302400 43200'
		 };
		if(! SCR->Write('.ldap.add',{ "dn" => $DN } ,$tmp)){
			my $ldapERR = SCR->Read(".ldap.error");
			return $self->SetError(summary     => "LDAP add failed",
					   code        => "SCR_WRITE_FAILED",
					   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
		}
       }
    }


    # First we read the main.cf
    my $MainCf             = SCR->Read('.mail.postfix.main.table');
    write_attribute($MainCf,'masquerade_classes','envelope_sender, header_sender, header_recipient');
    write_attribute($MainCf,'masquerade_exceptions','root');
    write_ldap_maps($MainCf,$ldapMap);
    SCR->Write('.mail.postfix.main.table',$MainCf);
    SCR->Write('.mail.postfix.main',undef);
    return 1;
}

=item *

C<$LDAPMap = ReadLDAPDefaults($AdminPassword)>

Reads the LDAP Configuration:
   The LDAP Base
   The LDAP Base for the User Configuration
   The LDAP Base for the Group Configuration
   The LDAP Base for the DNS Configuration
   The LDAP Base for the MAIL Configuration
   The LDAP Template for the MAIL Configuration
If the last there does not exist this will be created.

The result is an hash of following structur:

   $ldapMap = {
         'ldap_server'    => ...,
         'ldap_port'      => ...,
         'bind_pw'        => ...,
         'bind_dn'        => ...,
         'mail_config_dn' => ...,
         'dns_config_dn'  => ...,
         'user_config_dn' => ...,
         'group_config_dn'=> ...,
         
   }

=cut

BEGIN { $TYPEINFO{ReadLDAPDefaults} = ["function", ["map", "string", "any"], "string"]; }
sub ReadLDAPDefaults {
    my $self          = shift;
    my $AdminPassword = shift;

    my $ldapMap       = {};
    my $admin_bind    = {};
    my $ldapret       = undef;
    my $first_use     = 0;

    if(Ldap->Read())
    {
        $ldapMap = Ldap->Export();
        if(defined $ldapMap->{'ldap_server'} && $ldapMap->{'ldap_server'} ne "")
	{
            my $dummy = $ldapMap->{'ldap_server'};
            $ldapMap->{'ldap_server'} = Ldap->GetFirstServer("$dummy");
            $ldapMap->{'ldap_port'} = Ldap->GetFirstPort("$dummy");
        }
	else
	{
            return $self->SetError( summary => "No LDAP Server configured",
                                    code => "HOST_NOT_FOUND");
        }
    }
#print STDERR Dumper([$ldapMap]);
    # Now we try to bind to the LDAP
    if (! SCR->Execute(".ldap", {"hostname" => $ldapMap->{'ldap_server'},
                                 "port"     => $ldapMap->{'ldap_port'}}))
    {
        return $self->SetError(summary => "LDAP init failed",
                               code => "SCR_INIT_FAILED");
    }

    $ldapMap->{'bind_pw'} = $AdminPassword;
    if(! SCR->Execute('.ldap.bind',$ldapMap))
    {
         my $ldapERR = SCR->Read('.ldap.error');
         return $self->SetError(summary     => "LDAP bind failed!",
                                description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'},
                                code        => "LDAP_BIND_FAILED");
    }
    
    # read mail configuration data
    $ldapret = SCR->Read(".ldap.search", {
	"base_dn"      => $ldapMap->{'base_config_dn'},
	"filter"       => '(objectClass=suseMailConfiguration)',
	"scope"        => 2,
	"not_found_ok" => 1,
	"attrs"        => [ 'suseDefaultBase' ]
	});
    if (! defined $ldapret)
    {
        my $ldapERR = SCR->Read(".ldap.error");
        return $self->SetError(summary => "LDAP search failed!",
                               description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'},
                               code => "LDAP_SEARCH_FAILED");
    }
    if(@$ldapret > 0)
    {
        $ldapMap->{'mail_config_dn'} = $ldapret->[0]->{'suseDefaultBase'}->[0];
    }
    else
    {
	# mailconfiguration does not yet exist, so create it
	my $configOBJ;
	my $CONFIG_BASE = "cn=Mailserver,".$ldapMap->{'base_config_dn'};
	my $defaultBase = "ou=Mailserver,".$ldapMap->{'ldap_domain'};
        $ldapMap->{'mail_config_dn'} = $defaultBase;
	$configOBJ->{$CONFIG_BASE}->{'objectClass'} = 'suseMailConfiguration';
	$configOBJ->{$CONFIG_BASE}->{'cn'} = 'Mailserver';
	$configOBJ->{$CONFIG_BASE}->{'suseDefaultBase'} = $defaultBase;
	$configOBJ->{$CONFIG_BASE}->{'suseImapServer'} = "localhost";
	$configOBJ->{$CONFIG_BASE}->{'suseImapAdmin'} = "cyrus";
	$configOBJ->{$CONFIG_BASE}->{'suseImapUseSsl'} = "FALSE";
	$configOBJ->{$CONFIG_BASE}->{'suseImapDefaultQuota'} = 10000;
	$ldapMap->{'bind_pw'} = $AdminPassword;
	if (! SCR->Execute(".ldap.bind", $ldapMap) )
	{
	    my $ldapERR = SCR->Read(".ldap.error");
	    return $self->SetError(summary => "LDAP bind failed",
				   code => "SCR_INIT_FAILED",
				   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
	}
	if( ! SCR->Write('.ldap.add',
			 { "dn" => $CONFIG_BASE },
			 $configOBJ->{$CONFIG_BASE} ) )
	{
            my $ldapERR = SCR->Read(".ldap.error");
            return $self->SetError(summary => "LDAP add failed",
				   code => "SCR_INIT_FAILED",
				   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
	}
        $first_use = 1;
    }


    # check whether ou=Mailserver tree exists
    $ldapret = SCR->Read(".ldap.search", {
	"base_dn"      => $ldapMap->{'ldap_domain'},
	"filter"       => '(&(ou=Mailserver)(objectClass=organizationalUnit))',
	"scope"        => 2,
	"not_found_ok" => 1,
	"attrs"        => [ 'ou' ]
	});
    if (! defined $ldapret)
    {
        my $ldapERR = SCR->Read(".ldap.error");
        return $self->SetError(summary => "LDAP search failed!",
                               description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'},
                               code => "LDAP_SEARCH_FAILED");
    }
    if( @$ldapret == 0)
    {
	# create it
	my $configOBJ;
	my $uBase = "ou=Mailserver,".$ldapMap->{'ldap_domain'};
	$configOBJ->{$uBase}->{'objectClass'} = 'organizationalUnit';
	$configOBJ->{$uBase}->{'ou'} = 'Mailserver';
	$ldapMap->{'bind_pw'} = $AdminPassword;
	if (! SCR->Execute(".ldap.bind", $ldapMap) )
	{
	    my $ldapERR = SCR->Read(".ldap.error");
	    return $self->SetError(summary => "LDAP bind failed",
				   code => "SCR_INIT_FAILED",
				   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
	}
	if( ! SCR->Write('.ldap.add', { "dn" => $uBase }, $configOBJ->{$uBase} ) )
	{
            my $ldapERR = SCR->Read(".ldap.error");
            return $self->SetError(summary => "LDAP add failed",
				   code => "SCR_INIT_FAILED",
				   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
	}
	$uBase = "ou=Aliases,ou=Mailserver,".$ldapMap->{'ldap_domain'};
	$configOBJ->{$uBase}->{'objectClass'} = 'organizationalUnit';
	$configOBJ->{$uBase}->{'ou'} = 'Aliases';
	if( ! SCR->Write('.ldap.add', { "dn" => $uBase }, $configOBJ->{$uBase} ) )
	{
            my $ldapERR = SCR->Read(".ldap.error");
            return $self->SetError(summary => "LDAP add failed",
				   code => "SCR_INIT_FAILED",
				   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
	}
	$uBase = "ou=Canonical,ou=Mailserver,".$ldapMap->{'ldap_domain'};
	$configOBJ->{$uBase}->{'objectClass'} = 'organizationalUnit';
	$configOBJ->{$uBase}->{'ou'} = 'Canonical';
	if( ! SCR->Write('.ldap.add', { "dn" => $uBase }, $configOBJ->{$uBase} ) )
	{
            my $ldapERR = SCR->Read(".ldap.error");
            return $self->SetError(summary => "LDAP add failed",
				   code => "SCR_INIT_FAILED",
				   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
	}
    }


    # check whether mail plugin is already in the pluginlist
    $ldapret = SCR->Read(".ldap.search", {
	"base_dn"      => $ldapMap->{'base_config_dn'},
	"filter"       => '(objectClass=suseUserTemplate)',
	"scope"        => 2,
	"not_found_ok" => 1
	});
    if (! defined $ldapret)
    {
        my $ldapERR = SCR->Read(".ldap.error");
        return $self->SetError(summary => "LDAP search failed!",
                               description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'},
                               code => "LDAP_SEARCH_FAILED");
    }
    if( @$ldapret > 0)
    {
	# 
	my $foundplugin = 0;
	if( defined $ldapret->[0]->{'susePlugin'} )
	{
	    foreach my $sp ( @{$ldapret->[0]->{'susePlugin'}} )
	    {
		$foundplugin = 1 if lc($sp) eq "userspluginmail";
	    }
	    if( ! $foundplugin )
	    {
		$ldapMap->{'bind_pw'} = $AdminPassword;
		if (! SCR->Execute(".ldap.bind", $ldapMap) )
		{
		    my $ldapERR = SCR->Read(".ldap.error");
		    return $self->SetError(summary => "LDAP bind failed",
					   code => "SCR_INIT_FAILED",
					   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
		}
		my $dn = "cn=userTemplate,".$ldapMap->{'base_config_dn'};
		my $pluginlist = $ldapret->[0]->{'susePlugin'};
		push @$pluginlist, 'UsersPluginMail';
		if( ! SCR->Write('.ldap.modify',
				 { "dn" => $dn },
				 { 'susePlugin' => $pluginlist } ) )
		{
		    my $ldapERR = SCR->Read(".ldap.error");
		    return $self->SetError(summary => "LDAP modify failed",
					   code => "SCR_INIT_FAILED",
					   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
		}
	    }
	}
    }
    else
    {
        return $self->SetError(summary => "Plugintemplate not found",
                               description => "The entry cn=userTemplate,$ldapMap->{'base_config_dn'} is missing in the LDAP server.",
                               code => "MAIL_PLUGIN_TEMPLATE_NOT_FOUND");
    }
    
    # now we search user base
    $ldapret = SCR->Read(".ldap.search", {
                                          "base_dn"      => $ldapMap->{'base_config_dn'},
                                          "filter"       => '(objectClass=suseUserConfiguration)',
                                          "scope"        => 2,
                                          "not_found_ok" => 1,
                                          "attrs"        => [ 'suseDefaultBase' ]
                                         });
    if (! defined $ldapret)
    {
        my $ldapERR = SCR->Read(".ldap.error");
        return $self->SetError(summary => "LDAP search failed!",
                               description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'},
                               code => "LDAP_SEARCH_FAILED");
    }
    if(@$ldapret > 0)
    {
        $ldapMap->{'user_config_dn'} = $ldapret->[0]->{'suseDefaultBase'}->[0];
    }
    # now we search group base
    $ldapret = SCR->Read(".ldap.search", {
                                          "base_dn"      => $ldapMap->{'base_config_dn'},
                                          "filter"       => '(objectClass=suseGroupConfiguration)',
                                          "scope"        => 2,
                                          "not_found_ok" => 1,
                                          "attrs"        => [ 'suseDefaultBase' ]
                                         });
    if (! defined $ldapret)
    {
        my $ldapERR = SCR->Read(".ldap.error");
        return $self->SetError(summary => "LDAP search failed!",
                               description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'},
                               code => "LDAP_SEARCH_FAILED");
    }
    if(@$ldapret > 0)
    {
        $ldapMap->{'group_config_dn'} = $ldapret->[0]->{'suseDefaultBase'}->[0];
    }
    # now we search DNS base
    $ldapret = SCR->Read(".ldap.search", {
                                          "base_dn"      => $ldapMap->{'base_config_dn'},
                                          "filter"       => '(objectClass=suseDNSConfiguration)',
                                          "scope"        => 2,
                                          "not_found_ok" => 1,
                                          "attrs"        => [ 'suseDefaultBase' ]
                                         });
    if (! defined $ldapret)
    {
        my $ldapERR = SCR->Read(".ldap.error");
        return $self->SetError(summary => "LDAP search failed!",
                               description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'},
                               code => "LDAP_SEARCH_FAILED");
    }
    if(@$ldapret > 0) {
        $ldapMap->{'dns_config_dn'} = $ldapret->[0]->{'suseDefaultBase'}->[0];
    }
    else
    {
       # We create the DNS config if there is no any.
       my $DN  = 'ou=DNS,'.$ldapMap->{'ldap_domain'};
       my $tmp = { objectClass     => [ "top" , "suseDnsConfiguration" ],
                   cn              => 'defaultDNS',
		   suseDefaultBase => $DN
                 };
       if( ! SCR->Write('.ldap.add', { dn => 'cn=defaultDNS,'.$ldapMap->{'base_config_dn'} }, $tmp ) )
       {
            my $ldapERR = SCR->Read(".ldap.error");
            return $self->SetError(summary => "LDAP add failed",
				   code => "SCR_INIT_FAILED",
				   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
       }
       $ldapMap->{'dns_config_dn'} = $DN;
    }   
    $ldapret = SCR->Read(".ldap.search", {
                                          "base_dn"      => $ldapMap->{'dns_config_dn'},
                                          "filter"       => '(ou=DNS)',
                                          "scope"        => 0,
                                          "not_found_ok" => 1,
                                          "attrs"        => [ 'ou' ]
                                         });
    if (! defined $ldapret)
    {
        my $ldapERR = SCR->Read(".ldap.error");
        return $self->SetError(summary => "LDAP search failed!",
                               description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'},
                               code => "LDAP_SEARCH_FAILED");
    }
    if(@$ldapret != 1)
    {
       # There is no ou=DNS object, we create it.
       my $tmp = { objectClass => [ 'top' , 'organizationalUnit' ],
                   ou          => 'DNS'     
               };
       if( ! SCR->Write('.ldap.add', { dn => $ldapMap->{'dns_config_dn'}}, $tmp ) ) 
       {
            my $ldapERR = SCR->Read(".ldap.error");
            return $self->SetError(summary => "LDAP add failed",
				   code => "SCR_INIT_FAILED",
				   description => $ldapERR->{'code'}." : ".$ldapERR->{'msg'});
       }
    }
    return $ldapMap;
}
##
 # Create a textual summary and a list of unconfigured cards
 # @return summary of the current configuration
 #
BEGIN { $TYPEINFO{Summary} = ["function", [ "list", "string" ] ]; }
sub Summary {
    # TODO FIXME: your code here...
    # Configuration summary text for autoyast
    return (
        _("Configuration summary ...")
    );
}

##
 # Create an overview table with all configured cards
 # @return table items
 #
BEGIN { $TYPEINFO{Overview} = ["function", [ "list", "string" ] ]; }
sub Overview {
    # TODO FIXME: your code here...
    return ();
}

##
 # Return packages needed to be installed and removed during
 # Autoinstallation to insure module has all needed software
 # installed.
 # @return hash with 2 lists.
 #
BEGIN { $TYPEINFO{AutoPackages} = ["function", ["map", "string", ["list", "string"]]]; }
sub AutoPackages {
    # TODO FIXME: your code here...
    my %ret = (
        "install" => (),
        "remove" => (),
    );
    return \%ret;
}

=item *

C<boolean = ResetMailServer($AdminPassword)>

Funktion to reset the mail server configuration:
Needed Parameters are:
   $AdminPassword the Adminstrator Psssword

   Sets Maximum Mail Size to 10MB
   Sets Sending Mail Type to DNS
   Sets Mail Server Basic Protection to off
   Sets Mail Local Delivery Type to local
   Sets up the needed LDAP lookup tables
   Sets the postfix variables:
      mydestination
      masquerade_classes
      masquerade_exceptions

=cut
BEGIN { $TYPEINFO{ResetMailServer} = ["function",  "boolean" ,"string"]; }
sub ResetMailServer {
    my $self            = shift;
    my $AdminPassword   = shift;
    my $ldapMap         = $self->ReadLDAPDefaults($AdminPassword);
    my $check_postfix = 'if [ -z "$(id postfix | grep -E \'groups=.*mail\')" ]; then
usermod -G mail postfix
fi';

    # Now we setup postfix basicaly
    SCR->Write(".sysconfig.mail.MAIL_CREATE_CONFIG","yes");
    SCR->Write(".sysconfig.mail",undef);
    SCR->Execute(".target.bash", "SuSEconfig -module postfix");
    SCR->Write(".sysconfig.mail.MAIL_CREATE_CONFIG","no");
    SCR->Write(".sysconfig.mail",undef);

    #Put user postfix into the group mail
    system($check_postfix);

    #Setup Global Settings;
    my $TLS = "use";
    my $size = SCR->Read(".target.size", '/etc/ssl/servercerts/servercert.pem');
    if ($size <= 0)
    {
	$TLS = "none";	
    }
    my $TMP = $self->ReadGlobalSettings($AdminPassword);
       $TMP->{'Changed'}               = 1;
       $TMP->{'MaximumMailSize'}       = '10240000';
       $TMP->{'Interfaces'}            = 'all';
       $TMP->{'SendingMail'}->{'Type'} = 'DNS';
       $TMP->{'SendingMail'}->{'TLS'}  = 'NONE';
       $self->WriteGlobalSettings($TMP,$AdminPassword); 
    #Setup Mail Server Preventions
       $TMP = $self->ReadMailPrevention($AdminPassword);
       $TMP->{'Changed'}               = 1;
       $TMP->{'BasicProtection'}       = 'medium';
       $TMP->{'VirusScanning'}         = 1;
       $TMP->{'VSCount'}               = 2;
       $TMP->{'SpamLearning'}          = 0;
       $self->WriteMailPrevention($TMP,$AdminPassword); 
    #Setup Mail Server Relaying

       $TMP = $self->ReadMailRelaying($AdminPassword);
       $TMP->{'Changed'}               = 1;
       $TMP->{'RequireSASL'}           = '0';
       $TMP->{'SMTPDTLSMode'}          = $TLS;
       $self->WriteMailRelaying($TMP,$AdminPassword); 
    #Setup Local Delivery
       $TMP = $self->ReadMailLocalDelivery($AdminPassword);
       $TMP->{'Changed'}               = 1;
       $TMP->{'Type'}                  = 'local';
       $TMP->{'MailboxSizeLimit'}      = 0;
       $TMP->{'SpoolDirectory'}        = '/var/spool/mail';
       $self->WriteMailLocalDelivery($TMP,$AdminPassword); 

    #Read the main configuration
    my $MainCf             = SCR->Read('.mail.postfix.main.table');

    # Setup the tlsmanager service if necessary
    if( ! SCR->Read('.mail.postfix.mastercf') )
    {
       return $self->SetError( summary =>"Couln't open master.cf",
                               code    => "PARAM_CHECK_FAILED" );
    }
    my $tlsmgr = SCR->Execute('.mail.postfix.mastercf.findService',
                   { 'service' => 'tlsmgr',
                     'command' => 'tlsmgr' });
    if( $TLS eq "use" )
    {
      write_attribute($MainCf,'smtpd_tls_cert_file','/etc/ssl/servercerts/servercert.pem');
      write_attribute($MainCf,'smtpd_tls_key_file','/etc/ssl/servercerts/serverkey.pem');
      if(SCR->Read(".target.size", '/etc/ssl/certs/YaST-CA.pem') > 0)
      {
          #write_attribute($MainCf,'smtpd_tls_CAfile','/etc/ssl/certs/YaST-CA.pem');
          write_attribute($MainCf,'smtpd_tls_CApath','/etc/ssl/certs');
      }
      if(! defined $tlsmgr )
      {
           SCR->Execute('.mail.postfix.mastercf.addService',
           { 'service' => 'tlsmgr',
             'type'    => 'unix',
             'private' => '-',
             'unpriv'  => '-',
             'chroot'  => 'n',
             'wakeup'  => '1000?',
             'maxproc' => '1',
             'command' => 'tlsmgr' });
      }
    }
    else
    {
      if( defined $tlsmgr )
      {
         SCR->Execute('.mail.postfix.mastercf.deleteService', {'service' => 'tlsmgr','command' => 'tlsmgr'});
      }
    }
    write_attribute($MainCf,'masquerade_classes','envelope_sender, header_sender, header_recipient');
    write_attribute($MainCf,'masquerade_exceptions','root');
    #Setup the ldap tables;
    write_ldap_maps($MainCf,$ldapMap);
    SCR->Write('.mail.postfix.main.table',$MainCf);
    SCR->Write('.mail.postfix.main',undef);
    SCR->Write('.mail.postfix.mastercf',undef);
    SCR->Execute(".target.bash", "touch /var/adm/yast2-mail-server-used");

    return 1;
}

sub activate_virus_scanner {
   my $VSCount = shift || 5;
   use File::Copy;
   
   my $cconf = "/etc/clamd.conf";
   my $clamsock = '/var/lib/clamav/clamd-socket';
   my @CONF = ();
   
   if( ! open(IN,$aconf) )
   {
       return "Error: $!";
   }
   my @ACONF = <IN>;
   close(IN);
   
   my $isclam       = 0;
   my $ismax        = 0;
   my $ismyhostname = 0;
   my $myhostname   = `hostname -f`; chomp $myhostname;
   my $mydomain     = `hostname -d`; chomp $mydomain;
   if( ! $myhostname )
   {
	   $myhostname = `cat /etc/HOSTNAME`; chomp $myhostname;
	   if( ! $myhostname )
	   {
		   $myhostname = 'linux.lokal';
	   }
   }
   if( ! $mydomain )
   {
	   my $tmp;
	   ( $tmp, $mydomain) = split /,/,$myhostname,2;
   }
   foreach my $l ( @ACONF )
   {
	if ( $l =~ s/^\$max_servers = .*;/\$max_servers = $VSCount;/ )
	{
	   next if $ismax;
	   $ismax = 1;
	}
	if ( $l =~ s/^\$myhostname = .*;/\$myhostname = '$myhostname';/ )
	{
	   next if $ismyhostname;
	   $ismyhostname = 1;
	}
	if ( $l =~ s/^\$mydomain = .*;/\$mydomain = '$mydomain';/ )
	{
	   push @CONF, $l;
	   next ;
	}
   	$l =~ s/(.*)/# $1/ if $l =~ /bypass_virus_checks_acl.*=.*qw\( \./;
   	if( $isclam || $l =~ /Clam Antivirus-clamd/ )
	{
   	    $isclam = 1 if $l =~ /Clam Antivirus-clamd/;
   	    $isclam = 0 if $l =~ /Infected Archive.*FOUND/;
   	    $l =~ s/^#\s*//;
   	    if( $l =~ /ask_daemon/ )
	    {
   		$l =~ s/^(.*\").*(\".*)$/$1$clamsock$2/;
            }
   	}
	push @CONF, $l;
   }
   pop @CONF;
   if( !$ismax )
   {
       push @CONF, '$max_servers = '.$VSCount.";\n";
   }
   if( !$ismyhostname )
   {
       push @CONF, '$myhostname = '."'$myhostname';\n";
   }
   if( ! open(OUT,">$aconf.new") )
   {
       return "Error: $!";
   }
   push @CONF, '1;';
   print OUT @CONF;
   close(OUT);
   
   if( ! open(IN,$cconf) )
   {
       return "Error: $!";
   }
   my @CCONF = <IN>;
   close(IN);
   @CONF = ();
   
   foreach my $l ( @CCONF )
   {
   	$l = "LocalSocket $clamsock\n" if $l =~ /LocalSocket/;
   	$l =~ s/(.*)/#$1/ if $l =~ /^TCPSocket/;
   	$l =~ s/(.*)/#$1/ if $l =~ /^TCPAddr/;
	push @CONF, $l;
   }
   if( ! open(OUT,">$cconf.new") )
   {
       return "Error: $!";
   }
   print OUT @CONF;
   close(OUT);
   copy($aconf,"$aconf.bak");
   copy($cconf,"$cconf.bak");
   move("$aconf.new",$aconf);
   move("$cconf.new",$cconf);
   Service->Enable('amavis');
   Service->Enable('freshclam');
   Service->Enable('clamd');
   Service->Start('amavis');
   Service->Start('freshclam');
   Service->Start('clamd');
   return "";
}

sub write_attribute {
    my $config    = shift;
    my $attribute = shift;
    my $value     = shift;
    my $comment   = shift;

    my $unset = 1;

    foreach(@{$config})
    {
        if($_->{"key"} eq $attribute)
	{
            $_->{"value"} = $value;
            $unset = 0; 
            last;
        }
    }
    if($unset)
    {
        push (@{$config}, { "comment" => $comment,
                                "key" => $attribute,
                              "value" => $value }
                  );
    }
    return 1;
}

sub read_attribute {
    my $config    = shift;
    my $attribute = shift;
    my $a	  = undef;
    foreach(@{$config})
    {
        if($_->{"key"} eq $attribute)
	{
            return $_->{"value"} if defined $_->{"value"};
        }
    }
    chomp( $a = `postconf  -h $attribute` ); 
    return $a if( defined $a );
    return undef;
}

# Internal helper Funktion to write the ldap maps
sub write_ldap_maps($$)
{
    my( $MainCf, $ldapMap ) = @_;

    my $alias_maps      = read_attribute($MainCf,'alias_maps');
    if($alias_maps !~ /ldap:\/etc\/postfix\/ldapalias_maps_folder.cf/) 
    {
    	$alias_maps .= ', ldap:/etc/postfix/ldapalias_maps_folder.cf';
    }
    if($alias_maps !~ /ldap:\/etc\/postfix\/ldapalias_maps.cf/) 
    {
    	$alias_maps .= ', ldap:/etc/postfix/ldapalias_maps.cf';
    }
    write_attribute($MainCf,'alias_maps',$alias_maps);
    my $masquerade_domains      = read_attribute($MainCf,'masquerade_domains');
    if($masquerade_domains !~ /ldap:\/etc\/postfix\/ldapmasquerade_domains.cf/) 
    {
    	$masquerade_domains .= ', ldap:/etc/postfix/ldapmasquerade_domains.cf';
    }
    write_attribute($MainCf,'masquerade_domains',$masquerade_domains);
    my $mydestination   = read_attribute($MainCf,'mydestination');
    if($mydestination !~ /ldap:\/etc\/postfix\/ldapmydestination.cf/ )
    {
	$mydestination .= ', ldap:/etc/postfix/ldapmydestination.cf';
    }
    write_attribute($MainCf,'mydestination',$mydestination);
    write_attribute($MainCf,'smtpd_sender_restrictions','ldap:/etc/postfix/ldapaccess.cf');   
    write_attribute($MainCf,'smtp_tls_per_site','ldap:/etc/postfix/ldapsmtp_tls_per_site.cf');
    write_attribute($MainCf,'transport_maps','ldap:/etc/postfix/ldaptransport_maps.cf');
    write_attribute($MainCf,'virtual_alias_maps', 'ldap:/etc/postfix/ldapuser_recipient_maps.cf, ldap:/etc/postfix/ldapvalias_maps_both.cf, ldap:/etc/postfix/ldapvalias_maps_member.cf, ldap:/etc/postfix/ldapvalias_maps_folder.cf, ldap:/etc/postfix/ldapvalias_maps_forward.cf');
    write_attribute($MainCf,'virtual_alias_domains','ldap:/etc/postfix/ldapvirtual_alias_domains.cf');
    check_ldap_configuration('access',$ldapMap);
    check_ldap_configuration('alias_maps',$ldapMap);
    check_ldap_configuration('alias_maps_folder',$ldapMap);
    check_ldap_configuration('masquerade_domains',$ldapMap);
    check_ldap_configuration('mydestination',$ldapMap);
    check_ldap_configuration('smtp_tls_per_site',$ldapMap);
    check_ldap_configuration('transport_maps',$ldapMap);
    check_ldap_configuration('user_recipient_maps',$ldapMap);
    check_ldap_configuration('valias_maps_both',$ldapMap);
    check_ldap_configuration('valias_maps_member',$ldapMap);
    check_ldap_configuration('valias_maps_folder',$ldapMap);
    check_ldap_configuration('valias_maps_forward',$ldapMap);
    check_ldap_configuration('virtual_alias_domains',$ldapMap);

}

# Internal helper Funktion to check if a needed ldap table is correctly defined
# in the main.cf. If not so the neccesary entries will be created.
sub check_ldap_configuration {
    my $config      = shift;
    my $ldapMap    = shift;

    my $changes   = 0;
    my %query_filter     = (
                        'access'                  => '(&(objectClass=suseMailAccess)(suseMailClient=%s))',
                        'alias_maps'              => '(&(objectClass=suseMailTable)(tableKey=%s))',
                        'alias_maps_folder'       => '(&(objectClass=suseMailRecipient)(cn=%s)(suseDeliveryToFolder=yes))',
                        'masquerade_domains'      => '(&(objectClass=suseMailDomain)(zoneName=%s)(suseMailDomainMasquerading=yes))',
                        'mydestination'           => '(&(objectClass=suseMailDomain)(zoneName=%s)(relativeDomainName=@)(!(suseMailDomainType=virtual)))',
                        'mynetworks'              => '(&(objectClass=suseMailMyNetworks)(suseMailClient=%s))',
                        'smtp_tls_per_site'       => '(&(objectClass=suseMailTransport)(suseMailTransportDestination=%s))',
                        'transport_maps'          => '(&(objectClass=suseMailTransport)(suseMailTransportDestination=%s))',
                        'user_recipient_maps'     => '(&(objectClass=suseMailRecipient)(suseMailAcceptAddress=%s))',
                        'valias_maps_both'        => '(&(objectClass=suseMailRecipient)(suseMailAcceptAddress=%s)(suseDeliveryToMember=yes)(suseDeliveryToFolder=yes))',
                        'valias_maps_member'      => '(&(objectClass=suseMailRecipient)(suseMailAcceptAddress=%s)(suseDeliveryToMember=yes)(!(suseDeliveryToFolder=yes)))',
                        'valias_maps_folder'      => '(&(objectClass=suseMailRecipient)(suseMailAcceptAddress=%s)(!(suseDeliveryToMember=yes))(suseDeliveryToFolder=yes))',
                        'valias_maps_forward'     => '(&(objectClass=suseMailRecipient)(suseMailAcceptAddress=%s)(!(suseDeliveryToMember=yes))(!(suseDeliveryToFolder=yes)))',
                        'virtual_alias_domains'   => '(&(objectClass=suseMailDomain)(zoneName=%s)(relativeDomainName=@)(suseMailDomainType=virtual))',
                        'canonical_maps'          => '(&(objectClass=suseCanonicalTable)(tableKey=%s)(valueType=both))',
                        'recipient_canonical_maps'=> '(&(objectClass=suseCanonicalTable)(tableKey=%s)(valueType=recipient))',
                        'sender_canonical_maps'   => '(&(objectClass=suseCanonicalTable)(tableKey=%s)(valueType=sender))'
                       );
    my %result_attribute = (
                        'access'                  => 'suseMailAction',
                        'alias_maps'              => 'tableValue',
                        'alias_maps_folder'       => 'suseMailCommand',
                        'masquerade_domains'      => 'zoneName',
                        'mydestination'           => 'zoneName',
                        'mynetworks'              => 'suseMailClient',
                        'transport_maps'          => 'suseMailTransportNexthop',
                        'valias_maps_both'        => 'suseMailForwardAddress,cn,uid',
                        'valias_maps_member'      => 'suseMailForwardAddress,uid',
                        'valias_maps_folder'      => 'suseMailForwardAddress,cn',
                        'valias_maps_forward'     => 'suseMailForwardAddress',
                        'virtual_alias_domains'   => 'zoneName',
                        'canonical_maps'          => 'tableValue',
                        'recipient_canonical_maps'=> 'tableValue',
                        'smtp_tls_per_site'       => 'suseMailTransportNexthop',
                        'sender_canonical_maps'   => 'tableValue',
                        'user_recipient_maps'     => 'uid,suseMailForwardAddress'
                       );
    my %scope            = (
                        'access'                  => 'one',
                        'alias_maps'              => 'one',
                        'alias_maps_folder'       => 'one',
                        'masquerade_domains'      => 'sub',
                        'mydestination'           => 'sub',
                        'mynetworks'              => 'one',
                        'transport_maps'          => 'one',
                        'smtp_tls_per_site'       => 'one',
                        'valias_maps_both'        => 'one',
                        'valias_maps_member'      => 'one',
                        'valias_maps_folder'      => 'one',
                        'valias_maps_forward'     => 'one',
                        'virtual_alias_domains'   => 'sub',
                        'canonical_maps'          => 'one',
                        'recipient_canonical_maps'=> 'one',
                        'sender_canonical_maps'   => 'one',
			'user_recipient_maps'     => 'one'
                       );
    my %base            = (
                        'access'                  => $ldapMap->{'mail_config_dn'},
                        'alias_maps'              => 'ou=Aliases,'.$ldapMap->{'mail_config_dn'},
                        'alias_maps_folder'       => $ldapMap->{'group_config_dn'},
                        'masquerade_domains'      => $ldapMap->{'dns_config_dn'},
                        'mydestination'           => $ldapMap->{'dns_config_dn'},
                        'mynetworks'              => $ldapMap->{'mail_config_dn'},
                        'smtp_tls_per_site'       => $ldapMap->{'mail_config_dn'},
                        'transport_maps'          => $ldapMap->{'mail_config_dn'},
                        'valias_maps_both'        => $ldapMap->{'group_config_dn'},
                        'valias_maps_member'      => $ldapMap->{'group_config_dn'},
                        'valias_maps_folder'      => $ldapMap->{'group_config_dn'},
                        'valias_maps_forward'     => $ldapMap->{'group_config_dn'},
                        'virtual_alias_domains'   => $ldapMap->{'dns_config_dn'},
                        'canonical_maps'          => 'ou=Canonical,'.$ldapMap->{'mail_config_dn'},
                        'recipient_canonical_maps'=> 'ou=Canonical,'.$ldapMap->{'mail_config_dn'},
                        'sender_canonical_maps'   => 'ou=Canonical,'.$ldapMap->{'mail_config_dn'},
                        'user_recipient_maps'     => $ldapMap->{'user_config_dn'}
                       );
    my %special_result_attribute = (
                        'valias_maps_both'        => 'member',
                        'valias_maps_member'      => 'member'
		       );

    my %terminal_result_attribute = (
                        'valias_maps_both'        => 'uid',
                        'valias_maps_member'      => 'uid'
		       );


if( ! defined $result_attribute{$config} )
{
	print STDERR "BAJAVAN $config";
	return;
}
    #First we read the whool main.cf configuration
    my $LDAPCF    = SCR->Read('.mail.ldaptable',$config);

    #Now we are looking for if all the needed ldap entries are done
    if(!$LDAPCF->{'server_host'} || $LDAPCF->{'server_host'} ne $ldapMap->{'ldap_server'})
    {
	 $changes = 1;
    }
    if(! $LDAPCF->{'server_port'} || $LDAPCF->{'server_port'} ne $ldapMap->{'ldap_port'})
    {
	 $changes = 1;
    }
    if(! $LDAPCF->{'bind'}  || $LDAPCF->{'bind'} ne 'no')
    {
	 $changes = 1;
    }
    if(! $LDAPCF->{'timeout'} || $LDAPCF->{'timeout'} !~ /^\d+$/)
    {
	 $changes = 1;
    }
    if(! $LDAPCF->{'search_base'} || $LDAPCF->{'search_base'} ne $base{$config})
    {
	 $changes = 1;
    }
    if(! $LDAPCF->{'query_filter'} || $LDAPCF->{'query_filter'} ne $query_filter{$config})
    {
	 $changes = 1;
    }
    if(! $LDAPCF->{'result_attribute'} || $LDAPCF->{'result_attribute'} ne $result_attribute{$config})
    {
	 $changes = 1;
    }
    if(! $LDAPCF->{'scope'} || $LDAPCF->{'scope'} ne $scope{$config})
    {
	 $changes = 1;
    }

    # If we had made changes we have to save it
    if( $changes )
    {
        $LDAPCF->{'server_host'}      = $ldapMap->{'ldap_server'};
        $LDAPCF->{'server_port'}      = $ldapMap->{'ldap_port'};
        $LDAPCF->{'bind'}             = 'no';
        $LDAPCF->{'timeout'}          = '20';
        $LDAPCF->{'search_base'}      = $base{$config}; 
        $LDAPCF->{'query_filter'}     = $query_filter{$config}; 
        $LDAPCF->{'result_attribute'} = $result_attribute{$config}; 
	if(defined $special_result_attribute{$config})
	{
		$LDAPCF->{'special_result_attribute'} = $special_result_attribute{$config};
	}
	if(defined $terminal_result_attribute{$config})
	{
		$LDAPCF->{'terminal_result_attribute'} = $terminal_result_attribute{$config};
	}
        $LDAPCF->{'scope'}            = $scope{$config}; 

	SCR->Write('.mail.ldaptable',[$config,$LDAPCF]);
    }

    return $changes;
}

1;

# EOF

ACC SHELL 2018