1# --
2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/
3# --
4# This software comes with ABSOLUTELY NO WARRANTY. For details, see
5# the enclosed file COPYING for license information (GPL). If you
6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
7# --
8
9package Kernel::System::Console::Command::Maint::PostMaster::Read;
10
11use strict;
12use warnings;
13
14use parent qw(Kernel::System::Console::BaseCommand);
15
16our @ObjectDependencies = (
17    'Kernel::System::CommunicationLog',
18    'Kernel::System::Main',
19);
20
21sub Configure {
22    my ( $Self, %Param ) = @_;
23
24    $Self->Description('Read incoming email from STDIN.');
25    $Self->AddOption(
26        Name        => 'target-queue',
27        Description => "Preselect a target queue by name.",
28        Required    => 0,
29        HasValue    => 1,
30        ValueRegex  => qr/.*/smx,
31    );
32    $Self->AddOption(
33        Name        => 'untrusted',
34        Description => "This will cause X-OTRS email headers to be ignored.",
35        Required    => 0,
36        HasValue    => 0,
37    );
38
39    return;
40}
41
42sub Run {
43    my ( $Self, %Param ) = @_;
44
45    # start a new incoming communication
46    my $CommunicationLogObject = $Kernel::OM->Create(
47        'Kernel::System::CommunicationLog',
48        ObjectParams => {
49            Transport   => 'Email',
50            Direction   => 'Incoming',
51            AccountType => 'STDIN',
52        },
53    );
54
55    # start object log for the incoming connection
56    $CommunicationLogObject->ObjectLogStart( ObjectLogType => 'Connection' );
57
58    $CommunicationLogObject->ObjectLog(
59        ObjectLogType => 'Connection',
60        Priority      => 'Debug',
61        Key           => 'Kernel::System::Console::Command::Maint::PostMaster::Read',
62        Value         => 'Read email from STDIN.',
63    );
64
65    # get email from SDTIN
66    my @Email = <STDIN>;    ## no critic
67
68    if ( !@Email ) {
69
70        $CommunicationLogObject->ObjectLog(
71            ObjectLogType => 'Connection',
72            Priority      => 'Error',
73            Key           => 'Kernel::System::Console::Command::Maint::PostMaster::Read',
74            Value         => 'Got no email on STDIN!',
75        );
76
77        $CommunicationLogObject->ObjectLogStop(
78            ObjectLogType => 'Connection',
79            Status        => 'Failed',
80        );
81        $CommunicationLogObject->CommunicationStop( Status => 'Failed' );
82
83        return $Self->ExitCodeError(1);
84    }
85
86    $CommunicationLogObject->ObjectLog(
87        ObjectLogType => 'Connection',
88        Priority      => 'Debug',
89        Key           => 'Kernel::System::Console::Command::Maint::PostMaster::Read',
90        Value         => 'Email with ' . ( scalar @Email ) . ' lines successfully read from STDIN.',
91    );
92
93    # start object log for the email processing
94    $CommunicationLogObject->ObjectLogStart( ObjectLogType => 'Message' );
95
96    # remember the return code to stop the communictaion later with a proper status
97    my $PostMasterReturnCode = 0;
98
99    # Wrap the main part of the script in an "eval" block so that any
100    # unexpected (but probably transient) fatal errors (such as the
101    # database being unavailable) can be trapped without causing a
102    # bounce
103    eval {
104
105        $CommunicationLogObject->ObjectLog(
106            ObjectLogType => 'Message',
107            Priority      => 'Debug',
108            Key           => 'Kernel::System::Console::Command::Maint::PostMaster::Read',
109            Value         => 'Processing email with PostMaster module.',
110        );
111
112        my $PostMasterObject = $Kernel::OM->Create(
113            'Kernel::System::PostMaster',
114            ObjectParams => {
115                CommunicationLogObject => $CommunicationLogObject,
116                Email                  => \@Email,
117                Trusted                => $Self->GetOption('untrusted') ? 0 : 1,
118            },
119        );
120
121        my @Return = $PostMasterObject->Run(
122            Queue => $Self->GetOption('target-queue'),
123        );
124
125        if ( !$Return[0] ) {
126
127            $CommunicationLogObject->ObjectLog(
128                ObjectLogType => 'Message',
129                Priority      => 'Error',
130                Key           => 'Kernel::System::Console::Command::Maint::PostMaster::Read',
131                Value => 'PostMaster module exited with errors, could not process email. Please refer to the log!',
132            );
133            $CommunicationLogObject->CommunicationStop( Status => 'Failed' );
134
135            die "Could not process email. Please refer to the log!\n";
136        }
137
138        my $Dump = $Kernel::OM->Get('Kernel::System::Main')->Dump( \@Return );
139        $CommunicationLogObject->ObjectLog(
140            ObjectLogType => 'Message',
141            Priority      => 'Debug',
142            Key           => 'Kernel::System::Console::Command::Maint::PostMaster::Read',
143            Value         => "Email processing with PostMaster module completed, return data: $Dump",
144        );
145
146        $PostMasterReturnCode = $Return[0];
147    };
148
149    if ($@) {
150
151        # An unexpected problem occurred (for example, the database was
152        # unavailable). Return an EX_TEMPFAIL error to cause the mail
153        # program to requeue the message instead of immediately bouncing
154        # it; see sysexits.h. Most mail programs will retry an
155        # EX_TEMPFAIL delivery for about four days, then bounce the
156        # message.)
157        my $Message = $@;
158
159        $CommunicationLogObject->ObjectLog(
160            ObjectLogType => 'Message',
161            Priority      => 'Error',
162            Key           => 'Kernel::System::Console::Command::Maint::PostMaster::Read',
163            Value         => "An unexpected error occurred, message: $Message",
164        );
165
166        $CommunicationLogObject->ObjectLogStop(
167            ObjectLogType => 'Message',
168            Status        => 'Failed',
169        );
170        $CommunicationLogObject->ObjectLogStop(
171            ObjectLogType => 'Connection',
172            Status        => 'Failed',
173        );
174        $CommunicationLogObject->CommunicationStop( Status => 'Failed' );
175
176        return $Self->ExitCodeError(75);
177    }
178
179    $CommunicationLogObject->ObjectLog(
180        ObjectLogType => 'Connection',
181        Priority      => 'Debug',
182        Key           => 'Kernel::System::Console::Command::Maint::PostMaster::Read',
183        Value         => 'Closing connection from STDIN.',
184    );
185
186    $CommunicationLogObject->ObjectLogStop(
187        ObjectLogType => 'Message',
188        Status        => 'Successful',
189    );
190    $CommunicationLogObject->ObjectLogStop(
191        ObjectLogType => 'Connection',
192        Status        => 'Successful',
193    );
194
195    my %ReturnCodeMap = (
196        0 => 'Failed',        # error (also false)
197        1 => 'Successful',    # new ticket created
198        2 => 'Successful',    # follow up / open/reopen
199        3 => 'Successful',    # follow up / close -> new ticket
200        4 => 'Failed',        # follow up / close -> reject
201        5 => 'Successful',    # ignored (because of X-OTRS-Ignore header)
202    );
203
204    $CommunicationLogObject->CommunicationStop(
205        Status => $ReturnCodeMap{$PostMasterReturnCode} // 'Failed',
206    );
207
208    return $Self->ExitCodeOk();
209}
210
2111;
212