[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$egurkhaPath=(Get-Item Env:EGURKHA_INSTALL_DIR).value.ToString()
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$egEncryPath=$scriptPath+"\EGFileEncryption.psm1"
$egDatnKy=$scriptPath+"\GetDatnKeyFiles.psm1"
Import-Module $egEncryPath,$egDatnKy


$testargs=$args
$userName=$testargs[0]
$Password=Eg-O365Dcr -EncStr $testargs[1]
$proxyUsr=$testargs[2]
$proxyPass=Eg-O365Dcr -EncStr $testargs[3]
$rName=$testargs[4]
if($proxyUsr.toString().toLower().Trim() -eq 'none') { $proxyUsr=$proxyUsr.toString().toLower().Trim() }
if($proxyPass.toString().toLower().Trim() -eq 'none') { $proxyPass=$proxyPass.toString().toLower().Trim() }

$RprtNameAndmTime=$rName.split("#")
$reportingname=$RprtNameAndmTime[0]
$mTime=$RprtNameAndmTime[1]

#--------------------------------------
$domainSpecific=$false
if($reportingname -match '_exd'){
    $domainSpecific=$true
    $alldomainnames=@()
    $dhash=Eg-O635Domains -username $userName -password $Password -rptNam $reportingname -proxyserverip 'none' -proxyUsr $proxyUsr -proxyPass $proxyPass
    $reportingname=$dhash['SupersetName']
    foreach($h in $dhash.Keys){
        if($h -ne 'SupersetName'){
            $alldomainnames+=$h
        }
    }
    $ds_MPTr_Key='';$ds_MPTr_fpth='';$ds_MPTr_nam='';
    $ds_MPMl_Key='';$ds_MPMl_fpth='';$ds_MPMl_nam='';
    $ds_MPSpm_Key='';$ds_MPSpm_fpth='';$ds_MPSpm_nam='';
    $ds_MPMsg_Key='';$ds_MPMsg_fpth='';$ds_MPMsg_nam='';
}
$rptPath='EXO/'+$reportingname
$chkwritPath=$egurkhaPath+'/agent/'+$rptPath
if($domainSpecific){ 
    $isWrite=Check-WriteFile -rptPath $chkwritPath -srchWrd 'EXOMailProtection' -mTimInMin $mTime
}
$isProceed=$false
if($isWrite){
    $isProceed=$true
}elseif($domainSpecific -eq $false){
    $isProceed=$true
}else{
    $isProceed=$false
}
#--------------------------------------

if($isProceed){
    $azureVal=Eg-GetAzureEnv -UserName $userName
    $azureEnvArr=$azureVal.Split(',')
    $ManualThrottle=0
    [double]$ActiveThrottle=.25
    $ResetSeconds=870
    $WriteLog=$true
    $LogFile = $egurkhaPath+'/agent/EXO/'+$reportingname+"\mailprotection.log"
    $LogFile1 = $egurkhaPath+'/agent/EXO/'+$reportingname+"\mailprotection1.log"
    $isFrstTimLog=$true

    # Writes output to a log file with a time date stamp
    Function Write-Log {
	    Param ([string]$string)
	    [string]$date = Get-Date -Format G
        if ($WriteLog) {
           ( "[" + $date + "] - [" + $reportingname+"] mTime -  " + $mTime + " - " + $string ) | Out-File -FilePath $LogFile -Append }
        if($isFrstTimLog){     
            if ($WriteLog -eq $true){ #if flag is true 
                if ([System.IO.File]::Exists($LogFile) -and (Get-Item $LogFile).length -gt 2mb) {  #if the size of file is greater than 1MB 
                    if([System.IO.File]::Exists($LogFile1)){  #if logfile1 already exists, delete logfile1 
                        Remove-Item $LogFile1 
                    } 
                    Rename-Item $LogFile $LogFile1 
                }
            }
            $isFrstTimLog=$false
        }
    }

    Function Start-SleepWithProgress {
	    Param([int]$sleeptime)
	    For ($i=0;$i -le $sleeptime;$i++){
		    $timeleft = ($sleeptime - $i);
		    Write-Progress -Activity "Sleeping" -CurrentOperation "$Timeleft More Seconds" -PercentComplete (($i/$sleeptime)*100);
		    start-sleep 1
	    }
	    Write-Progress -Completed -Activity "Sleeping"
    }

    Function New-CleanO365Session {
        $Credential = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $userName, $(convertto-securestring $Password -asplaintext -force)
        $i = 0
	    while (($Credential -eq $Null) -and ($i -lt 5)){
		    $script:Credential = Get-Credential -Message "Please provide your Exchange Online Credentials"
		    $i++
	    }
	    if ($Credential -eq $null){
		    Write-log "[Error] - Failed to get credentials"
		    Write-Error -Message "Failed to get credentials" -ErrorAction Stop
	    }
	    Write-Log "Removing all PS Sessions"
	    Get-PSSession | Remove-PSSession -Confirm:$false
	    [System.GC]::Collect()
	    Write-Log ("Sleeping 15 seconds for Session Tear Down")
	    Start-SleepWithProgress -SleepTime 15
	    $Error.Clear()
	
	    # Create the session
	    Write-Log "Creating new PS Session"
	    $sessionOption = New-PSSessionOption -SkipRevocationCheck
	    if($proxyUsr -ne 'none' -and $proxyPass -ne 'none'){
	        $proxyCred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $proxyUsr, $(convertto-securestring $proxyPass -asplaintext -force)
	        $sessionOption = New-PSSessionOption -SkipRevocationCheck -ProxyAccessType WinHttpConfig -ProxyAuthentication basic -ProxyCredential $proxyCred
	    }
	    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $azureEnvArr[1] -Credential $Credential -Authentication Basic -AllowRedirection -SessionOption $sessionOption -WarningAction SilentlyContinue
		
	    # Check for an error while creating the session
	    if ($Error.Count -gt 0){
		    Write-Log "[ERROR] - Error while setting up session"
		    Write-log $Error
		    $ErrorCount++
		    if ($ErrorCount -gt 3){
			    Write-log "[ERROR] - Failed to setup session after multiple tries"
			    Write-log "[ERROR] - Aborting Script"
			    exit
		    }
		    Write-Log "Sleeping 60s so that issue can potentially be resolved"
		    Start-SleepWithProgress -sleeptime 60
		    New-CleanO365Session
	    }
	    else{
		    $ErrorCount = 0
	    }
	
	    # Import the PS session
	    $null = Import-PSSession $session -AllowClobber -WarningAction SilentlyContinue -DisableNameChecking
	
	    # Set the Start time for the current session
	    Set-Variable -Scope script -Name SessionStartTime -Value (Get-Date)
    }

    Function Test-O365Session {
	    $ObjectTime = Get-Date
	    $SessionInfo = $null
	    $SessionInfo = Get-PSSession
	    if ($SessionInfo -eq $null) { 
		    Write-Log "[ERROR] - No Session Found"
		    Write-log "Recreating Session"
		    New-CleanO365Session
	    }	
	    elseif ($SessionInfo.State -ne "Opened"){
		    Write-Log "[ERROR] - Session not in Open State"
		    Write-log ($SessionInfo | fl | Out-String )
		    Write-log "Recreating Session"
		    New-CleanO365Session
	    }
	    elseif (($ObjectTime - $SessionStartTime).totalseconds -gt $ResetSeconds){
		    Write-Log ("Session Has been active for greater than " + $ResetSeconds + " seconds" )
		    Write-Log "Rebuilding Connection"
		    [int]$DelayinSeconds = ((($ResetSeconds * $ActiveThrottle) / 2) - 15)
		    if ($DelayinSeconds -gt 0){
			    Write-Log ("Sleeping " + $DelayinSeconds + " addtional seconds to allow throttle recovery")
			    Start-SleepWithProgress -SleepTime $DelayinSeconds
		    }
		    else{
			    Write-Log ("Active Delay calculated to be " + ($DelayinSeconds + 15) + " seconds no addtional delay needed")
		    }
		    New-CleanO365Session
	    }
	    else {
	    }
	    if ($ManualThrottle -gt 0){
		    Write-log ("Sleeping " + $ManualThrottle + " milliseconds")
		    Start-Sleep -Milliseconds $ManualThrottle
	    }
    }

    Function Get-EstimatedTimeToCompletion {
	    param([int]$ProcessedCount)
	    $ProcessedCount++
	    if (($ProcessedCount % 100) -eq 0){
		    $CurrentDate = Get-Date
		    $AveragePerObject = (((($CurrentDate) - $ScriptStartTime).totalseconds) / $ProcessedCount)
		    Write-Log ("[STATS] - Total Number of Objects:     " + $ObjectCount)
		    Write-Log ("[STATS] - Number of Objects processed: " + $ProcessedCount)
		    Write-Log ("[STATS] - Average seconds per object:  " + $AveragePerObject)
		    Write-Log ("[STATS] - Estimated completion time:   " + $CurrentDate.addseconds((($ObjectCount - $ProcessedCount) * $AveragePerObject)))
	    }
	    return $ProcessedCount
    }


    $rptPath='EXO/'+$reportingname
    $MyDir=$egurkhaPath+'/agent/EXO/'+$reportingname
    if(!(Test-Path -Path $MyDir )){
        New-Item -ItemType directory -Path $MyDir
    }
    $isErrorOccur= $false

    $endDat = Get-Date
    $startDat = Get-Date -Hour 00 -Minute 00 -Second 00
    $startDat=$startDat.AddMinutes(-1440)
    $startingDat=$endDat.AddMinutes(-$mTime)

    Set-StrictMode -Version 2
    $ErrorCount = 0
    New-CleanO365Session
    $ScriptStartTime = Get-Date 
     
    try{
        Test-O365Session
        $Error.Clear()
        #$ruledetail   = Get-MailDetailTransportRuleReport |select EventType,MessageSize,Direction,SenderAddress,RecipientAddress,Date,Domain,Subject,MessageId | Where-Object {$_.Date -gt $startDat} | export-csv $transportRules
        $rulePageval=1
        try{
            $Error.Clear()
            $transportRules = Eg-WriteFile -ComntRptPath $rptPath -FileName "transportrules" -keyFileName "ktransportrules" -EgPath $egurkhaPath
            $trnptflag=$true
            while($trnptflag){
	            $ruleCount=0
	            $ruleDetails=Get-MailDetailTransportRuleReport -StartDate $startDat -EndDate $endDat -page $rulePageval -pagesize 5000 |select EventType,MessageSize,Direction,SenderAddress,RecipientAddress,Date,Domain,Subject,MessageId,Action,TransportRule
                $ruleDetails|Export-Csv -Append  -LiteralPath $transportRules[1]
                try{$ruleCount=$ruleDetails.Count}catch{$ruleCount=0}
                Test-O365Session
                if($ruleCount -lt 5000){
                    $trnptflag=$false
                }
                $rulePageval++
            }
        }
        Catch{
            $ErrorMessage = $_.Exception.Message
            write-Log ("ErrorMessage while running   TransportRule Report : "+$ErrorMessage)   
            $isErrorOccur=$true
        } 
        if($isErrorOccur -eq $true -and (Get-Item $transportRules[1]).length -le 2kb){
            write-Log (" Deleting file ErrorMessage while running  TransportRule Report  : "+$Error)  
            Remove-Item $transportRules[1]
            $isErrorOccur=$false
        }else{
            $ds_MPTr_Key=$transportRules[0];$ds_MPTr_fpth=$transportRules[1];$ds_MPTr_nam=$transportRules[2];
            $null=Protect-File  $transportRules[1] -Algorithm AES -KeyAsPlainText $transportRules[0] -RemoveSource
        } 

        Test-O365Session
        $Error.Clear()
        $MalwarePageval=1
        try{
            $Error.Clear()
            $malwareDetails = Eg-WriteFile -ComntRptPath $rptPath -FileName "malware" -keyFileName "kmalware" -EgPath $egurkhaPath
            $malwareflag=$true
            while($malwareflag){
	            $MalwareCount=0
		        $Malwaredata=Get-MailDetailMalwareReport -StartDate $startDat -EndDate $endDat -page $MalwarePageval -pagesize 5000 |select Date,SenderAddress,RecipientAddress,MessageSize,Direction,EventType,MalwareName,FileName
		        $Malwaredata|Export-Csv -Append  -LiteralPath $malwareDetails[1]
                try{$MalwareCount=$Malwaredata.Count }catch{$MalwareCount=0}
                Test-O365Session
                if($MalwareCount -lt 5000){
                    $malwareflag=$false
                }
                $MalwarePageval++
            }
        }Catch{
            $ErrorMessage = $_.Exception.Message
            write-Log ("ErrorMessage while running  Malware Report  : "+$ErrorMessage)   
            $isErrorOccur=$true
        } 
        if($isErrorOccur -eq $true -and (Get-Item $malwareDetails[1]).length -le 200){
            write-Log (" Deleting File ErrorMessage while running  Malware Report : "+$ErrorMessage)  
            Remove-Item $malwareDetails[1]
            $isErrorOccur=$false
        }else{
            $ds_MPMl_Key=$malwareDetails[0];$ds_MPMl_fpth=$malwareDetails[1];$ds_MPMl_nam=$malwareDetails[2];
            $null=Protect-File  $malwareDetails[1] -Algorithm AES -KeyAsPlainText $malwareDetails[0] -RemoveSource
        }

        Test-O365Session
        $SpamPageval=1
        try{
            $Error.Clear()
            $spamDetails = Eg-WriteFile -ComntRptPath $rptPath -FileName "spam" -keyFileName "kspam" -EgPath $egurkhaPath
            $spmflag=$true
            while($spmflag){
	            $spamCount=0
		        $spamdata=Get-MailDetailSpamReport -StartDate $startDat -EndDate $endDat -page $SpamPageval -pagesize 5000 |select -Property @{Name='Current Date';Expression={$endDat}},Date,SenderAddress,RecipientAddress,MessageSize,Direction,EventType,Subject,MessageTraceId,Domain,Organization,MessageId 
		        $spamdata|Export-Csv -Append  -LiteralPath $spamDetails[1]
		        try{$spamCount=$spamdata.Count}catch{$spamCount=0}
                Test-O365Session
                if($spamCount -lt 5000){
                    $spmflag=$false
                }
                $SpamPageval++
            }
        }Catch{
            $ErrorMessage = $_.Exception.Message
            write-Log ("ErrorMessage while running  spam Details : "+$ErrorMessage)   
            $isErrorOccur=$true
        } 
        if($isErrorOccur -eq $true -and (Get-Item $spamDetails[1]).length -le 2kb){
            write-Log ("Deleting file ErrorMessage while running   spam Details : "+$Error)  
            Remove-Item $spamDetails[1]
            $isErrorOccur=$false
        }else{
            $ds_MPSpm_Key=$spamDetails[0];$ds_MPSpm_fpth=$spamDetails[1];$ds_MPSpm_nam=$spamDetails[2];
            $null=Protect-File  $spamDetails[1] -Algorithm AES -KeyAsPlainText $spamDetails[0] -RemoveSource
        } 

        Test-O365Session
        $val=1
        try{
            $Error.Clear()
            $MsgTrace = Eg-WriteFile -ComntRptPath $rptPath -FileName "msgs" -keyFileName "kmsgs" -EgPath $egurkhaPath
            $msgflag=$true
            while($msgflag){
                $count=0
                $output=Get-MessageTrace -StartDate $startingDat -EndDate $endDat -page $val -pagesize 5000 | select-object senderaddress ,RecipientAddress ,FromIP ,ToIP ,Size ,Status, Subject, Received
                $output | Export-Csv -Append  -LiteralPath $MsgTrace[1]
                try{$count=$output.Count}catch{$count=0}
                Test-O365Session
                if($count -lt 5000){
                    $msgflag=$false
                }
                $val++
            }
        }Catch{
            $ErrorMessage = $_.Exception.Message
            write-Log ("ErrorMessage while running  Message Trace : "+$ErrorMessage)   
            $isErrorOccur=$true
        } 
        if($isErrorOccur -eq $true -and (Get-Item $MsgTrace[1]).length -le 2kb){
            write-Log ("Deleting File ErrorMessage while running   Message Trace : "+$Error)  
            Remove-Item $MsgTrace[1]
            $isErrorOccur=$false
        }else{
            $ds_MPMsg_Key=$MsgTrace[0];$ds_MPMsg_fpth=$MsgTrace[1];$ds_MPMsg_nam=$MsgTrace[2];
            $null=Protect-File  $MsgTrace[1] -Algorithm AES -KeyAsPlainText $MsgTrace[0] -RemoveSource
        } 
    }
    catch{
        $ErrorMessage = $_.Exception.Message
        $FailedItem = $_.Exception.ItemName
        write-log "ErrorMessage : " + $ErrorMessage   
        write-log "FailedItem : " + $FailedItem
    } 
    Write-Log "Script Complete Destroying PS Sessions"
    Get-PSSession | Remove-PSSession -Confirm:$false
}

if($domainSpecific){
    #------------- 1.For Domain Specific - transportrules ----------------------
    if($ds_MPTr_fpth -ne ''){
        $mptrFilePth=$ds_MPTr_fpth -replace (".csv",".dat")   
        if((Get-Item -Path $mptrFilePth).Length -gt 2KB){
            $null=Unprotect-File $mptrFilePth -Algorithm AES -KeyAsPlainText $ds_MPTr_Key
            $tpRls= import-csv $ds_MPTr_fpth
            $trnam=$ds_MPTr_nam.ToString()
            foreach($domain in $alldomainnames){
                $isAddContent=$false
                $domainDir=$egurkhaPath+'/agent/EXO/'+$dhash[$domain]
                if(!(Test-Path -Path $domainDir )){
                    New-Item -ItemType directory -Path $domainDir
                }        
                $rptDpth=$domainDir+'/'+$trnam
                foreach($tmpRes in $tpRls){
                    if($tmpRes.Domain -match $domain){
                        $isAddContent=$true
                        $tmpRes| export-csv $rptDpth -Append
                    }
                }
                if($isAddContent){
                    $knam=$trnam.Replace("csv","dat")
                    $kDpth=$domainDir+'/k'+$knam
                    $ds_MPTr_Key|Add-Content $kDpth
                    $null=Protect-File $rptDpth -Algorithm AES -KeyAsPlainText $ds_MPTr_Key -RemoveSource
                }
            }
        }
    }

    #------------- 2.For Domain Specific - malware ----------------------
    if($ds_MPMl_fpth -ne ''){
        $mpmlFilePth=$ds_MPMl_fpth -replace (".csv",".dat")
        if((Get-Item -Path $mpmlFilePth).Length -gt 200){
            $null=Unprotect-File $mpmlFilePth -Algorithm AES -KeyAsPlainText $ds_MPMl_Key
            $mwDtls= import-csv $ds_MPMl_fpth
            $mwnam=$ds_MPMl_nam.ToString()
            foreach($domain in $alldomainnames){
                $isAddContent=$false
                $domainDir=$egurkhaPath+'/agent/EXO/'+$dhash[$domain]
                if(!(Test-Path -Path $domainDir )){
                    New-Item -ItemType directory -Path $domainDir
                }        
                $rptDpth=$domainDir+'/'+$mwnam
                foreach($tmpRes in $mwDtls){
                    if($tmpRes.SenderAddress -match $domain -or $tmpRes.RecipientAddress -match $domain){
                        $isAddContent=$true
                        $tmpRes| export-csv $rptDpth -Append
                    }
                }
                if($isAddContent){
                    $knam=$mwnam.Replace("csv","dat")
                    $kDpth=$domainDir+'/k'+$knam
                    $ds_MPMl_Key|Add-Content $kDpth
                    $null=Protect-File $rptDpth -Algorithm AES -KeyAsPlainText $ds_MPMl_Key -RemoveSource
                }
            }
        }
    }

    #------------- 3.For Domain Specific - spam ----------------------
    if($ds_MPSpm_fpth -ne ''){
        $mpspmFilePth=$ds_MPSpm_fpth -replace (".csv",".dat")
        if((Get-Item -Path $mpspmFilePth).Length -gt 2KB){
            $null=Unprotect-File $mpspmFilePth -Algorithm AES -KeyAsPlainText $ds_MPSpm_Key
            $spmDtls= import-csv $ds_MPSpm_fpth
            $spmnam=$ds_MPSpm_nam.ToString()
            foreach($domain in $alldomainnames){
                $isAddContent=$false
                $domainDir=$egurkhaPath+'/agent/EXO/'+$dhash[$domain]
                if(!(Test-Path -Path $domainDir )){
                    New-Item -ItemType directory -Path $domainDir
                }        
                $rptDpth=$domainDir+'/'+$spmnam
                foreach($tmpRes in $spmDtls){
                    if($tmpRes.Domain -match $domain){
                        $isAddContent=$true
                        $tmpRes| export-csv $rptDpth -Append
                    }
                }
                if($isAddContent){
                    $knam=$spmnam.Replace("csv","dat")
                    $kDpth=$domainDir+'/k'+$knam
                    $ds_MPSpm_Key|Add-Content $kDpth
                    $null=Protect-File $rptDpth -Algorithm AES -KeyAsPlainText $ds_MPSpm_Key -RemoveSource
                }
            }
        }
    }

    #------------- 4.For Domain Specific - msgs ----------------------
     if($ds_MPMsg_fpth -ne ''){
        $mpmsgFilePth=$ds_MPMsg_fpth -replace (".csv",".dat")
        if((Get-Item -Path $mpmsgFilePth).Length -gt 2KB){
            $null=Unprotect-File $mpmsgFilePth -Algorithm AES -KeyAsPlainText $ds_MPMsg_Key
            $mtDtls= import-csv $ds_MPMsg_fpth
            $mtnam=$ds_MPMsg_nam.ToString()
            foreach($domain in $alldomainnames){
                $isAddContent=$false
                $domainDir=$egurkhaPath+'/agent/EXO/'+$dhash[$domain]
                if(!(Test-Path -Path $domainDir )){
                    New-Item -ItemType directory -Path $domainDir
                }        
                $rptDpth=$domainDir+'/'+$mtnam
                foreach($tmpRes in $mtDtls){
                    if($tmpRes.SenderAddress -match $domain -or $tmpRes.RecipientAddress -match $domain){
                        $isAddContent=$true
                        $tmpRes| export-csv $rptDpth -Append
                    }
                }
                if($isAddContent){
                    $knam=$mtnam.Replace("csv","dat")
                    $kDpth=$domainDir+'/k'+$knam
                    $ds_MPMsg_Key|Add-Content $kDpth
                    $null=Protect-File $rptDpth -Algorithm AES -KeyAsPlainText $ds_MPMsg_Key -RemoveSource
                }
            }
        }
    }
}

$csvDir=$egurkhaPath+'/agent/EXO/'+$reportingname+'/'
Eg-DeleteCsvFiles -FilePath $csvDir -Pattern 'transportrules'
Eg-DeleteCsvFiles -FilePath $csvDir -Pattern 'malware'
Eg-DeleteCsvFiles -FilePath $csvDir -Pattern 'spam'
Eg-DeleteCsvFiles -FilePath $csvDir -Pattern 'msgs'