# --
# Kernel/System/PostMaster/Filter/AgentInterface.pm - sub part of PostMaster.pm
# Copyright (C) 2001-2008 OTRS AG, http://otrs.org/
# --
# $Id: AgentInterface.pm,v 1.13 2008/07/13 23:11:15 martin Exp $
# --
# This software comes with ABSOLUTELY NO WARRANTY. For details, see
# the enclosed file COPYING for license information (GPL). If you
# did not receive this file, see http://www.gnu.org/licenses/gpl-2.0.txt.
# --

package Kernel::System::PostMaster::Filter::AgentInterface;

use strict;
use warnings;

use Kernel::System::Email;
use Kernel::System::Queue;
use Kernel::System::User;
use Kernel::System::CustomerUser;

use vars qw($VERSION);
$VERSION = qw($Revision: 1.13 $) [1];

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

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

    $Self->{Debug} = $Param{Debug} || 0;

    # get needed opbjects
    for (qw(ConfigObject LogObject DBObject ParserObject TicketObject MainObject)) {
        $Self->{$_} = $Param{$_} || die "Got no $_!";
    }

    $Self->{EmailObject}        = Kernel::System::Email->new(%Param);
    $Self->{QueueObject}        = Kernel::System::Queue->new(%Param);
    $Self->{UserObject}         = Kernel::System::User->new(%Param);
    $Self->{CustomerUserObject} = Kernel::System::CustomerUser->new(%Param);

    return $Self;
}

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

    # get config options
    my %Config = ();
    my %Match  = ();
    my %Set    = ();
    if ( $Param{JobConfig} && ref( $Param{JobConfig} ) eq 'HASH' ) {
        %Config = %{ $Param{JobConfig} };
        if ( $Config{Match} ) {
            %Match = %{ $Config{Match} };
        }
        if ( $Config{Set} ) {
            %Set = %{ $Config{Set} };
        }
    }

    # check bulk emails
    if ( $Param{GetParam}->{'X-OTRS-Loop'} ) {

        # set this message to ignore, because it's a bulk email
        if ( $Self->{Debug} > 1 ) {
            $Self->{LogObject}->Log(
                Priority => 'debug',
                Message =>
                    "Ignore Message for AgentEmailinterface because of loop header (MessageID:$Param{GetParam}->{'Message-ID'})!",
            );
        }
        $Param{GetParam}->{'X-OTRS-Ignore'} = 'yes';
        return 1;
    }

    # check if it's a follow up
    if ( !$Param{TicketID} ) {
        if ( $Self->{Debug} > 1 ) {
            $Self->{LogObject}->Log(
                Priority => 'debug',
                Message =>
                    "No email for AgentInterface because of missing TicketID (MessageID:$Param{GetParam}->{'Message-ID'})!",
            );
        }
        return 1;
    }

    # get ticket data
    my $TicketHook = $Self->{ConfigObject}->Get('Ticket::Hook') || '';
    my %Ticket = $Self->{TicketObject}->TicketGet( TicketID => $Param{TicketID} );
    if ( !%Ticket ) {
        $Self->{LogObject}->Log(
            Priority => 'debug',
            Message  => "No such Ticket (TicketID=$Param{TicketID})!",
        );
        return 1;
    }

    # get command
    my %Command = ();
    $Param{GetParam}->{Body} =~ s{
        <OTRS_CMD>(.+?)</OTRS_CMD>
    }
    {
        my @CMDs = split(/,/, $1);
       for my $CMD (@CMDs) {
            $CMD =~ s/ //g;
            $Command{lc($CMD)} = 1;
        }
        "";
    }sexm;

    # check commands
    if ( !%Command ) {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message =>
                "No commands in AgentInterface email found, send reject to agent (MessageID:$Param{GetParam}->{'Message-ID'})!",
        );

        # send reject
        $Self->{EmailObject}->Send(
            To      => $Param{GetParam}->{From},
            Subject => "[$TicketHook: $Ticket{TicketNumber}] AgentEmail rejected!",
            Type    => 'text/plain',
            Charset => 'us-ascii',
            Body    => "Sorry, AgentEmail rejected because no <OTRS_CMD> found!",
            Loop    => 1,
        );

        # set this message to ignore, becouse it's already done
        $Param{GetParam}->{'X-OTRS-Ignore'} = 'yes';
        return 1;
    }

    # check To: address (return if no correct recipient)
    if ( $Config{AgentInterfaceAddress} ) {
        my $ForAgentInterface = 0;
        my $Recipient         = '';
        for (qw(To Cc Resent-To)) {
            if ( $Param{GetParam}->{$_} ) {
                if ($Recipient) {
                    $Recipient .= ', ';
                }
                $Recipient .= $Param{GetParam}->{$_};
            }
        }
        my @EmailAddresses = $Self->{ParserObject}->SplitAddressLine( Line => $Recipient, );
        for (@EmailAddresses) {
            my $Address = $Self->{ParserObject}->GetEmailAddress( Email => $_ );
            if ( $Config{AgentInterfaceAddress} =~ /^\Q$Address\E$/i ) {
                $ForAgentInterface = 1;
                if ( $Self->{Debug} > 1 ) {
                    $Self->{LogObject}->Log(
                        Priority => 'debug',
                        Message =>
                            "Email for AgentInterface: $_ (MessageID:$Param{GetParam}->{'Message-ID'})!",
                    );
                }
            }
        }
        if ( !$ForAgentInterface ) {
            if ( $Self->{Debug} > 1 ) {
                $Self->{LogObject}->Log(
                    Priority => 'debug',
                    Message =>
                        "Email not for AgentInterface: $_ (MessageID:$Param{GetParam}->{'Message-ID'})!",
                );
            }
            return 1;
        }
    }

    # check From: Address (return if sender is no valid agent)
    my $From = $Param{GetParam}->{'From'};
    my @FromEmailAddress = $Self->{ParserObject}->SplitAddressLine( Line => $From, );
    $FromEmailAddress[0] = $Self->{ParserObject}->GetEmailAddress( Email => $FromEmailAddress[0] );
    my %User = $Self->{UserObject}->UserSearch(
        Valid            => 1,
        PostMasterSearch => $FromEmailAddress[0],
    );
    my $UserID;
    for ( keys %User ) {
        $UserID = $_;
    }
    if ( !$UserID ) {
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message =>
                "No valid sender for AgentInterface: $From (MessageID:$Param{GetParam}->{'Message-ID'})!",
        );

        # send reject
        $Self->{EmailObject}->Send(
            To      => $Param{GetParam}->{From},
            Subject => "[$TicketHook: $Ticket{TicketNumber}] AgentEmail rejected!",
            Type    => 'text/plain',
            Charset => 'us-ascii',
            Body    => "Sorry, AgentEmail rejected no valid agent sender address!",
            Loop    => 1,
        );

        # set this message to ignore, becouse it's already done
        $Param{GetParam}->{'X-OTRS-Ignore'} = 'yes';
        return 1;
    }

    # check queue permission
    if (
        !$Self->{TicketObject}->Permission(
            Type     => 'rw',
            TicketID => $Param{TicketID},
            UserID   => $UserID
        )
        )
    {

        # send reject
        $Self->{EmailObject}->Send(
            To      => $Param{GetParam}->{From},
            Subject => "[$TicketHook: $Ticket{TicketNumber}] AgentEmail rejected!",
            Type    => 'text/plain',
            Charset => 'us-ascii',
            Body    => "Sorry, AgentEmail rejected because no rw permission on this ticket!",
            Loop    => 1,
        );

        # set this message to ignore, becouse it's already done
        $Param{GetParam}->{'X-OTRS-Ignore'} = 'yes';
        return 1;
    }

    # send orig (get)
    if ( $Command{get} ) {
        delete $Command{get};

        # get old article for quoteing
        my %Article
            = $Self->{TicketObject}->ArticleLastCustomerArticle( TicketID => $Param{TicketID} );

        # set from
        my $From = $Self->{ConfigObject}->Get('NotificationSenderName') . ' <'
            . $Self->{ConfigObject}->Get('NotificationSenderEmail') . '>';
        my $Subject = $Self->{TicketObject}->TicketSubjectBuild(
            TicketNumber => $Ticket{TicketNumber},
            Subject => $Article{Subject} || '',
        );
        my $Body
            = "\n----------------->raw message send by OTRS<-------------------\n<OTRS_CMD>send,lock,unlock</OTRS_CMD>\n";
        for (qw(From To Cc Subject)) {
            if ( $Article{$_} ) {
                $Body .= "$_: $Article{$_}\n";
            }
        }
        $Body .= $Article{Body};

        # send notify
        $Self->{EmailObject}->Send(
            From => $Article{From} || $From,
            To => $Param{GetParam}->{From},
            Subject    => $Subject,
            'Reply-To' => $Self->{ConfigObject}->Get('NotificationSenderEmail'),
            Type       => 'text/plain',
            Charset    => $Article{Charset},
            Body       => $Body,
            Loop       => 1,
        );

        # log reject
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message =>
                "Sent requested ticket ($Ticket{TicketNumber}) to $Param{GetParam}->{From}: $From (MessageID:$Param{GetParam}->{'Message-ID'})!",
        );

        # set this message to ignore, becouse it's already done
        $Param{GetParam}->{'X-OTRS-Ignore'} = 'yes';
        return 1;
    }

    # check command
    # close
    # lock ticket
    if ( $Command{lock} ) {

        # check lock
        if ( !$Self->{TicketObject}->LockIsTicketLocked( TicketID => $Param{TicketID} ) ) {

            # set owner
            $Self->{TicketObject}->OwnerSet(
                TicketID  => $Param{TicketID},
                UserID    => $UserID,
                NewUserID => $UserID,
            );

            # set lock
            $Self->{TicketObject}->LockSet(
                TicketID => $Param{TicketID},
                Lock     => 'lock',
                UserID   => $UserID,
            );
        }
        else {
            my ( $OwnerID, $OwnerLogin )
                = $Self->{TicketObject}->OwnerCheck( TicketID => $Param{TicketID}, );
            if ( $OwnerID != $UserID ) {

                # log reject
                $Self->{LogObject}->Log(
                    Priority => 'notice',
                    Message =>
                        "Reject AgentInterface message because of other owner lock: $From (MessageID:$Param{GetParam}->{'Message-ID'})!",
                );

                # send reject
                $Self->{EmailObject}->Send(
                    To      => $Param{GetParam}->{From},
                    Subject => "[$TicketHook: $Ticket{TicketNumber}] AgentEmail rejected!",
                    Type    => 'text/plain',
                    Charset => 'us-ascii',
                    Body =>
                        "Sorry, AgentEmail rejected because Ticket is already locked for somebody else!",
                    Loop => 1,
                );

                # set this message to ignore, becouse it's already done
                $Param{GetParam}->{'X-OTRS-Ignore'} = 'yes';
                return 1;
            }
        }
    }

    # send answer
    if ( $Command{send} ) {
        delete $Command{send};

        # check lock
        if ( !$Self->{TicketObject}->LockIsTicketLocked( TicketID => $Param{TicketID} ) ) {

            # set owner
            $Self->{TicketObject}->OwnerSet(
                TicketID  => $Param{TicketID},
                UserID    => $UserID,
                NewUserID => $UserID,
            );

            # set lock
            $Self->{TicketObject}->LockSet(
                TicketID => $Param{TicketID},
                Lock     => 'lock',
                UserID   => $UserID,
            );
        }
        else {
            my ( $OwnerID, $OwnerLogin )
                = $Self->{TicketObject}->OwnerCheck( TicketID => $Param{TicketID}, );
            if ( $OwnerID != $UserID ) {

                # log reject
                $Self->{LogObject}->Log(
                    Priority => 'notice',
                    Message =>
                        "Reject AgentInterface message because of other owner lock: $From (MessageID:$Param{GetParam}->{'Message-ID'})!",
                );

                # send reject
                $Self->{EmailObject}->Send(
                    To      => $Param{GetParam}->{From},
                    Subject => "[$TicketHook: $Ticket{TicketNumber}] AgentEmail rejected!",
                    Type    => 'text/plain',
                    Charset => 'us-ascii',
                    Body =>
                        "Sorry, AgentEmail rejected because Ticket is already locked for somebody else!",
                    Loop => 1,
                );

                # set this message to ignore, becouse it's already done
                $Param{GetParam}->{'X-OTRS-Ignore'} = 'yes';
                return 1;
            }
        }

        # get old article
        my %Data
            = $Self->{TicketObject}->ArticleLastCustomerArticle( TicketID => $Param{TicketID}, );

        # check article type and replace To with From (in case)
        if ( $Data{SenderType} !~ /customer/ ) {
            my $To   = $Data{To};
            my $From = $Data{From};
            $Data{From}    = $To;
            $Data{To}      = $Data{From};
            $Data{ReplyTo} = '';
        }

        # check ReplyTo
        if ( $Data{ReplyTo} ) {
            $Data{To} = $Data{ReplyTo};
        }
        else {
            $Data{To} = $Data{From};
        }

        # get customer data
        my %Customer = ();
        if ( $Ticket{CustomerUserID} ) {
            %Customer = $Self->{CustomerUserObject}->CustomerUserDataGet(
                User => $Ticket{CustomerUserID},
            );
        }

        # get to email (just "some@example.com")
        for my $Email ( Mail::Address->parse( $Data{To} ) ) {
            $Data{ToEmail} = $Email->address();
        }

        # use database email
        if ( $Customer{UserEmail} && $Data{ToEmail} !~ /^\Q$Customer{UserEmail}\E$/i ) {
            $Self->{LogObject}->Log(
                Priority => 'notice',
                Message =>
                    "Added customer database email to Cc: $Customer{UserEmail} (MessageID:$Param{GetParam}->{'Message-ID'})!",
            );
            if ( $Data{Cc} ) {
                $Data{Cc} .= ', ' . $Customer{UserEmail};
            }
            else {
                $Data{Cc} = $Customer{UserEmail};
            }
        }

        # prepare subject
        my $Subject = $Self->{TicketObject}->TicketSubjectBuild(
            TicketNumber => $Ticket{TicketNumber},
            Subject => $Param{GetParam}->{'Subject'} || '',
        );

        # get queue sender
        my %Address = $Self->{QueueObject}->GetSystemAddress(%Ticket);
        $Data{From} = "$Address{RealName} <$Address{Email}>";
        my $NewRecipient = '';
        for (qw(To Cc Bcc)) {
            if ( $Data{$_} ) {
                $NewRecipient .= "$Data{$_}, ";
            }
        }

        # send email
        my $ArticleID = $Self->{TicketObject}->ArticleSend(
            ArticleType    => 'email-external',
            SenderType     => 'agent',
            TicketID       => $Param{TicketID},
            HistoryType    => 'SendAnswer',
            HistoryComment => "\%\%$NewRecipient",
            From           => $Data{From},
            To             => $Data{To},
            Cc             => $Data{Cc} || '',
            Bcc            => $Data{Bcc} || '',
            Subject        => $Subject,
            UserID         => $UserID,
            Body           => $Param{GetParam}->{'Body'},
            InReplyTo      => $Data{InReplyTo},
            Charset        => $Param{GetParam}->{'Charset'},
            Type           => 'text/plain',
            Attachment     => [ $Self->{ParserObject}->GetAttachments() ],
        );
        $Self->{LogObject}->Log(
            Priority => 'notice',
            Message =>
                "Send AgentInterface message to $NewRecipient (MessageID:$Param{GetParam}->{'Message-ID'})!",
        );
    }

    # unlock ticket
    if ( $Command{unlock} ) {
        delete $Command{unlock};
        my ( $OwnerID, $OwnerLogin )
            = $Self->{TicketObject}->OwnerCheck( TicketID => $Param{TicketID}, );
        if ( $OwnerID != $UserID ) {

            # log reject
            $Self->{LogObject}->Log(
                Priority => 'notice',
                Message =>
                    "Reject AgentInterface message because of other owner lock: $From (MessageID:$Param{GetParam}->{'Message-ID'})!",
            );

            # send reject
            $Self->{EmailObject}->Send(
                To      => $Param{GetParam}->{From},
                Subject => "[$TicketHook: $Ticket{TicketNumber}] AgentEmail rejected!",
                Type    => 'text/plain',
                Charset => 'us-ascii',
                Body =>
                    "Sorry, AgentEmail rejected because Ticket is already locked for somebody else!",
                Loop => 1,
            );

            # set this message to ignore, becouse it's already done
            $Param{GetParam}->{'X-OTRS-Ignore'} = 'yes';
            return 1;
        }

        # set unlock
        $Self->{TicketObject}->LockSet(
            TicketID => $Param{TicketID},
            Lock     => 'unlock',
            UserID   => $UserID,
        );
        print "Unlock Ticket\n";
    }
    if (%Command) {
        for ( sort keys %Command ) {
            $Self->{LogObject}->Log(
                Priority => 'error',
                Message  => "Unknown command $_! (MessageID:$Param{GetParam}->{'Message-ID'})!",
            );
            print "Unknown Command $_\n";
        }
    }

    # set this message to ignore, becouse it's already done
    $Param{GetParam}->{'X-OTRS-Ignore'} = 'yes';

    return 1;
}

1;
