<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># --
# Kernel/Modules/Installer.pm - provides the DB installer
# Copyright (C) 2001-2014 OTRS AG, http://otrs.com/
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (AGPL). If you
# did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
# --

package Kernel::Modules::Installer;
## nofilter(TidyAll::Plugin::OTRS::Perl::DBObject)
## nofilter(TidyAll::Plugin::OTRS::Perl::Print)

use strict;
use warnings;

use DBI;
use Net::Domain qw(hostfqdn);

use Kernel::System::DB;
use Kernel::System::Email;
use Kernel::System::JSON;
use Kernel::System::MailAccount;
use Kernel::System::ReferenceData;
use Kernel::System::SysConfig;
use Kernel::System::User;
use Kernel::System::XML;

use vars qw(%INC);

sub new {
    my ( $Type, %Param ) = @_;

    # allocate new hash for object
    my $Self = {%Param};
    bless( $Self, $Type );

    # check needed objects
    for (qw(ParamObject LayoutObject LogObject ConfigObject)) {
        if ( !$Self-&gt;{$_} ) {
            $Self-&gt;{LayoutObject}-&gt;FatalError( Message =&gt; "Got no $_!" );
        }
    }

    # create additional object
    $Self-&gt;{JSONObject} = Kernel::System::JSON-&gt;new( %{$Self} );

    return $Self;
}

sub Run {
    my ( $Self, %Param ) = @_;

    # check env directories
    $Self-&gt;{Path} = $Self-&gt;{ConfigObject}-&gt;Get('Home');
    if ( !-d $Self-&gt;{Path} ) {
        $Self-&gt;{LayoutObject}-&gt;FatalError(
            Message =&gt; "Directory '$Self-&gt;{Path}' doesn't exist!",
            Comment =&gt; 'Configure Home in Kernel/Config.pm first!',
        );
    }
    if ( !-f "$Self-&gt;{Path}/Kernel/Config.pm" ) {
        $Self-&gt;{LayoutObject}-&gt;FatalError(
            Message =&gt; "File '$Self-&gt;{Path}/Kernel/Config.pm' not found!",
            Comment =&gt; 'Contact your Admin!',
        );
    }

    # check/get sql schema dir
    my $DirOfSQLFiles = $Self-&gt;{Path} . '/scripts/database';
    if ( !-d $DirOfSQLFiles ) {
        $Self-&gt;{LayoutObject}-&gt;FatalError(
            Message =&gt; "Directory '$DirOfSQLFiles' not found!",
            Comment =&gt; 'Contact your Admin!',
        );
    }

    # read installer.json if it exists
    # it contains options set by Windows Installer
    if ( -f "$Self-&gt;{Path}/var/tmp/installer.json" ) {
        my $JSONString = $Self-&gt;{MainObject}-&gt;FileRead(
            Location =&gt; "$Self-&gt;{Path}/var/tmp/installer.json",
        );
        $Self-&gt;{Options} = $Self-&gt;{JSONObject}-&gt;Decode(
            Data =&gt; $$JSONString,
        );
    }

    # check if License option needs to be skipped
    if ( $Self-&gt;{Subaction} eq 'License' &amp;&amp; $Self-&gt;{Options}-&gt;{SkipLicense} ) {
        $Self-&gt;{Subaction} = 'Start';
    }

    # check if Database option needs to be skipped
    if ( $Self-&gt;{Subaction} eq 'Start' &amp;&amp; $Self-&gt;{Options}-&gt;{DBType} ) {
        $Self-&gt;{Subaction} = 'DBCreate';
    }

    $Self-&gt;{Subaction} = 'Intro' if !$Self-&gt;{Subaction};

    # build steps
    my @Steps = qw(License Database General Finish);
    my $StepCounter;

    # no license step needed if defined in .json file
    shift @Steps if $Self-&gt;{Options}-&gt;{SkipLicense};

    # build header - but only if we're not in AJAX mode
    if ( $Self-&gt;{Subaction} ne 'CheckRequirements' ) {
        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'Steps',
            Data =&gt; { Steps =&gt; scalar @Steps, },
        );

        # mapping of subactions to steps
        my %Steps = (
            Intro         =&gt; 'Intro',
            License       =&gt; 'License',
            Start         =&gt; 'Database',
            DB            =&gt; 'Database',
            DBCreate      =&gt; 'Database',
            ConfigureMail =&gt; 'General',
            System        =&gt; 'General',
            Finish        =&gt; 'Finish',
        );

        # on the intro screen no steps should be highlighted
        my $Highlight = ( $Self-&gt;{Subaction} eq 'Intro' ) ? '' : 'Highlighted NoLink';

        my $Counter;

        for my $Step (@Steps) {
            $Counter++;

            # is the current step active?
            my $Active = ( $Steps{ $Self-&gt;{Subaction} } eq $Step ) ? 'Active' : '';
            $Self-&gt;{LayoutObject}-&gt;Block(
                Name =&gt; 'Step' . $Step,
                Data =&gt; {
                    Step      =&gt; $Counter,
                    Highlight =&gt; $Highlight,
                    Active    =&gt; $Active,
                },
            );

            # if this is the actual step
            if ( $Steps{ $Self-&gt;{Subaction} } eq $Step ) {

                # no more highlights from now on
                $Highlight = '',

                    # step calculation: 2/5 etc.
                    $StepCounter = $Counter . "/" . scalar @Steps;
            }
        }
    }

    # print intro form
    my $Title = $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('Install OTRS');
    if ( $Self-&gt;{Subaction} eq 'Intro' ) {
        my $Output =
            $Self-&gt;{LayoutObject}-&gt;Header(
            Title =&gt; "$Title - "
                . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('Intro')
            );
        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'Intro',
            Data =&gt; {}
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
            TemplateFile =&gt; 'Installer',
            Data         =&gt; {},
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
        return $Output;
    }

    # print license from
    elsif ( $Self-&gt;{Subaction} eq 'License' ) {
        my $Output =
            $Self-&gt;{LayoutObject}-&gt;Header(
            Title =&gt; "$Title - "
                . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('License')
            );
        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'License',
            Data =&gt; {
                Item =&gt; 'License',
                Step =&gt; $StepCounter,
            },
        );
        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'LicenseText',
            Data =&gt; {},
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
            TemplateFile =&gt; 'Installer',
            Data         =&gt; {},
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
        return $Output;
    }

    # database selection screen
    elsif ( $Self-&gt;{Subaction} eq 'Start' ) {
        if ( !-w "$Self-&gt;{Path}/Kernel/Config.pm" ) {
            my $Output =
                $Self-&gt;{LayoutObject}-&gt;Header(
                Title =&gt; "$Title - "
                    . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('Error')
                );
            $Output .= $Self-&gt;{LayoutObject}-&gt;Warning(
                Message =&gt; "Kernel/Config.pm isn't writable!",
                Comment =&gt; 'If you want to use the installer, set the '
                    . 'Kernel/Config.pm writable for the webserver user! '
            );
            $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
            return $Output;
        }

        my %Databases = (
            mysql      =&gt; "MySQL",
            postgresql =&gt; "PostgreSQL",
            mssql      =&gt; "SQL Server (Microsoft)",
            oracle     =&gt; "Oracle",
        );

        # OTRS can only run on SQL Server if OTRS is on Windows as well
        if ( $^O ne 'MSWin32' ) {
            delete $Databases{mssql};
        }

        # build the select field for the InstallerDBStart.dtl
        $Param{SelectDBType} = $Self-&gt;{LayoutObject}-&gt;BuildSelection(
            Data       =&gt; \%Databases,
            Name       =&gt; 'DBType',
            Size       =&gt; scalar keys %Databases,
            SelectedID =&gt; 'mysql',
        );

        my $Output =
            $Self-&gt;{LayoutObject}-&gt;Header(
            Title =&gt; "$Title - "
                . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('Database Selection')
            );
        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'DatabaseStart',
            Data =&gt; {
                Item         =&gt; 'Database Selection',
                Step         =&gt; $StepCounter,
                SelectDBType =&gt; $Param{SelectDBType},
                }
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
            TemplateFile =&gt; 'Installer',
            Data         =&gt; {},
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
        return $Output;
    }

    # check different requirements (AJAX)
    elsif ( $Self-&gt;{Subaction} eq 'CheckRequirements' ) {
        my $CheckMode = $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'CheckMode' );
        my %Result;

        # check DB requirements
        if ( $CheckMode eq 'DB' ) {
            my %DBCredentials;
            for my $Param (
                qw(DBUser DBPassword DBHost DBType DBPort DBSID DBName InstallType OTRSDBUser OTRSDBPassword)
                )
            {
                $DBCredentials{$Param} = $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; $Param ) || '';
            }

            %Result = $Self-&gt;CheckDBRequirements(
                %DBCredentials,
            );
        }

        # check mail configuration
        elsif ( $CheckMode eq 'Mail' ) {
            %Result = $Self-&gt;CheckMailConfiguration();
        }

        # no adequate check method found
        else {
            %Result = (
                Successful =&gt; 0,
                Message    =&gt; 'Unknown Check!',
                Comment    =&gt; "The check '$CheckMode' doesn't exist!"
            );
        }

        # return JSON-String because of AJAX-Mode
        my $OutputJSON = $Self-&gt;{LayoutObject}-&gt;JSONEncode( Data =&gt; \%Result );

        return $Self-&gt;{LayoutObject}-&gt;Attachment(
            ContentType =&gt; 'application/json; charset='
                . $Self-&gt;{LayoutObject}-&gt;{Charset},
            Content =&gt; $OutputJSON,
            Type    =&gt; 'inline',
            NoCache =&gt; 1,
        );
    }

    elsif ( $Self-&gt;{Subaction} eq 'DB' ) {

        my $DBType        = $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'DBType' );
        my $DBInstallType = $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'DBInstallType' );

        # use MainObject to generate a password
        my $GeneratedPassword = $Self-&gt;{MainObject}-&gt;GenerateRandomString();

        if ( $DBType eq 'mysql' ) {
            my $PasswordExplanation
                = $DBInstallType eq 'CreateDB'
                ? $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get(
                'If you have set a root password for your database, it must be entered here. If not, leave this field empty.'
                )
                : $Self-&gt;{LayoutObject}-&gt;{LanguageObject}
                -&gt;Get('Enter the password for the database user.');
            my $Output =
                $Self-&gt;{LayoutObject}-&gt;Header(
                Title =&gt; "$Title - "
                    . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('Database') . ' MySQL'
                );
            $Self-&gt;{LayoutObject}-&gt;Block(
                Name =&gt; 'DatabaseMySQL',
                Data =&gt; {
                    Item                =&gt; 'Configure MySQL',
                    Step                =&gt; $StepCounter,
                    InstallType         =&gt; $DBInstallType,
                    DefaultDBUser       =&gt; $DBInstallType eq 'CreateDB' ? 'root' : 'otrs',
                    PasswordExplanation =&gt; $PasswordExplanation,
                },
            );
            if ( $DBInstallType eq 'CreateDB' ) {
                $Self-&gt;{LayoutObject}-&gt;Block(
                    Name =&gt; 'DatabaseMySQLCreate',
                    Data =&gt; {
                        Password =&gt; $GeneratedPassword,
                    },
                );
            }
            else {
                $Self-&gt;{LayoutObject}-&gt;Block(
                    Name =&gt; 'DatabaseMySQLUseExisting',
                );
            }

            $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
                TemplateFile =&gt; 'Installer',
                Data         =&gt; {
                    Item =&gt; 'Configure MySQL',
                    Step =&gt; $StepCounter,
                    }
            );
            $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
            return $Output;
        }
        elsif ( $DBType eq 'mssql' ) {
            my $PasswordExplanation
                = $DBInstallType eq 'CreateDB'
                ? $Self-&gt;{LayoutObject}-&gt;{LanguageObject}
                -&gt;Get('Enter the password for the administrative database user.')
                : $Self-&gt;{LayoutObject}-&gt;{LanguageObject}
                -&gt;Get('Enter the password for the database user.');
            my $Output =
                $Self-&gt;{LayoutObject}-&gt;Header(
                Title =&gt; "$Title - "
                    . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('Database')
                    . ' Microsoft SQL Server'
                );
            $Self-&gt;{LayoutObject}-&gt;Block(
                Name =&gt; 'DatabaseMSSQL',
                Data =&gt; {
                    Item          =&gt; 'Database',
                    Step          =&gt; $StepCounter,
                    InstallType   =&gt; $DBInstallType,
                    DefaultDBUser =&gt; $DBInstallType eq 'CreateDB' ? 'sa' : 'otrs',
                },
            );

            if ( $DBInstallType eq 'CreateDB' ) {
                $Self-&gt;{LayoutObject}-&gt;Block(
                    Name =&gt; 'DatabaseMSSQLCreate',
                    Data =&gt; {
                        Password =&gt; $GeneratedPassword,
                    },
                );
            }
            else {
                $Self-&gt;{LayoutObject}-&gt;Block(
                    Name =&gt; 'DatabaseMSSQLUseExisting',
                );
            }

            $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
                TemplateFile =&gt; 'Installer',
                Data         =&gt; {
                    Item        =&gt; 'Configure Microsoft SQL Server',
                    Step        =&gt; $StepCounter,
                    InstallType =&gt; $DBInstallType,
                    }
            );
            $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
            return $Output;
        }
        elsif ( $DBType eq 'postgresql' ) {
            my $PasswordExplanation
                = $DBInstallType eq 'CreateDB'
                ? $Self-&gt;{LayoutObject}-&gt;{LanguageObject}
                -&gt;Get('Enter the password for the administrative database user.')
                : $Self-&gt;{LayoutObject}-&gt;{LanguageObject}
                -&gt;Get('Enter the password for the database user.');
            my $Output =
                $Self-&gt;{LayoutObject}-&gt;Header(
                Title =&gt; "$Title - "
                    . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('Database') . ' PostgreSQL'
                );
            $Self-&gt;{LayoutObject}-&gt;Block(
                Name =&gt; 'DatabasePostgreSQL',
                Data =&gt; {
                    Item          =&gt; 'Database',
                    Step          =&gt; $StepCounter,
                    InstallType   =&gt; $DBInstallType,
                    DefaultDBUser =&gt; $DBInstallType eq 'CreateDB' ? 'postgres' : 'otrs',
                },
            );
            if ( $DBInstallType eq 'CreateDB' ) {
                $Self-&gt;{LayoutObject}-&gt;Block(
                    Name =&gt; 'DatabasePostgreSQLCreate',
                    Data =&gt; {
                        Password =&gt; $GeneratedPassword,
                    },
                );
            }
            else {
                $Self-&gt;{LayoutObject}-&gt;Block(
                    Name =&gt; 'DatabasePostgreSQLUseExisting',
                );
            }

            $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
                TemplateFile =&gt; 'Installer',
                Data         =&gt; {
                    Item =&gt; 'Configure PostgreSQL',
                    Step =&gt; $StepCounter,
                    }
            );
            $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
            return $Output;
        }

        elsif ( $DBType eq 'oracle' ) {
            my $Output =
                $Self-&gt;{LayoutObject}-&gt;Header(
                Title =&gt; "$Title - "
                    . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('Database') . ' Oracle'
                );
            $Self-&gt;{LayoutObject}-&gt;Block(
                Name =&gt; 'DatabaseOracle',
                Data =&gt; {
                    Item =&gt; 'Database',
                    Step =&gt; $StepCounter,
                },
            );

            $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
                TemplateFile =&gt; 'Installer',
                Data         =&gt; {
                    Item =&gt; 'Configure Oracle',
                    Step =&gt; $StepCounter,
                    }
            );
            $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
            return $Output;
        }

        else {
            $Self-&gt;{LayoutObject}-&gt;FatalError(
                Message =&gt; "Unknown database type '$DBType'.",
                Comment =&gt; 'Please go back',
            );
        }
    }

    # do database settings
    elsif ( $Self-&gt;{Subaction} eq 'DBCreate' ) {

        my %DBCredentials;
        for my $Param (
            qw(DBUser DBPassword DBHost DBType DBName DBSID DBPort InstallType OTRSDBUser OTRSDBPassword)
            )
        {
            $DBCredentials{$Param} = $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; $Param ) || '';
        }
        %DBCredentials = %{ $Self-&gt;{Options} } if $Self-&gt;{Options}-&gt;{DBType};

        # get and check params and connect to DB
        my %Result = $Self-&gt;ConnectToDB(%DBCredentials);

        my %DB;
        my $DBH;
        if ( ref $Result{DB} ne 'HASH' || !$Result{DBH} ) {
            $Self-&gt;{LayoutObject}-&gt;FatalError(
                Message =&gt; $Result{Message},
                Comment =&gt; $Result{Comment},
            );
        }
        else {
            %DB  = %{ $Result{DB} };
            $DBH = $Result{DBH};
        }

        my $Output = $Self-&gt;{LayoutObject}-&gt;Header(
            Title =&gt; $Title . '-'
                . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get(
                'Create Database'
                )
        );

        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'DatabaseResult',
            Data =&gt; {
                Item =&gt; 'Create Database',
                Step =&gt; $StepCounter,
            },
        );

        my @Statements;

        # create database, add user
        if ( $DB{DBType} eq 'mysql' ) {

            if ( $DB{InstallType} eq 'CreateDB' ) {

                # determine current host for MySQL account
                my $ConnectionID;
                my $StatementHandle = $DBH-&gt;prepare("select connection_id()");
                $StatementHandle-&gt;execute();
                while ( my @Row = $StatementHandle-&gt;fetchrow_array() ) {
                    $ConnectionID = $Row[0];
                }

                $StatementHandle = $DBH-&gt;prepare("show processlist");
                $StatementHandle-&gt;execute();
                PROCESSLIST:
                while ( my @Row = $StatementHandle-&gt;fetchrow_array() ) {
                    if ( $Row[0] eq $ConnectionID ) {
                        $DB{Host} = $Row[2];
                        last PROCESSLIST;
                    }
                }

                # strip off port, i.e. 'localhost:14962' should become 'localhost'
                $DB{Host} =~ s{:\d*\z}{}xms;

                @Statements = (
                    "CREATE DATABASE `$DB{DBName}` charset utf8",
                    "GRANT ALL PRIVILEGES ON `$DB{DBName}`.* TO `$DB{OTRSDBUser}`\@`$DB{Host}` IDENTIFIED BY '$DB{OTRSDBPassword}' WITH GRANT OPTION;",
                    "FLUSH PRIVILEGES",
                );
            }

            # set DSN for Config.pm
            $DB{ConfigDSN} = 'DBI:mysql:database=$Self-&gt;{Database};host=$Self-&gt;{DatabaseHost}';
            $DB{DSN}       = "DBI:mysql:database=$DB{DBName};host=$DB{DBHost}";
        }
        elsif ( $DB{DBType} eq 'mssql' ) {

            if ( $DB{InstallType} eq 'CreateDB' ) {
                @Statements = (
                    "CREATE DATABASE [$DB{DBName}]",
                    "CREATE LOGIN [$DB{OTRSDBUser}] WITH PASSWORD = '$DB{OTRSDBPassword}'",
                    "USE [$DB{DBName}]",
                    "CREATE USER  [$DB{OTRSDBUser}] FOR LOGIN [$DB{OTRSDBUser}]",
                    "exec sp_addrolemember 'db_owner', '$DB{OTRSDBUser}'",
                    "exec sp_defaultdb '$DB{OTRSDBUser}', '$DB{DBName}'",
                );
            }

            # set DSN for Config.pm
            $DB{ConfigDSN}
                = 'DBI:ODBC:driver={SQL Server};Database=$Self-&gt;{Database};Server=$Self-&gt;{DatabaseHost}';
            $DB{DSN} = "DBI:ODBC:driver={SQL Server};Database=$DB{DBName};Server=$DB{DBHost}";
        }
        elsif ( $DB{DBType} eq 'postgresql' ) {

            if ( $DB{InstallType} eq 'CreateDB' ) {
                @Statements = (
                    "CREATE ROLE \"$DB{OTRSDBUser}\" WITH LOGIN PASSWORD '$DB{OTRSDBPassword}'",
                    "CREATE DATABASE \"$DB{DBName}\" OWNER=\"$DB{OTRSDBUser}\" ENCODING 'utf-8'",
                );
            }

            # set DSN for Config.pm
            $DB{ConfigDSN}
                = 'DBI:Pg:dbname=$Self-&gt;{Database};host=$Self-&gt;{DatabaseHost}';
            $DB{DSN} = "DBI:Pg:dbname=$DB{DBName};host=$DB{DBHost}";
        }
        elsif ( $DB{DBType} eq 'oracle' ) {

            # set DSN for Config.pm
            $DB{ConfigDSN}
                = 'DBI:Oracle:host=$Self-&gt;{DatabaseHost};' . "sid=$DB{DBSID};port=$DB{DBPort}";
            $DB{DSN} = "DBI:Oracle:host=$DB{DBHost};sid=$DB{DBSID};port=$DB{DBPort}";
            $Self-&gt;{ConfigObject}-&gt;Set(
                Key   =&gt; 'Database::Connect',
                Value =&gt; "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'",
            );
        }

        # execute database statements
        for my $Statement (@Statements) {
            my @Description = split( ' ', $Statement );

            # prevent unitilialized variables
            for my $Index ( 0 .. 2 ) {
                $Description[$Index] //= '';
            }

            $Self-&gt;{LayoutObject}-&gt;Block(
                Name =&gt; 'DatabaseResultItem',
                Data =&gt; { Item =&gt; "$Description[0] $Description[1] $Description[2]" },
            );
            if ( !$DBH-&gt;do($Statement) ) {
                $Self-&gt;{LayoutObject}-&gt;Block(
                    Name =&gt; 'DatabaseResultItemFalse',
                    Data =&gt; {},
                );
                $Self-&gt;{LayoutObject}-&gt;Block(
                    Name =&gt; 'DatabaseResultItemMessage',
                    Data =&gt; { Message =&gt; $DBI::errstr, },
                );
                $Self-&gt;{LayoutObject}-&gt;Block(
                    Name =&gt; 'DatabaseResultBack',
                    Data =&gt; {},
                );
                $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
                    TemplateFile =&gt; 'Installer',
                    Data         =&gt; {},
                );
                $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
                return $Output;
            }
            else {
                $Self-&gt;{LayoutObject}-&gt;Block(
                    Name =&gt; 'DatabaseResultItemDone',
                    Data =&gt; {},
                );
            }
        }

        # ReConfigure Config.pm
        my $ReConfigure = $Self-&gt;ReConfigure(
            DatabaseDSN  =&gt; $DB{ConfigDSN},
            DatabaseHost =&gt; $DB{DBHost},
            Database     =&gt; $DB{DBName},
            DatabaseUser =&gt; $DB{OTRSDBUser},
            DatabasePw   =&gt; $DB{OTRSDBPassword},
        );

        if ($ReConfigure) {
            my $Output =
                $Self-&gt;{LayoutObject}-&gt;Header(
                Title =&gt; 'Install OTRS - Error'
                );
            $Output .= $Self-&gt;{LayoutObject}-&gt;Warning(
                Message =&gt; "Kernel/Config.pm isn't writable!",
                Comment =&gt; 'If you want to use the installer, set the '
                    . 'Kernel/Config.pm writable for the webserver user!',
            );
            $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
            return $Output;
        }

        # we need a database object to be able to parse the XML
        # connect to database using given credentials
        $Self-&gt;{DBObject} = Kernel::System::DB-&gt;new(
            %{$Self},
            DatabaseDSN  =&gt; $DB{DSN},
            DatabaseUser =&gt; $DB{OTRSDBUser},
            DatabasePw   =&gt; $DB{OTRSDBPassword},
            Type         =&gt; $DB{DBType},
        );
        $Self-&gt;{XMLObject} = Kernel::System::XML-&gt;new( %{$Self} );

        # create database tables and insert initial values
        my @SQLPost;
        for my $SchemaFile (qw(otrs-schema otrs-initial_insert)) {
            if ( !-f "$DirOfSQLFiles/$SchemaFile.xml" ) {
                $Self-&gt;{LayoutObject}-&gt;FatalError(
                    Message =&gt; "File '$DirOfSQLFiles/$SchemaFile.xml' not found!",
                    Comment =&gt; 'Contact your Admin!',
                );
            }

            $Self-&gt;{LayoutObject}-&gt;Block(
                Name =&gt; 'DatabaseResultItem',
                Data =&gt; { Item =&gt; "Processing $SchemaFile" },
            );

            my $XML = $Self-&gt;{MainObject}-&gt;FileRead(
                Directory =&gt; $DirOfSQLFiles,
                Filename  =&gt; $SchemaFile . '.xml',
            );
            my @XMLArray = $Self-&gt;{XMLObject}-&gt;XMLParse(
                String =&gt; $XML,
            );

            my @SQL = $Self-&gt;{DBObject}-&gt;SQLProcessor(
                Database =&gt; \@XMLArray,
            );

            # if we parsed the schema, catch post instructions
            @SQLPost = $Self-&gt;{DBObject}-&gt;SQLProcessorPost() if $SchemaFile eq 'otrs-schema';

            for my $SQL (@SQL) {
                $Self-&gt;{DBObject}-&gt;Do( SQL =&gt; $SQL );
            }

            $Self-&gt;{LayoutObject}-&gt;Block(
                Name =&gt; 'DatabaseResultItemDone',
            );

        }

        # execute post SQL statements (indexes, constraints)

        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'DatabaseResultItem',
            Data =&gt; { Item =&gt; "Processing post statements" },
        );

        for my $SQL (@SQLPost) {
            $Self-&gt;{DBObject}-&gt;Do( SQL =&gt; $SQL );
        }

        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'DatabaseResultItemDone',
        );

        # if running under PerlEx, reload the application (and thus the configuration)
        if (
            exists $ENV{'GATEWAY_INTERFACE'}
            &amp;&amp; $ENV{'GATEWAY_INTERFACE'} eq "CGI-PerlEx"
            )
        {
            PerlEx::ReloadAll();
        }

        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'DatabaseResultSuccess',
        );
        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'DatabaseResultNext',
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
            TemplateFile =&gt; 'Installer',
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
        return $Output;
    }

    # show system settings page, pre-install packages
    elsif ( $Self-&gt;{Subaction} eq 'System' ) {

        # create new DB object in order to setup sysconfig object

        $Self-&gt;{DBObject} = Kernel::System::DB-&gt;new( %{$Self} );
        if ( !$Self-&gt;{DBObject} ) {
            $Self-&gt;{LayoutObject}-&gt;FatalError();
        }

        # create sys config object
        my $SysConfigObject = Kernel::System::SysConfig-&gt;new( %{$Self} );

        # take care that default config file is existing
        if ( !$SysConfigObject-&gt;WriteDefault() ) {
            return $Self-&gt;{LayoutObject}-&gt;FatalError();
        }

        # install default files
        if ( $Self-&gt;{MainObject}-&gt;Require('Kernel::System::Package') ) {
            my $PackageObject = Kernel::System::Package-&gt;new( %{$Self} );
            if ($PackageObject) {
                $PackageObject-&gt;PackageInstallDefaultFiles();
            }
        }

        my @SystemIDs = map { sprintf "%02d", $_ } ( 0 .. 99 );

        $Param{SystemIDString} = $Self-&gt;{LayoutObject}-&gt;BuildSelection(
            Data       =&gt; \@SystemIDs,
            Name       =&gt; 'SystemID',
            SelectedID =&gt; $SystemIDs[ int( rand(100) ) ],    # random system ID
        );
        $Param{LanguageString} = $Self-&gt;{LayoutObject}-&gt;BuildSelection(
            Data       =&gt; $Self-&gt;{ConfigObject}-&gt;Get('DefaultUsedLanguages'),
            Name       =&gt; 'DefaultLanguage',
            HTMLQuote  =&gt; 0,
            SelectedID =&gt; $Self-&gt;{LayoutObject}-&gt;{UserLanguage},
        );

        # build the selection field for the MX check
        $Param{SelectCheckMXRecord} = $Self-&gt;{LayoutObject}-&gt;BuildSelection(
            Data =&gt; {
                1 =&gt; 'Yes',
                0 =&gt; 'No',
            },
            Name       =&gt; 'CheckMXRecord',
            SelectedID =&gt; '1',
        );

        # read FQDN using Net::Domain and prepopulate the field
        $Param{FQDN} = hostfqdn();

        my $Output =
            $Self-&gt;{LayoutObject}-&gt;Header(
            Title =&gt; "$Title - "
                . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('System Settings')
            );

        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'System',
            Data =&gt; {
                Item =&gt; 'System Settings',
                Step =&gt; $StepCounter,
                %Param,
            },
        );

        if ( !$Self-&gt;{Options}-&gt;{SkipLog} ) {
            $Param{LogModuleString} = $Self-&gt;{LayoutObject}-&gt;BuildSelection(
                Data =&gt; {
                    'Kernel::System::Log::SysLog' =&gt; 'Syslog',
                    'Kernel::System::Log::File'   =&gt; 'File',
                },
                Name       =&gt; 'LogModule',
                HTMLQuote  =&gt; 0,
                SelectedID =&gt; $Self-&gt;{ConfigObject}-&gt;Get('LogModule'),
            );
            $Self-&gt;{LayoutObject}-&gt;Block(
                Name =&gt; 'LogModule',
                Data =&gt; \%Param,
            );
        }

        $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
            TemplateFile =&gt; 'Installer',
            Data         =&gt; {},
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
        return $Output;
    }

    # do system settings action
    elsif ( $Self-&gt;{Subaction} eq 'ConfigureMail' ) {

        # save config values in DB
        $Self-&gt;{DBObject} = Kernel::System::DB-&gt;new( %{$Self} );
        if ( !$Self-&gt;{DBObject} ) {
            $Self-&gt;{LayoutObject}-&gt;FatalError();
        }

        # create sys config object
        my $SysConfigObject = Kernel::System::SysConfig-&gt;new( %{$Self} );

        # take care that default config file is existing
        if ( !$SysConfigObject-&gt;WriteDefault() ) {
            return $Self-&gt;{LayoutObject}-&gt;FatalError();
        }

        for my $Key (
            qw(SystemID FQDN AdminEmail Organization LogModule LogModule::LogFile
            DefaultLanguage CheckMXRecord)
            )
        {
            my $Value = $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; $Key );

            # update config item via sys config object
            $SysConfigObject-&gt;ConfigItemUpdate(
                Valid =&gt; 1,
                Key   =&gt; $Key,
                Value =&gt; $Value,
            );
        }

        # get mail account object and check available backends
        my $MailAccount  = Kernel::System::MailAccount-&gt;new( %{$Self} );
        my %MailBackends = $MailAccount-&gt;MailAccountBackendList();

        my $OutboundMailTypeSelection = $Self-&gt;{LayoutObject}-&gt;BuildSelection(
            Data =&gt; {
                sendmail =&gt; 'Sendmail',
                smtp     =&gt; 'SMTP',
                smtps    =&gt; 'SMTPS',
                smtptls  =&gt; 'SMTPTLS',
            },
            Name =&gt; 'OutboundMailType',
        );
        my $OutboundMailDefaultPorts = $Self-&gt;{LayoutObject}-&gt;BuildSelection(
            Class =&gt; 'Hidden',
            Data  =&gt; {
                sendmail =&gt; '25',
                smtp     =&gt; '25',
                smtps    =&gt; '465',
                smtptls  =&gt; '587',
            },
            Name =&gt; 'OutboundMailDefaultPorts',
        );

        my $InboundMailTypeSelection = $Self-&gt;{LayoutObject}-&gt;BuildSelection(
            Data =&gt; \%MailBackends,
            Name =&gt; 'InboundMailType',
        );

        my $Output =
            $Self-&gt;{LayoutObject}-&gt;Header(
            Title =&gt; "$Title - "
                . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('Configure Mail')
            );
        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'ConfigureMail',
            Data =&gt; {
                Item             =&gt; 'Mail Configuration',
                Step             =&gt; $StepCounter,
                InboundMailType  =&gt; $InboundMailTypeSelection,
                OutboundMailType =&gt; $OutboundMailTypeSelection,
                OutboundPorts    =&gt; $OutboundMailDefaultPorts,
            },
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
            TemplateFile =&gt; 'Installer',
            Data         =&gt; {},
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
        return $Output;
    }

    elsif ( $Self-&gt;{Subaction} eq 'Finish' ) {

        $Self-&gt;{DBObject} = Kernel::System::DB-&gt;new( %{$Self} );

        # create sysconfig object
        my $SysConfigObject = Kernel::System::SysConfig-&gt;new( %{$Self} );

        # make sure the default config file exists
        if ( !$SysConfigObject-&gt;WriteDefault() ) {
            return $Self-&gt;{LayoutObject}-&gt;FatalError();
        }

        # update config item via sysconfig object
        my $Result = $SysConfigObject-&gt;ConfigItemUpdate(
            Valid =&gt; 1,
            Key   =&gt; 'SecureMode',
            Value =&gt; 1,
        );
        if ( !$Result ) {
            $Self-&gt;{LayoutObject}-&gt;FatalError(
                Message =&gt; "Can't write Config file!"
            );
        }

        # 'rebuild' the configuration to prevent duplicate rows in ZZZAuto.pm
        $SysConfigObject-&gt;WriteDefault();

        # if running under PerlEx, reload the application (and thus the configuration)
        if (
            exists $ENV{'GATEWAY_INTERFACE'}
            &amp;&amp; $ENV{'GATEWAY_INTERFACE'} eq "CGI-PerlEx"
            )
        {
            PerlEx::ReloadAll();
        }

        # set a generated password for the 'root@localhost' account
        $Self-&gt;{UserObject} = Kernel::System::User-&gt;new( %{$Self} );
        my $Password = $Self-&gt;{UserObject}-&gt;GenerateRandomPassword( Size =&gt; 16 );
        $Self-&gt;{UserObject}-&gt;SetPassword(
            UserLogin =&gt; 'root@localhost',
            PW        =&gt; $Password,
        );

        # remove installer file with preconfigured options
        if ( -f "$Self-&gt;{Path}/var/tmp/installer.json" ) {
            unlink "$Self-&gt;{Path}/var/tmp/installer.json";
        }

        # check web server - is a restart needed?
        my $Webserver;

        # only if we have mod_perl we have to restart
        if ( exists $ENV{MOD_PERL} ) {
            eval 'require mod_perl';    ## no critic
            if ( defined $mod_perl::VERSION ) {    ## no critic
                $Webserver = 'Apache2 + mod_perl';
                if ( -f '/etc/SuSE-release' ) {
                    $Webserver = 'rcapache2 restart';
                }
                elsif ( -f '/etc/redhat-release' ) {
                    $Webserver = 'service httpd restart';
                }
            }
        }

        # check if Apache::Reload is loaded
        for my $Module ( sort keys %INC ) {
            $Module =~ s/\//::/g;
            $Module =~ s/\.pm$//g;

            if ( $Module eq 'Apache2::Reload' ) {
                $Webserver = '';
            }
        }

        my $OTRSHandle = $ENV{SCRIPT_NAME};
        $OTRSHandle =~ s/\/(.*)\/installer\.pl/$1/;
        my $Output =
            $Self-&gt;{LayoutObject}-&gt;Header(
            Title =&gt; "$Title - "
                . $Self-&gt;{LayoutObject}-&gt;{LanguageObject}-&gt;Get('Finished')
            );
        $Self-&gt;{LayoutObject}-&gt;Block(
            Name =&gt; 'Finish',
            Data =&gt; {
                Item       =&gt; 'Finished',
                Step       =&gt; $StepCounter,
                Host       =&gt; $ENV{HTTP_HOST} || $Self-&gt;{ConfigObject}-&gt;Get('FQDN'),
                OTRSHandle =&gt; $OTRSHandle,
                Webserver  =&gt; $Webserver,
                Password   =&gt; $Password,
            },
        );
        if ($Webserver) {
            $Self-&gt;{LayoutObject}-&gt;Block(
                Name =&gt; 'Restart',
                Data =&gt; {
                    Webserver =&gt; $Webserver,
                },
            );
        }
        $Output .= $Self-&gt;{LayoutObject}-&gt;Output(
            TemplateFile =&gt; 'Installer',
            Data         =&gt; {},
        );
        $Output .= $Self-&gt;{LayoutObject}-&gt;Footer();
        return $Output;
    }

    # else error!
    $Self-&gt;{LayoutObject}-&gt;FatalError(
        Message =&gt; "Unknown Subaction $Self-&gt;{Subaction}!",
        Comment =&gt; 'Please contact your administrator',
    );
}

sub ReConfigure {
    my ( $Self, %Param ) = @_;

    # perl quote and set via ConfigObject
    for my $Key ( sort keys %Param ) {
        $Self-&gt;{ConfigObject}-&gt;Set(
            Key   =&gt; $Key,
            Value =&gt; $Param{$Key},
        );
        if ( $Param{$Key} ) {
            $Param{$Key} =~ s/'/\\'/g;
        }
    }

    # read config file
    my $ConfigFile = "$Self-&gt;{Path}/Kernel/Config.pm";
    ## no critic
    open( my $In, '&lt;', $ConfigFile )
        || return "Can't open $ConfigFile: $!";
    ## use critic
    my $Config = '';
    while (&lt;$In&gt;) {

        # skip empty lines or comments
        if ( !$_ || $_ =~ /^\s*#/ || $_ =~ /^\s*$/ ) {
            $Config .= $_;
        }
        else {
            my $NewConfig = $_;

            # replace config with %Param
            for my $Key ( sort keys %Param ) {

             # database passwords can contain characters like '@' or '$' and should be single-quoted
             # same goes for database hosts which can be like 'myserver\instance name' for MS SQL
                if ( $Key eq 'DatabasePw' || $Key eq 'DatabaseHost' ) {
                    $NewConfig =~
                        s/(\$Self-&gt;{("|'|)$Key("|'|)} =.+?('|"));/\$Self-&gt;{'$Key'} = '$Param{$Key}';/g;
                }
                else {
                    $NewConfig =~
                        s/(\$Self-&gt;{("|'|)$Key("|'|)} =.+?('|"));/\$Self-&gt;{'$Key'} = "$Param{$Key}";/g;
                }
            }
            $Config .= $NewConfig;
        }
    }
    close $In;

    # write new config file
    ## no critic
    open( my $Out, '&gt;:utf8', $ConfigFile )
        || return "Can't open $ConfigFile: $!";
    print $Out $Config;
    ## use critic
    close $Out;

    return;
}

sub ConnectToDB {
    my ( $Self, %Param ) = @_;

    # check params
    my @NeededKeys = qw(DBType DBHost DBUser DBPassword);

    if ( $Param{InstallType} eq 'CreateDB' ) {
        push @NeededKeys, qw(OTRSDBUser OTRSDBPassword);
    }

    # for Oracle we require DBSID and DBPort
    if ( $Param{DBType} eq 'oracle' ) {
        push @NeededKeys, qw(DBSID DBPort);
    }

    # for existing databases we require the database name
    if ( $Param{DBType} ne 'oracle' &amp;&amp; $Param{InstallType} eq 'UseDB' ) {
        push @NeededKeys, 'DBName';
    }

    for my $Key (@NeededKeys) {
        if ( !$Param{$Key} &amp;&amp; $Key !~ /^(DBPassword)$/ ) {
            return (
                Successful =&gt; 0,
                Message    =&gt; "You need '$Key'!!",
                DB         =&gt; undef,
                DBH        =&gt; undef,
            );
        }
    }

    # if we do not need to create a database for OTRS OTRSDBuser equals DBUser
    if ( $Param{InstallType} ne 'CreateDB' ) {
        $Param{OTRSDBUser}     = $Param{DBUser};
        $Param{OTRSDBPassword} = $Param{DBPassword};
    }

    # create DSN string for backend
    if ( $Param{DBType} eq 'mysql' &amp;&amp; $Param{InstallType} eq 'CreateDB' ) {
        $Param{DSN} = "DBI:mysql:database=;host=$Param{DBHost};";
    }
    elsif ( $Param{DBType} eq 'mysql' &amp;&amp; $Param{InstallType} eq 'UseDB' ) {
        $Param{DSN} = "DBI:mysql:database=;host=$Param{DBHost};database=$Param{DBName}";
    }
    elsif ( $Param{DBType} eq 'mssql' &amp;&amp; $Param{InstallType} eq 'CreateDB' ) {
        $Param{DSN} = "DBI:ODBC:driver={SQL Server};Server=$Param{DBHost};";
    }
    elsif ( $Param{DBType} eq 'mssql' &amp;&amp; $Param{InstallType} eq 'UseDB' ) {
        $Param{DSN} = "DBI:ODBC:driver={SQL Server};Server=$Param{DBHost};Database=$Param{DBName}";
    }
    elsif ( $Param{DBType} eq 'postgresql' &amp;&amp; $Param{InstallType} eq 'CreateDB' ) {
        $Param{DSN} = "DBI:Pg:host=$Param{DBHost};";
    }
    elsif ( $Param{DBType} eq 'postgresql' &amp;&amp; $Param{InstallType} eq 'UseDB' ) {
        $Param{DSN} = "DBI:Pg:host=$Param{DBHost};dbname=$Param{DBName}";
    }
    elsif ( $Param{DBType} eq 'oracle' ) {
        $Param{DSN} = "DBI:Oracle:host=$Param{DBHost};sid=$Param{DBSID};port=$Param{DBPort};"
    }

    # extract driver to load for install test
    my ($Driver) = ( $Param{DSN} =~ /^DBI:(.*?):/ );
    if ( !$Self-&gt;{MainObject}-&gt;Require( 'DBD::' . $Driver ) ) {
        return (
            Successful =&gt; 0,
            Message    =&gt; "Can't connect to database, Perl module DBD::$Driver not installed!",
            Comment    =&gt; "",
            DB         =&gt; undef,
            DBH        =&gt; undef,
        );
    }

    my $DBH = DBI-&gt;connect(
        $Param{DSN}, $Param{DBUser}, $Param{DBPassword},
    );

    if ( !$DBH ) {
        return (
            Successful =&gt; 0,
            Message    =&gt; "Can't connect to database, read comment!",
            Comment    =&gt; "$DBI::errstr",
            DB         =&gt; undef,
            DBH        =&gt; undef,
        );
    }

    # if we use an existing database, check if it already contains tables
    if ( $Param{InstallType} ne 'CreateDB' ) {

        my $Data = $DBH-&gt;selectall_arrayref('SELECT * FROM valid');
        if ($Data) {
            return (
                Successful =&gt; 0,
                Message    =&gt; $Self-&gt;{LayoutObject}-&gt;{LanguageObject}
                    -&gt;Get("Database already contains data - it should be empty!"),
                Comment =&gt; "",
                DB      =&gt; undef,
                DBH     =&gt; undef,
            );
        }
    }

    return (
        Successful =&gt; 1,
        Message    =&gt; '',
        Comment    =&gt; '',
        DB         =&gt; \%Param,
        DBH        =&gt; $DBH,
    );
}

sub CheckDBRequirements {
    my ( $Self, %Param ) = @_;

    my %Result = $Self-&gt;ConnectToDB(
        %Param,
    );

    # delete not necessary key/value pairs
    delete $Result{DB};
    delete $Result{DBH};

    return %Result;
}

sub CheckMailConfiguration {
    my ( $Self, %Param ) = @_;

    # first check outbound mail config
    my $OutboundMailType =
        $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'OutboundMailType' );
    my $SMTPHost = $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'SMTPHost' );
    my $SMTPPort = $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'SMTPPort' );
    my $SMTPAuthUser =
        $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'SMTPAuthUser' );
    my $SMTPAuthPassword =
        $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'SMTPAuthPassword' );

    # if chosen config option is SMTP, set some Config params
    if ( $OutboundMailType &amp;&amp; $OutboundMailType ne 'sendmail' ) {
        $Self-&gt;{ConfigObject}-&gt;Set(
            Key   =&gt; 'SendmailModule',
            Value =&gt; 'Kernel::System::Email::' . uc($OutboundMailType),
        );
        $Self-&gt;{ConfigObject}-&gt;Set(
            Key   =&gt; 'SendmailModule::Host',
            Value =&gt; $SMTPHost,
        );
        $Self-&gt;{ConfigObject}-&gt;Set(
            Key   =&gt; 'SendmailModule::Port',
            Value =&gt; $SMTPPort,
        );
        if ($SMTPAuthUser) {
            $Self-&gt;{ConfigObject}-&gt;Set(
                Key   =&gt; 'SendmailModule::AuthUser',
                Value =&gt; $SMTPAuthUser,
            );
        }
        if ($SMTPAuthPassword) {
            $Self-&gt;{ConfigObject}-&gt;Set(
                Key   =&gt; 'SendmailModule::AuthPassword',
                Value =&gt; $SMTPAuthPassword,
            );
        }
    }

    # if sendmail, set config to sendmail
    else {
        $Self-&gt;{ConfigObject}-&gt;Set(
            Key   =&gt; 'SendmailModule',
            Value =&gt; 'Kernel::System::Email::Sendmail',
        );
    }

    # if config option smtp and no smtp host given, return with error
    if ( $OutboundMailType ne 'sendmail' &amp;&amp; !$SMTPHost ) {
        return ( Successful =&gt; 0, Message =&gt; 'No SMTP Host given!' );
    }

    # check outbound mail configuration
    $Self-&gt;{DBObject} = Kernel::System::DB-&gt;new( %{$Self} );
    my $SendObject = Kernel::System::Email-&gt;new( %{$Self} );
    my %Result     = $SendObject-&gt;Check();

    my $SysConfigObject = Kernel::System::SysConfig-&gt;new( %{$Self} );

    # if smtp check was successful, write data into config
    my $SendmailModule = $Self-&gt;{ConfigObject}-&gt;Get('SendmailModule');
    if (
        $Result{Successful}
        &amp;&amp; $SendmailModule ne 'Kernel::System::Email::Sendmail'
        )
    {
        my %NewConfigs = (
            'SendmailModule'       =&gt; $SendmailModule,
            'SendmailModule::Host' =&gt; $SMTPHost,
            'SendmailModule::Port' =&gt; $SMTPPort,
        );

        for my $Key ( sort keys %NewConfigs ) {
            $SysConfigObject-&gt;ConfigItemUpdate(
                Valid =&gt; 1,
                Key   =&gt; $Key,
                Value =&gt; $NewConfigs{$Key},
            );
        }

        if ( $SMTPAuthUser &amp;&amp; $SMTPAuthPassword ) {
            %NewConfigs = (
                'SendmailModule::AuthUser'     =&gt; $SMTPAuthUser,
                'SendmailModule::AuthPassword' =&gt; $SMTPAuthPassword,
            );

            for my $Key ( sort keys %NewConfigs ) {
                $SysConfigObject-&gt;ConfigItemUpdate(
                    Valid =&gt; 1,
                    Key   =&gt; $Key,
                    Value =&gt; $NewConfigs{$Key},
                );
            }
        }
    }

    # if sendmail check was successful, write data into config
    elsif (
        $Result{Successful}
        &amp;&amp; $SendmailModule eq 'Kernel::System::Email::Sendmail'
        )
    {
        $SysConfigObject-&gt;ConfigItemUpdate(
            Valid =&gt; 1,
            Key   =&gt; 'SendmailModule',
            Value =&gt; $Self-&gt;{ConfigObject}-&gt;Get('SendmailModule'),
        );
    }

    # now check inbound mail config. return if the outbound config threw an error
    if ( !$Result{Successful} ) {
        return %Result;
    }

    # check inbound mail config
    my $MailAccount = Kernel::System::MailAccount-&gt;new( %{$Self} );

    for (qw(InboundUser InboundPassword InboundHost)) {
        if ( !$Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; $_ ) ) {
            return ( Successful =&gt; 0, Message =&gt; "Missing parameter: $_!" );
        }
    }

    my $InboundUser = $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'InboundUser' );
    my $InboundPassword =
        $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'InboundPassword' );
    my $InboundHost = $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'InboundHost' );
    my $InboundMailType =
        $Self-&gt;{ParamObject}-&gt;GetParam( Param =&gt; 'InboundMailType' );

    %Result = $MailAccount-&gt;MailAccountCheck(
        Login    =&gt; $InboundUser,
        Password =&gt; $InboundPassword,
        Host     =&gt; $InboundHost,
        Type     =&gt; $InboundMailType,
        Timeout  =&gt; '60',
        Debug    =&gt; '0',
    );

    # if successful, add mail account to DB
    if ( $Result{Successful} ) {
        my $ID = $MailAccount-&gt;MailAccountAdd(
            Login         =&gt; $InboundUser,
            Password      =&gt; $InboundPassword,
            Host          =&gt; $InboundHost,
            Type          =&gt; $InboundMailType,
            ValidID       =&gt; 1,
            Trusted       =&gt; 0,
            DispatchingBy =&gt; 'From',
            QueueID       =&gt; 1,
            UserID        =&gt; 1,
        );

        if ( !$ID ) {
            return (
                Successful =&gt; 0,
                Message    =&gt; 'Error while adding mail account!'
            );
        }
    }

    return %Result;
}

1;
</pre></body></html>