EAI-Wrap
view release on metacpan or search on metacpan
lib/EAI/Common.pm view on Meta::CPAN
package EAI::Common 1.921;
use strict; use feature 'unicode_strings'; use warnings; no warnings 'uninitialized';
use Exporter qw(import); use EAI::DateUtil; use Data::Dumper qw(Dumper); use Getopt::Long qw(:config no_ignore_case); use Log::Log4perl qw(get_logger); use MIME::Lite (); use Scalar::Util qw(looks_like_number);
use Carp qw(confess longmess);
# to make use of colored logs with Log::Log4perl::Appender::ScreenColoredLevels on windows we have to use that (special "use" to make this optional on non-win environments)
BEGIN {
if ($^O =~ /MSWin/) {require Win32::Console::ANSI; Win32::Console::ANSI->import();}
}
our @EXPORT = qw($EAI_WRAP_CONFIG_PATH $EAI_WRAP_SENS_CONFIG_PATH %common %config %execute @loads @optload %opt readConfigFile getSensInfo setupConfigMerge getOptions setupEAIWrap dumpFlat extractConfigs checkHash checkParam getLogFPathForMail getLog...
my %hashCheck = (
common => {
DB => {},
File => {},
FTP => {},
process => {},
task => {},
},
config => { # parameter category for site global settings, usually defined in site.config and other associated configs loaded at INIT
checkLogExistDelay => {}, # ref to following hash: {Test => 2, Dev => 3, "" => 0}, mapping to set delays for checkLogExist per environment in $execute{env}, this can be further overriden per job (and environment) in checkLookup.
checkLookup => {}, # ref to following datastructure: {"scriptname.pl + optional addToScriptName" => {errmailaddress => "",errmailsubject => "",timeToCheck =>"", freqToCheck => "", logFileToCheck => "", logcheck => "",logRootPath =>""},...} used for...
errmailaddress => "", # default mail address for central logcheck/errmail sending
errmailsubject => "", # default mail subject for central logcheck/errmail sending
executeOnInit => "", # code to be executed during INIT of EAI::Wrap to allow for assignment of config/execute parameters from commandline params BEFORE Logging!
folderEnvironmentMapping => {}, # ref to hash {Test => "Test", Dev => "Dev", "" => "Prod"}, mapping for $execute{envraw} to $execute{env}
fromaddress => "", # from address for central logcheck/errmail sending, also used as default sender address for sendGeneralMail
historyFolder => {}, # ref to following hash: {"scriptname.pl + optional addToScriptName" => "folder"}, folders where downloaded files are historized, lookup key as in checkLookup, default in "" => "defaultfolder". historyFolder, historyFolderUploa...
historyFolderUpload => {}, # ref to following hash: {"scriptname.pl + optional addToScriptName" => "folder"}, folders where uploaded files are historized, lookup key as in checkLookup, default in "" => "defaultfolder"
logCheckHoliday => "", # calendar for business days in central logcheck/errmail sending. builtin calendars are AT (Austria), TG (Target), UK (United Kingdom) and WE (for only weekends). Calendars can be added with EAI::DateUtil::addCalendar
logs_to_be_ignored_in_nonprod => qr//, # regular expression to specify logs to be ignored in central logcheck/errmail sending
logprefixForLastLogfile => sub {}, # prefix for previous (day) logs to be set in error mail (link), if not given, defaults to get_curdate(). In case Log::Dispatch::FileRotate is used as the File Appender in Log4perl config, the previous log is iden...
logRootPath => {}, # ref to following hash: {"scriptname.pl + optional addToScriptName" => "folder"}, paths to log file root folders (environment is added to that if non production), lookup key as checkLookup, default in "" => "defaultfolder"
prodEnvironmentInSeparatePath => 1, # set to 1 if the production scripts/logs etc. are in a separate Path defined by folderEnvironmentMapping (prod=root/Prod, test=root/Test, etc.), set to 0 if the production scripts/logs are in the root folder and...
redoDir => {}, # ref to following hash: {"scriptname.pl + optional addToScriptName" => "folder"}, folders where files for redo are contained, lookup key as checkLookup, default in "" => "defaultfolder"
sensitive => {}, # hash lookup table: {"prefix" => {user=>"",pwd =>"",hostkey=>"",privkey =>""},...} for sensitive access information in DB and FTP (lookup keys are set with DB{prefix} or FTP{prefix}), may also be placed outside of site.config; all...
smtpServer => "", # smtp server for den (error) mail sending
smtpTimeout => 60, # timeout for smtp response
testerrmailaddress => '', # error mail address in non prod environment
DB => {},
File => {},
FTP => {},
process => {},
task => {},
},
execute => { # hash of parameters for current task execution. This is not to be set by the user, but can be used to as information to set other parameters and control the flow
addToScriptName => "", # this can be set to be added to the scriptname for config{checkLookup} keys, e.g. some passed parameter. This is typically done in config{executeOnInit}
env => "", # Prod, Test, Dev, whatever is defined as the lookup value in folderEnvironmentMapping. homedir as fetched from the File::basename::dirname of the executing script using /^.*[\\\/](.*?)$/ is used as the key for looking up this value.
envraw => "", # Production has a special significance here as being an empty string. Otherwise like env.
errmailaddress => "", # target address for central logcheck/errmail sending in current process
errmailsubject => "", # mail subject for central logcheck/errmail sending in current process
failcount => 1, # for counting failures in processing to switch to longer wait period or finish altogether
filesToDelete => [], # list of files to be deleted locally after download, necessary for cleanup at the end of the process
filesUploadedToDelete => [], # list of files to be deleted locally after upload, necessary for cleanup at the end of the process
filesToMoveinHistory => [], # list of files to be moved in historyFolder locally, necessary for cleanup at the end of the process
filesToMoveinHistoryUpload => [], # list of files to be moved in historyFolderUpload locally, necessary for cleanup at the end of the process
firstRunSuccess => 1, # for planned retries (process=>plannedUntil filled) -> this is set after the first run to avoid error messages resulting of files having been moved/removed.
freqToCheck => "", # for logchecker: frequency to check entries (B,D,M,M1) ...
homedir => "", # the home folder of the script, mostly used to return from redo and other folders for globbing files.
historyFolder => "", # actually set historyFolder
historyFolderUpload => "", # actually set historyFolderUpload
logcheck => "", # for logchecker: the Logcheck (regex)
logFileToCheck => "", # for logchecker: Logfile to be searched
logRootPath => "", # actually set logRootPath
processEnd => 1, # specifies that the process is ended, checked in EAI::Wrap::processingEnd
redoDir => "", # actually set redoDir
retryBecauseOfError => 1, # retryBecauseOfError shows if a rerun occurs due to errors (for successMail)
retrySeconds => 60, # how many seconds are passed between retries. This is set on error with process=>retrySecondsErr and if planned retry is defined with process=>retrySecondsPlanned
scriptname => "", # name of the current process script, also used in log/history setup together with addToScriptName for config{checkLookup} keys
startingTime => "", # tasks starting time for checking task{retryEndsAfterMidnight} against current time
timeToCheck => "", # for logchecker: scheduled time of job (don't look earlier for log entries)
},
load => {
DB => {},
File => {},
FTP => {},
process => {},
},
DB => { # DB specific configs
addID => {}, # this hash can be used to additionaly set a constant to given fields: Fieldname => Fieldvalue
additionalLookup => "", # query used in getAdditionalDBData to retrieve lookup information from DB using EAI::DB::readFromDBHash
additionalLookupKeys => [], # used for getAdditionalDBData, list of field names to be used as the keys of the returned hash
cutoffYr2000 => 60, # when storing date data with 2 year digits in dumpDataIntoDB/EAI::DB::storeInDB, this is the cutoff where years are interpreted as 19XX (> cutoffYr2000) or 20XX (<= cutoffYr2000)
columnnames => [], # returned column names from EAI::DB::readFromDB and EAI::DB::readFromDBHash, this is used in writeFileFromDB to pass column information from database to writeText
database => "", # database to be used for connecting
debugKeyIndicator => "", # used in dumpDataIntoDB/EAI::DB::storeInDB as an indicator for keys for debugging information if primkey not given (errors are shown with this key information). Format is the same as for primkey
deleteBeforeInsertSelector => "", # used in dumpDataIntoDB/EAI::DB::storeInDB to delete specific data defined by keydata before an insert (first occurrence in data is used for key values). Format is the same as for primkey ("key1 = ? ...")
dontWarnOnNotExistingFields => 0, # suppress warnings in dumpDataIntoDB/EAI::DB::storeInDB for not existing fields
dontKeepContent => 1, # if table should be completely cleared before inserting data in dumpDataIntoDB/EAI::DB::storeInDB
doUpdateBeforeInsert => 1, # invert insert/update sequence in dumpDataIntoDB/EAI::DB::storeInDB, insert only done when upsert flag is set
lib/EAI/Common.pm view on Meta::CPAN
dateOfFetchedFile => 0, # returned date (taken from mtime/mdtm) of file fetched with fetchFiles in format YYYYMMDD, only works for single file
dontMoveTempImmediately => 1, # if 0 oder missing: rename/move files immediately after writing to FTP to the final name, otherwise/1: a call to EAI::FTP::moveTempFiles is required for that
dontDoSetStat => 1, # for Net::SFTP::Foreign, no setting of time stamp of remote file to that of local file (avoid error messages of FTP Server if it doesn't support this)
dontDoUtime => 1, # don't set time stamp of local file to that of remote file
dontUseQuoteSystemForPwd => 0, # for windows, a special quoting is used for passing passwords to Net::SFTP::Foreign that contain [()"<>& . This flag can be used to disable this quoting.
dontUseTempFile => 1, # directly upload files, without temp files
fileToArchive => 1, # should files be archived on FTP server? if archiveDir is not set, then file is archived (rolled) in the same folder
fileToRemove => 1, # should files be removed on FTP server?
FTPdebugLevel => 0, # debug ftp: 0 or ~(1|2|4|8|16|1024|2048), loglevel automatically set to debug for module EAI::FTP
hostkey => "", # hostkey to present to the server for Net::SFTP::Foreign, either directly (insecure -> visible) or via sensitive lookup
hostkey2 => "", # additional hostkey to be presented (e.g. in case of round robin DNS)
localDir => "", # optional: local folder for files to be placed, if not given files are downloaded into current folder
lookups => {}, # similar to $config{sensitive}, a hash lookup table ({"prefix" => {remoteHost=>""},...} or {"prefix" => {remoteHost=>{Prod => "", Test => ""}},...}) for centrally looking up remoteHost and port settings depending on $FTP{prefix}.
maxConnectionTries => 5, # maximum number of tries for connecting in login procedure
noDirectRemoteDirChange => 1, # if no direct change into absolute paths (/some/path/to/change/into) ist possible then set this to 1, this does a separated change into setcwd(undef) and setcwd(remoteDir)
onlyArchive => 0, # only archive/remove given files on the FTP server, requires archiveDir to be set
path => "", # additional relative FTP path (under remoteDir which is set at login), where the file(s) is/are located
port => 22, # ftp/sftp port (leave empty for default port 22 when using Net::SFTP::Foreign, or port 21 when using Net::FTP)
prefix => "ftp", # key for sensitive information (e.g. pwd and user) in config{sensitive} or system wide remoteHost/port in config{FTP}{prefix}{remoteHost} or config{FTP}{prefix}{port}. respects environment in $execute{env} if configured.
privKey => "", # sftp key file location for Net::SFTP::Foreign, either directly (insecure -> visible) or via sensitive lookup
pwd => "", # for password setting, either directly (insecure -> visible) or via sensitive lookup
queue_size => 1, # queue_size for Net::SFTP::Foreign, if > 1 this causes often connection issues
remove => {}, # ref to hash {removeFolders=>[], day=>, mon=>, year=>1} for for removing (archived) files with removeFilesOlderX, all files in removeFolders are deleted being older than day days, mon months and year years
remoteDir => "", # remote root folder for up-/download, archive and remove: "out/Marktdaten/", path is added then for each filename (load)
remoteHost => {}, # ref to hash of IP-addresses/DNS of host(s).
SFTP => 0, # to explicitly use SFTP, if not given SFTP will be derived from existence of privKey or hostkey
simulate => 0, # for removal of files using removeFilesinFolderOlderX/removeFilesOlderX only simulate (1) or do actually (0)?
sshInstallationPath => "", # path were ssh/plink exe to be used by Net::SFTP::Foreign is located
type => "", # (A)scii or (B)inary, only applies to Net::FTP
user => "", # set user directly, either directly (insecure -> visible) or via sensitive lookup
},
process => { # used to pass information within each process (data, additionalLookupData, filenames, hadErrors, retrievedFiles or commandline parameters starting with interactive) and for additional configurations not suitable for DB, File or FTP (e....
additionalLookupData => {}, # additional data retrieved from database with EAI::Wrap::getAdditionalDBData
archivefilenames => [], # in case a zip archive package is retrieved, the filenames of these packages are kept here, necessary for cleanup at the end of the process
countPercent => 0, # percentage for counting File text reading and DB storing, if given (greater 0) then on each reaching of the percentage in countPercent a progress is shown (e.g. every 10% if countPercent = 10). Any value >=100 will count ALL li...
data => [], # loaded data: array (rows) of hash refs (columns)
filenames => [], # names of files that were retrieved and checked to be locally available for that load, can be more than the defined file in File->filename (due to glob spec or zip archive package)
filesProcessed => {}, # hash for checking the processed files, necessary for cleanup at the end of the whole task
hadErrors => 1, # set to 1 if there were any errors in the process
interactive_ => "", # interactive options (are not checked), can be used to pass arbitrary data via command line into the script (eg a selected date for the run with interactive_date).
onlyExecFor => qr//, # define loads to only be executed when $common{task}{execOnly} !~ $load->{process}{onlyExecFor}. Empty onlyExecFor loads are always executed regardless of $common{task}{execOnly}
retrievedFiles => [], # files retrieved from FTP or redo directory
successfullyDone => "", # accumulates API sub names to prevent most API calls that ran successfully from being run again.
uploadCMD => "", # upload command for use with uploadFileCMD
uploadCMDPath => "", # path of upload command
uploadCMDLogfile => "", # logfile where command given in uploadCMD writes output (for error handling)
},
task => { # contains parameters used on the task script level, only available for %common parameter hash.
customHistoryTimestamp => "", # optional custom timestamp to be added to filenames moved to History/HistoryUpload/FTP archive, if not given, get_curdatetime is used (YYYYMMDD_hhmmss)
execOnly => "", # do not execute loads where $common{task}{execOnly} !~ $load->{process}{onlyExecFor}. Empty onlyExecFor loads are always executed regardless of $common{task}{execOnly}
ignoreNoTest => 0, # ignore the notest file in the process-script folder, usually preventing all runs that are not in production
plannedUntil => 2359, # latest time that planned repetition should start, this can be given either as HHMM (HourMinute) or HHMMSS (HourMinuteSecond), in case of HHMM the "Second" part is attached as 59
redoFile => 1, # flag for specifying a redo
redoTimestampPatternPart => "", # part of the regex for checking against filename in redo with additional timestamp/redoDir pattern (e.g. "redo", numbers and _), anything after files barename (and before ".$ext" if extension is defined) is regarded...
retryEndsAfterMidnight => 1, # if set, all retries should end after midnight
retrySecondsErr => 60, # retry period in case of error
retrySecondsErrAfterXfails => 600, # after fail count is reached this alternate retry period in case of error is applied. If 0/undefined then job finishes after fail count
retrySecondsXfails => 3, # fail count after which the retrySecondsErr are changed to retrySecondsErrAfterXfails
retrySecondsPlanned => 300, # retry period in case of planned retry
skipHolidays => "", # skip script execution on holidays
skipHolidaysDefault => "", # holiday calendar to take into account for skipHolidays
skipWeekends => 0, # skip script execution on weekends
skipForFirstBusinessDate => "", # used for "wait with execution for first business date", either this is a calendar or 1 (then calendar is skipHolidaysDefault), this cannot be used together with skipHolidays
},
);
# alternate type checking for these as they might have different types
my %alternateType = (
configexecuteOnInit => sub {}, # can be eval string or anonymous sub
DBpostDumpProcessing => sub {}, # can be eval string or anonymous sub
DBpostReadProcessing => sub {}, # can be eval string or anonymous sub
Filecolumns => [], # can be ref to hash or ref to array
Fileformat_skip => 1, # can be "skip until pattern" string or line number (int)
Fileformat_sep => qr//, # can be separator string or regex split
FilelineCode => sub {}, # can be eval string or anonymous sub
FTPremoteHost => "", # can also be string
taskskipHolidays => 1, # can be calendar string or true (1)
taskskipForFirstBusinessDate => 1, # can be calendar string or true (1)
);
# passed options containing numerical strings are converted to numbers if their hash check (definition) looks like a number and their leading zero shouldn't be preserved
# currently below two parameters are to be treated as strings.
my %allow_leading_zeros = (
task => {
plannedUntil => 1,
},
DB => {
cutoffYr2000 => 1,
}
);
our %common;our %config;our @loads;our %execute;our @optload;our %opt;
our $EAI_WRAP_CONFIG_PATH; our $EAI_WRAP_SENS_CONFIG_PATH;
my @coreConfig = ("DB","File","FTP","process");
my @commonCoreConfig = (@coreConfig,"task");
my @allConfig = (@commonCoreConfig,"config");
our $logConfig;
# read given config file (eval perl code)
sub readConfigFile ($) {
my ($configfilename) = @_;
my $siteCONFIGFILE;
open (CONFIGFILE, "<$configfilename") or confess("couldn't open $configfilename: $@ $!, caller ".(caller(1))[3].", line ".(caller(1))[2]." in ".(caller(1))[1]);
{
local $/=undef;
$siteCONFIGFILE = <CONFIGFILE>;
close CONFIGFILE;
}
unless (my $return = eval $siteCONFIGFILE) {
confess("Error parsing config file $configfilename for script $execute{homedir}/$execute{scriptname}: $@") if $@;
confess("Error executing config file $configfilename for script $execute{homedir}/$execute{scriptname}: $!") unless defined $return;
}
print STDOUT "included $configfilename\n";
}
# get key info from $config{sensitive}{$prefix}{$key}. Also checks if $config{sensitive}{$prefix}{$key} is a hash, then get info from $config{sensitive}{$prefix}{$key}{$execute{env}}
sub getSensInfo ($$) {
my ($prefix,$key) = @_;
# depending on queried key being a ref to hash, get the environment lookup hash key value or the value directly
return (ref($config{sensitive}{$prefix}{$key}) eq "HASH" ? $config{sensitive}{$prefix}{$key}{$execute{env}} : $config{sensitive}{$prefix}{$key});
}
# setupConfigMerge creates cascading inheritance of config/DB/File/FTP/process/task settings
sub setupConfigMerge {
my $logger = get_logger();
for (@commonCoreConfig) {
# fill missing keys in order to avoid Can't use an undefined value as a HASH reference errors in hash config merging later
$common{$_} = {} if !defined($common{$_});
$config{$_} = {} if !defined($config{$_});
$opt{$_} = {} if !defined($opt{$_});
}
# check for unintended merging/inheritance into sections of loads defined with underscore (inheritance prevention)
for my $check (0..$#loads) {
for my $hashName (@allConfig) {
if (defined($loads[$check]{$hashName."_"})) {
# first write the $hashName."_" values into the normal config hash...
for my $defkey (keys %{$loads[$check]{$hashName."_"}}) {
$loads[$check]{$hashName}{$defkey} = $loads[$check]{$hashName."_"}{$defkey};
}
for my $defkey (keys %{$common{$hashName}}) {
lib/EAI/Common.pm view on Meta::CPAN
if ($execute{envraw}) {
$logger->error("no errmailaddress found, no entry found in \$config{testerrmailaddress}".longmess());
} else {
$logger->error("no errmailaddress found for ".$extendedScriptname.", no entry found in \$config{checkLookup}{$extendedScriptname}".longmess());
}
}
setErrSubject("Setting up EAI::Wrap"); # general context after logging initialization: setup of EAI::Wrap by script
} else {
# remove any defined mail appenders
undef(Log::Log4perl->appenders()->{"MAIL"}) if Log::Log4perl->appenders()->{"MAIL"};
}
}
# set up EAI configuration
sub setupEAIWrap {
my $logger = get_logger();
setupConfigMerge(); # %config (from site.config, amended with command line options) and %common (from process script, amended with command line options) are merged into %common and all @loads (amended with command line options)
# starting log entry: process script name + %common parameters, used for process monitoring (%config is not written due to sensitive information, $execute is stripped down to standard keys to avoid potentially sensitve information there as well)
$logger->info("==============================================================================================");
$execute{startingTime} = get_curtime("%02d%02d%02d");
my %executeDump; my %configDump;
for my $key (keys %{$hashCheck{execute}}) {
$executeDump{$key} = $execute{$key};
}
for my $key (keys %config) {
$configDump{$key} = $config{$key} if $key ne "sensitive";
}
$logger->info("started $execute{scriptname} in $execute{homedir} (environment $execute{env}) ... execute parameters: ".dumpFlat(\%executeDump,1,1)." ... common parameters: ".dumpFlat(\%common,1,1));
if ($logger->is_debug) {
$logger->debug("config parameters: ".dumpFlat(\%configDump,1,1));
$logger->debug("load $_ parameters: ".dumpFlat($loads[$_],1,1)) for (0..$#loads);
}
# check starting conditions and exit if met (returned true)
checkStartingCond(\%common) and exit 0;
setErrSubject("General EAI::Wrap script execution"); # general context after setup of EAI::Wrap
}
# returned Data::Dumpered datastructure given in $arg flattened, sorted (if $sortDump given) and compressed (if $compressDump given)
sub dumpFlat ($;$$) {
my ($arg, $sortDump, $compressDump) = @_;
$Data::Dumper::Indent = 0; # temporarily flatten dumper output for single line
$Data::Dumper::Sortkeys = 1 if $sortDump; # sort keys to get outputs easier to read
$Data::Dumper::Deepcopy = 1;
my $dump = Dumper($arg);
if ($compressDump) {
$dump =~ s/\s+//g;$dump =~ s/,'/,/g;$dump =~ s/{'/{/g;$dump =~ s/'=>/=>/g; # compress information
}
$dump =~ s/\$VAR1//;
$Data::Dumper::Indent = 2;
$Data::Dumper::Deepcopy = 0;
return $dump;
}
# check starting conditions and return 1 if met
sub checkStartingCond ($) {
my ($arg) = @_;
my $logger = get_logger();
my ($task) = extractConfigs("checking starting conditions",$arg,"task");
my $curdate = get_curdate();
$logger->debug("checkStartingCond for \$curdate: $curdate, task config:".dumpFlat($task,1));
# skipHolidays is either a calendar or 1 (then defaults to $task->{skipHolidaysDefault})
my $holidayCal = $task->{skipHolidays} if $task->{skipHolidays};
# skipForFirstBusinessDate is for "wait with execution for first business date", either this is a calendar or 1 (then calendar is skipHolidaysDefault), this cannot be used together with skipHolidays
$holidayCal = $task->{skipForFirstBusinessDate} if $task->{skipForFirstBusinessDate};
# default setting (1 becomes $task->{skipHolidaysDefault})
$holidayCal = $task->{skipHolidaysDefault} if ($task->{skipForFirstBusinessDate} eq "1" or $task->{skipHolidays} eq "1");
if ($holidayCal) {
if (is_holiday($holidayCal,$curdate) and !$task->{redoFile}) {
$logger->info("skip processing (skipHolidays = ".$task->{skipHolidays}.", skipForFirstBusinessDate = ".$task->{skipForFirstBusinessDate}.") as $curdate holiday in $holidayCal !");
return 1;
}
}
if (($task->{skipWeekends} or $task->{skipForFirstBusinessDate}) and is_weekend($curdate) and !$task->{redoFile}) {
$logger->info("skip processing (skipWeekends = ".$task->{skipWeekends}.", skipForFirstBusinessDate = ".$task->{skipForFirstBusinessDate}.") as $curdate is day of weekend !");
return 1;
}
# if there are were any business days (meaning that nonBusinessDays are less than calendar days) since the 1st of the month, then skip if $task->{skipForFirstBusinessDate}
if ($task->{skipForFirstBusinessDate} and !$task->{redoFile}) {
my $nonBusinessDays;
my $daysfrom1st = substr($curdate,-2)-1; # get the first decimal from day part of today, this is the number of days from the 1st
# count non business days since the 1st of the month
for (1..$daysfrom1st) {
$nonBusinessDays += (is_weekend(subtractDays($curdate,$_)) or is_holiday($holidayCal,subtractDays($curdate,$_)));
}
$logger->debug("\$nonBusinessDays: $nonBusinessDays,\$daysfrom1st: $daysfrom1st");
if ($nonBusinessDays < $daysfrom1st) {
$logger->info("skip processing (skipForFirstBusinessDate = ".$task->{skipForFirstBusinessDate}.") as processing already took place on a business day before $curdate!");
return 1;
}
}
# if notest file exists, then exit here if not set to ignore that...
if (!$task->{ignoreNoTest} and -e "notest") {
$logger->info("skip processing, because notest set (file exists).");
return 1;
}
return 0;
}
# general mail sending for notifying of conditions/sending reports (for use in user specific code)
sub sendGeneralMail ($$$$$$;$$$$$) {
my ($From, $To, $Cc, $Bcc, $Subject, $Data, $Type, $Encoding, $AttachType, $AttachFile, $enforceToAddressInTest) = @_;
my $logger = get_logger();
$logger->error("cannot send mail as \$config{smtpServer} not set".longmess()) if !$config{smtpServer};
$logger->info("sending general mail From:".($From ? $From : $config{fromaddress}).", To:".($execute{envraw} && !$enforceToAddressInTest ? $config{testerrmailaddress} : $To).", CC:".($execute{envraw} ? "" : $Cc).", Bcc:".($execute{envraw} ? "" : $Bcc...
$logger->debug("Mailbody: $Data");
my $msg = MIME::Lite->new(
From => ($From ? $From : $config{fromaddress}),
To => ($execute{envraw} && !$enforceToAddressInTest ? $config{testerrmailaddress} : $To),
Cc => ($execute{envraw} ? "" : $Cc),
Bcc => ($execute{envraw} ? "" : $Bcc),
Subject => ($execute{envraw} ? $execute{envraw}.": " : "").$Subject,
Type => ($Type ? $Type : "TEXT"),
Data => ($Type eq 'multipart/related' ? undef : $Data),
Encoding => ($Type eq 'multipart/related' ? undef : $Encoding),
);
$logger->error("couldn't create msg for mail sending..".longmess()) unless $msg;
if ($Type eq 'multipart/related') {
if (ref($AttachFile) ne 'ARRAY') {
$logger->error("argument $AttachFile needs to be ref to array for type multipart/related".longmess());
return 0;
}
if (!$AttachType) {
$logger->error("no AttachType given for type multipart/related".longmess());
return 0;
}
$msg->attach(
Type => 'text/html',
Data => $Data,
Encoding => $Encoding
);
for (@$AttachFile) {
$msg->attach(
Encoding => 'base64',
Type => $AttachType,
Path => $_,
Id => $_,
);
( run in 1.480 second using v1.01-cache-2.11-cpan-98e64b0badf )