#!/usr/local/bin/perl
# 
# $Header: imap_service_test.pl 06-apr-2007.23:06:54 nsarkar Exp $
#
# imap_service_stat.pl
#  
# Desc : the IMAP service target should be marked as down only if the "connection"
#        and "login" to the IMAP service fails 6 consecutive times ( or a user
#        specifiable property ). The initial version will not let the user to 
#        configure the number of times a failure can be allowed for concerns on
#        using large number. 
# 
# Copyright (c) 2003, 2007, Oracle. All rights reserved.  
#
#    NAME
#      imap_service_stat.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      <short description of component this file declares/defines>
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    nsarkar   04/06/07 - Backport nsarkar_bug-5844308_01 from main
#    nsarkar   01/31/07 - timeout parameter is passed in IMAP connection
#    vesriniv  07/14/05 - fix succss string 
#    fsalim    07/08/05 - fix4478756
#    fsalim    07/04/05 - To return the error status message 
#    tjaiswal  11/12/04 - tjaiswal_test_type_impl
#    vesriniv	 11/02/04 - Updated the result to return Txn name and Beacon name
#    vesriniv	 11/02/04 - Modified instance variables to USER input variables
#    hwjung	     10/25/03 - Bug3206136 - down only if fails 6 consecutive times 
#    gmulchan    07/30/03 - gmulchan_ocsv1_main_merge
#    tjaiswal    04/25/03 - 
#    tjaiswal    04/22/03 - 
#    tjaiswal    04/20/03 - Creation
# 
#use strict;
use Getopt::Long; # set up to accept user input
use Net::IMAP::SimpleConn;
use Time::HiRes;

#imap parameters
GetOptions(\%cmdLine,
            "beaconName=s",
            "txnName=s",
            "retryinterval=i",
            "numretries=i",
            "imap_host=s",
            "imap_port=i",
            "imap_user_name=s",
            "imap_password=s");

my $beaconName = $cmdLine{"beaconName"};
my $txnName = $cmdLine{"txnName"};
my $imap_host = $cmdLine{"imap_host"};
my $imap_port = $cmdLine{"imap_port"};
my $imap_user_name = $cmdLine{"imap_user_name"};
my $imap_password = $cmdLine{"imap_password"};
my $retryinterval = $cmdLine{"retryinterval"};
my $imap_fail_count = $cmdLine{"numretries"};
my $imap_timeout = 270;

#default
$imap_fail_count = 6 unless (exists  $cmdLine{"numretries"});
$retryinterval = 5 unless (exists  $cmdLine{"retryinterval"});

# metrics
######
# $connect_time
# $login_time
# $open_email_time
# $list_folders_time
# $errTxt
####
$total_time = 0;
$connect_time = 0;
$login_time = 0;
$open_email_time = 0;
$list_folders_time = 0;
$errTxt = "Success";

print "Connecting.. $imap_host:$imap_port :: $imap_user_name\n";

# open a connection to the IMAP server

$start_time = Time::HiRes::time();
# the number of failed login try 
$fail_count = 0;

do {
   if( $fail_count >0 )
   {
    sleep $retryinterval;
   }

   $status = check_imap_login();
   $fail_count++;
   print "test count = $fail_count, status = $status\n";
}while ( $fail_count < $imap_fail_count && $status == 0 );

if ( $status == 1 ) 
{
   print "Connect Time = $connect_time\n";
   print "Login Time = $login_time\n";
   print "List Folders Time = $list_folders_time\n";
   print "Open Email Time = $open_email_time\n";
   print "Total Time = $total_time\n";
   printf ("em_result=$txnName|$beaconName|$status|$total_time|$connect_time|$login_time|$open_email_time|$list_folders_time|$errTxt\n");
}
else
{
 printf ("em_result=$txnName|$beaconName|$status|$total_time|$connect_time|$login_time|$open_email_time|$list_folders_time|$errTxt\n");
}
#################################################################
# create sub routine
# return value : 1 - login success
#                0 - login fail
#################################################################
sub check_imap_login {
   # define $l_status as local variable
   my( $l_status );    

   # connect imap server
   $server = Net::IMAP::SimpleConn->new( $imap_host, $imap_port, $imap_timeout);
   
   if ($@) 
   {
      if ($@ =~ /timeout/) 
      {
          $errTxt = "IMAP connection is timed out";
          print "Connection failed\n";
          $l_status = 0;   
          return $l_status;
      } 
          
   }

   # if connection is succeed
   if ($server) 
   {
       $l_status = 1;
       $connect_time = Time::HiRes::time() - $start_time;
   
       # login, by default selects INBOX
       $start_time = Time::HiRes::time();

       $num_messages = $server->login( $imap_user_name, $imap_password );
       print "Number of messages in the inbox = $num_messages\n";
       $login_time = Time::HiRes::time() - $start_time;

       # decide if this is a metric error or just l_status = down ?
       if (! defined  ($num_messages))
       {
	   $errTxt = "Login Failed - Please check the username and password";
           # regard this as l_status down
           print "Login failed\n";
           $l_status = 0;
       } else {
          # Read the first message
          $start_time = Time::HiRes::time();
          $lines = $server->get( 1 );
          $open_email_time = Time::HiRes::time() - $start_time;
   
          # the list of all folders
          $start_time = Time::HiRes::time();
          @folders = $server->mailboxes();
          for ($i=0; $i < @folders; $i++)
          { 
              #print "$folders[$i]\n";
          }
          $list_folders_time = Time::HiRes::time() - $start_time;
      
          # close the connection
          $server->quit();
   
          $total_time = $connect_time + $login_time + $open_email_time + 
          $list_folders_time;
   
          # Important : Convert to milliseconds.
          $connect_time = toMilliSec($connect_time) ;
          $login_time = toMilliSec($login_time);
          $list_folders_time = toMilliSec($list_folders_time) ;
          $open_email_time = toMilliSec($open_email_time) ;   
          $total_time = toMilliSec($total_time); 
      
      } # end of login fail
   } 
   else 
   {   # fail to connect imap
      $errTxt = "Could not connect to imap server, please check machine name and port number";
      print "Connection failed\n";
      $l_status = 0;
   }

   return $l_status
} # end of check_imap_login

sub toMilliSec 
{
    my ( $time_in_sec) = @_;
    return $time_in_sec * 1000;
}

