Files
2024-10-14 00:08:40 +02:00

353 lines
9.7 KiB
Perl

# --
# Copyright (C) 2001-2019 OTRS AG, https://otrs.com/
# --
# 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 https://www.gnu.org/licenses/gpl-3.0.txt.
# --
package Kernel::System::Console::Command::Dev::Tools::ImportFakeEmails;
use strict;
use warnings;
use parent qw(Kernel::System::Console::BaseCommand);
use POSIX qw(ceil);
use Time::HiRes qw();
use Kernel::System::PostMaster;
use Kernel::System::MailAccount::IMAP;
our @ObjectDependencies = (
'Kernel::Config',
'Kernel::System::Log',
'Kernel::System::MailAccount',
);
package MyIMAP { ## no critic
our $AUTOLOAD;
sub new {
my $Class = shift;
my %Param = (
@_,
TotalProcessed => 0,
Processed => {},
);
my $Self = bless( \%Param, $Class, );
$Self->{Email} = 'Return-Path: test@dummy.com
Received: from mail.dummy.com (LHLO mail.dummy.com) (62.146.52.73) by
mail.dummy.com with LMTP; Tue, 25 Jul 2017 15:08:45 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
by mail.dummy.com (Postfix) with ESMTP id D17ACAE1F8D
for <test@dummy.com>; Tue, 25 Jul 2017 15:08:45 +0000 (UTC)
X-Spam-Flag: NO
X-Spam-Score: -2.9
X-Spam-Level:
X-Spam-Status: No, score=-2.9 required=6.6 tests=[ALL_TRUSTED=-1,
BAYES_00=-1.9] autolearn=ham autolearn_force=no
Received: from mail.dummy.com ([127.0.0.1])
by localhost (mail.dummy.com [127.0.0.1]) (amavisd-new, port 10032)
with ESMTP id u-bcHVQKwYt4 for <test@dummy.com>;
Tue, 25 Jul 2017 15:08:44 +0000 (UTC)
Received: from localhost (localhost [127.0.0.1])
by mail.dummy.com (Postfix) with ESMTP id E0437AE1F92
for <test@dummy.com>; Tue, 25 Jul 2017 15:08:44 +0000 (UTC)
X-Virus-Scanned: amavisd-new at mail.dummy.com
Received: from mail.dummy.com ([127.0.0.1])
by localhost (mail.dummy.com [127.0.0.1]) (amavisd-new, port 10026)
with ESMTP id hbGqcx4LIqJK for <test@dummy.com>;
Tue, 25 Jul 2017 15:08:44 +0000 (UTC)
Received: from dummy.lan (192.243.186.30.rev.dummy.pt [46.189.212.196])
by mail.dummy.com (Postfix) with ESMTPSA id A8E45AE1F8D
for <test@dummy.com>; Tue, 25 Jul 2017 15:08:44 +0000 (UTC)
From: =?utf-8?B?QW5kcsOpIEJyw6Fz?= <test@dummy.com>
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Mime-Version: 1.0 (Mac OS X Mail 10.3 \(3273\))
Subject: test
Message-Id: <A3586247-F0B4-4887-BCC4-C6587A7E176A-%s-%s@dummy.com>
Date: Tue, 25 Jul 2017 16:09:36 +0100
To: =?utf-8?B?QW5kcsOpIEJyw6Fz?= <test@dummy.com>
X-Mailer: Apple Mail (2.3273)
test %s';
return $Self;
}
sub AUTOLOAD {
my $Self = shift;
my ($Method) = ( $AUTOLOAD =~ m/::([^:]+)$/i );
if ( !$Method || $Method eq 'DESTROY' ) {
return;
}
return 1;
}
sub get {
my ( $Self, $Idx ) = @_;
if ( !( defined $Self->{Processed}->{$Idx} ) ) {
$Self->{TotalProcessed} += 1;
$Self->{Processed}->{$Idx} = 1;
}
my ( $Seconds, $MSeconds ) = Time::HiRes::gettimeofday();
my $Email = sprintf $Self->{Email}, $Seconds, $MSeconds, "$Seconds-$MSeconds";
my @Lines = split "\n", $Email;
return wantarray ? @Lines : \@Lines;
}
sub select {
my $Self = shift;
return $Self->{Total} - $Self->{TotalProcessed};
}
sub nbr_of_processed { shift->{TotalProcessed}; }
};
sub Configure {
my ( $Self, %Param ) = @_;
$Self->Description('Insert fake emails/tickets to the system.');
$Self->AddOption(
Name => 'total',
Description => 'Total of emails to insert per account.',
Required => 1,
HasValue => 1,
ValueRegex => qr/^\d+$/,
);
$Self->AddOption(
Name => 'create-postmaster-accounts',
Description => 'Create fake postmaster accounts.',
Required => 0,
HasValue => 0,
);
$Self->AddOption(
Name => 'per-communication',
Description => 'Number of emails per communication (defaults to 20).',
Required => 0,
HasValue => 1,
ValueRegex => qr/^\d+$/,
);
return;
}
sub Run {
my ( $Self, %Param, ) = @_;
my $CreatePMAccts = $Self->GetOption('create-postmaster-accounts');
my $PerCommunication = $Self->GetOption('per-communication') || 20;
$Kernel::OM->Get('Kernel::Config')->Set(
Key => 'PostMasterReconnectMessage',
Value => $PerCommunication,
);
# Get the current postmaster accounts
my $PMAccounts = $Self->_GetPMAccounts();
return if !$PMAccounts;
# Create postmaster accounts if none exists.
if ( !@{$PMAccounts} ) {
$PMAccounts = $Self->_CreatePMAccounts();
}
# Import the emails
$Self->_ImportEmails(
PMAccounts => $PMAccounts,
);
return $Self->ExitCodeOk();
}
sub _CreatePMAccounts {
my ( $Self, %Param, ) = @_;
my $Total = $Self->GetOption('total');
my $PerCommunication = $Kernel::OM->Get('Kernel::Config')->Get('PostMasterReconnectMessage');
my $LimitAccounts = 5;
my $NbrOfAccounts = ceil( $Total / $PerCommunication );
if ( $NbrOfAccounts > $LimitAccounts ) {
$NbrOfAccounts = $LimitAccounts;
}
my @Accounts = ();
for my $Idx ( 0 .. ( $NbrOfAccounts - 1 ) ) {
my %Account = (
Login => "fake-mail-${ Idx }",
Password => 'SomePassword',
Host => "mail.fake-mail-${ Idx }.com",
ValidID => 1,
Trusted => 0,
DispatchingBy => 'Queue', # Queue|From
QueueID => 1,
UserID => 1,
Type => 'IMAP',
);
my $ID = $Kernel::OM->Get('Kernel::System::MailAccount')->MailAccountAdd(
%Account,
);
if ( !$ID ) {
return $Self->_Log(
Message => 'Error while creating the postmaster mail account: %s - %s',
Binds => [
$Account{Login},
$Account{Host},
]
);
}
push @Accounts,
{
%Account,
ID => $ID,
};
}
return \@Accounts;
}
sub _GetPMAccounts {
my ( $Self, %Param, ) = @_;
return [
$Kernel::OM->Get('Kernel::System::MailAccount')->MailAccountGetAll(),
];
}
sub _ImportEmails {
my ( $Self, %Param, ) = @_;
my $Accounts = $Param{PMAccounts};
my $Total = $Self->GetOption('total');
my $PerCommunication = $Kernel::OM->Get('Kernel::Config')->Get('PostMasterReconnectMessage');
my $TotalProcessed = 0;
my $StartAt = $Kernel::OM->Create('Kernel::System::DateTime');
my $FakeIMAPObject;
# Redefine PostMaster::Run so we can fail some messages
# and keep this change local to the current scope
no strict 'refs'; ## no critic
local *{'Kernel::System::MailAccount::IMAP::Connect'} = sub {
my ( $Self, %Param ) = @_;
return (
Successful => 1,
IMAPObject => $FakeIMAPObject,
Type => 'IMAP',
);
};
my $OriginalPostMasterRun = \&{'Kernel::System::PostMaster::Run'};
local *{'Kernel::System::PostMaster::Run'} = sub {
my $RandNbr = int rand( $FakeIMAPObject->nbr_of_processed() * 999 );
if ( ( $RandNbr % 3 ) == 0 ) {
die "dummy exception";
}
return $OriginalPostMasterRun->(@_);
};
use strict 'refs';
TOTAL:
while ( $TotalProcessed < $Total ) {
for my $Account ( @{$Accounts} ) {
my $ToProcess = $Total - $TotalProcessed;
# Process the account emails
# Create the IMAP object only for the current processing scope
$FakeIMAPObject = MyIMAP->new(
Total => $ToProcess > $PerCommunication ? $PerCommunication : $ToProcess,
);
$Kernel::OM->Get('Kernel::System::MailAccount')->MailAccountFetch(
UserID => 1,
%{$Account},
);
# Update the number of processed emails
$TotalProcessed += $FakeIMAPObject->nbr_of_processed();
$FakeIMAPObject = undef;
# Stop if we reached the limit
last TOTAL if $TotalProcessed >= $Total;
}
}
print 'Insert completed, waiting for some tasks to complete', "\n";
my $StopAt = $Kernel::OM->Create('Kernel::System::DateTime');
$Self->_CleanSpoolFiles(
StartAt => $StartAt,
StopAt => $StopAt,
);
return;
}
sub _CleanSpoolFiles {
my ( $Self, %Param ) = @_;
my $StartAt = $Param{StartAt};
my $StopAt = $Param{StopAt};
my $OtrsDir = __FILE__;
$OtrsDir =~ s/\/Kernel.*$//i;
my @SpoolFilesFailedUnlink = ();
my @SpoolFiles = glob "${ OtrsDir }/var/spool/problem-email-*";
for my $SpoolFile (@SpoolFiles) {
my @FileStat = stat $SpoolFile;
my $FileModifiedAt = $Kernel::OM->Create(
'Kernel::System::DateTime',
ObjectParams => {
Epoch => $FileStat[9],
},
);
if ( $FileModifiedAt >= $StartAt && $FileModifiedAt <= $StopAt ) {
if ( !( unlink $SpoolFile ) ) {
push @SpoolFilesFailedUnlink, $SpoolFile;
}
}
}
return;
}
sub _Log {
my ( $Self, %Param, ) = @_;
my $Message = $Param{Message};
my @Binds = @{ $Param{Binds} || [] };
$Message = sprintf $Message, @Binds;
$Kernel::OM->Get('Kernel::System::Log')->Log(
Message => $Message,
Priority => $Param{'Priority'} || 'error',
);
return;
}
1;