Test.EmailServerProfileANDMailbox.psm1

##__________This Module Test Email Server Profile and mailbox in Dynamics 365 CRM instance___________##
##_____________________________________Author : YASH GUPTA (YG)______________________________________##



#This function is used to send email at higher priority of failed mailbox details to the User.
function Send-EmailToNotifyError{
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [parameter(Mandatory=$false)]
        [string] $loc,
        [parameter(Mandatory=$true)]
        [string] $EmailTo,
        [parameter(Mandatory=$true)]
        [string] $SMTPServer,
        [parameter(Mandatory=$true)]
        [int] $SMTPPort,
        [parameter(Mandatory=$true)]
        [string] $EnvName,
        [parameter(Mandatory=$true)]
        [string] $MailboxName
        )
    try{
        #Subject, Body and SMTP Details
        $Subject = (Get-Date).ToString('MM-dd-yyyy hh:mm:ss') + " Alert: Mailbox Status failure in "+ $EnvName

        $StoredSMTPCredential = Get-StoredCredential -Target SMTPLogin -AsCredentialObject
        If (!$StoredSMTPCredential)
        {
            $psCred = Get-Credential -Message "Enter your EmailID and Password"
            $cre = New-StoredCredential -Target SMTPLogin -Credentials $psCred -Persist LocalMachine
            $StoredSMTPCredential = Get-StoredCredential -Target SMTPLogin
            }
        $SMTPAuthUsername = $StoredSMTPCredential.UserName
        $SMTPAuthPassword = $StoredSMTPCredential.Password

        $EmailFrom = $SMTPAuthUsername
        $Body = "Dear Tester,
The Mailbox "
 + $MailboxName +" if failed on " +(Get-Date).ToString('MM-dd-yyyy hh:mm:ss') + " Please find Attachment of Mailbox Status History.
 
NOTE: This is an autogenerated mail. Please do not reply.
 
Thanks and Regards,
Administrator"

        $mailmessage = New-Object system.net.mail.mailmessage
        $mailmessage.from = ($EmailFrom)
        $mailmessage.To.add($EmailTo)
        $mailmessage.Subject = $Subject
        $mailmessage.Body = $Body
        $mailmessage.Priority = [System.Net.Mail.MailPriority]::High
        $attachment = New-Object System.Net.Mail.Attachment($loc1)
        $mailmessage.Attachments.Add($attachment)
        $SMTPClient = New-Object Net.Mail.SmtpClient("$SMTPServer", "$SMTPPort")
        $SMTPClient.Credentials = New-Object System.Net.NetworkCredential("$SMTPAuthUsername", "$SMTPAuthPassword")
        $SMTPClient.Send($mailmessage)
        Write-Host Email Send Successfully to $EmailTo
        }
    catch{
        Write-Host An Error Has Ocuured $_.Exception.Message
        }

<#
.SYNOPSIS
  
This function is used to send Email if anything goes wrong in mailbox.
  
.DESCRIPTION
  
Author : Yash Gupta(YG).
This function is automatically triggered by Test-Mailbox.
This function is a parameterised function.
You should pass arguments to the function using Named parametered.
The credentials will be saved in Window's Credential Manager.
  
.OUTPUTS
  
Send Email
 
#>

    }


#This function is used get last tested date of mailbox.
function Get-MailboxLastTestDate{
    [CmdletBinding(SupportsShouldProcess)]
    PARAM(
        [parameter(Mandatory=$true)]
        [string] $MailboxName
        )
    $result = Get-CrmRecords -EntityLogicalName mailbox -FilterAttribute name -FilterOperator eq $MailboxName -Fields testmailboxaccesscompletedon
    $value = foreach($j in $result.CrmRecords){$j.testmailboxaccesscompletedon}
    return $value

<#
.SYNOPSIS
  
This function is used to get last test date and time of mailbox.
  
.DESCRIPTION
  
Author : Yash Gupta(YG).
This function is tiggered by Test-Mailbox.
 
#>

    }


#This function is used get the status of mailbox and save the details in csv file.
function Test-Mailbox{
#.ExternalHelp Test.EmailServerProfileANDMailbox.help.xml
    [CmdletBinding(SupportsShouldProcess)]
    PARAM(
        [parameter(Mandatory=$true)]
        [string]$MailboxName,
        [parameter(Mandatory=$true)]
        [string]$URL,
        [parameter(Mandatory=$true)]
        [string]$ServerProfileName,
        [parameter(Mandatory=$true)]
        [string]$DataFilepath,
        [parameter(Mandatory=$true)]
        [string]$EmailTo,
        [parameter(Mandatory=$true)]
        [string]$SMTPServer,
        [parameter(Mandatory=$true)]
        [int]$SMTPPort
        )
    try{

        #Checking Required Module
        $PackageArray = "CredentialManager","Microsoft.Xrm.Data.Powershell"
        foreach($i in $PackageArray){
            Write-Host Intalling required Modules.
            if(Get-Module -ListAvailable -Name $i){
                }
            else{
                Install-Module -Name $i -Force
                }
            }

        $StoredCredential = Get-StoredCredential -Target PowershellLogin
        If(!$StoredCredential) {
            $psCred = Get-Credential -Message "Enter your Credential for Dynamics 365 Environment"
            $strcred = New-StoredCredential -Target PowershellLogin -Credentials $psCred -Persist LocalMachine
            $StoredCredential = Get-StoredCredential -Target PowershellLogin
            }
        $trgtUserName = $StoredCredential.UserName
        $trgtPass = $StoredCredential.Password
        $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $trgtUserName, $trgtPass

        #________________________Connecting CRM______________________
        Write-Host Connecting to CRM/CDS...
        $trgtCRMOrg = Connect-CrmOnline -Credential $cred -ServerUrl $URL
        Write-Host Connected to Dynamics 365 $URL

        $result = Get-CrmRecords -EntityLogicalName mailbox -FilterAttribute name -FilterOperator eq $MailboxName -Fields name,mailboxid
        $value = foreach($j in $result.CrmRecords){$j.name;$j.mailboxid.Guid}

        $Oldvalue = Get-MailboxLastTestDate -MailboxName $j.name

        #Test and enabling the mailbox
        Set-CrmRecord -conn $trgtCRMOrg -EntityLogicalName mailbox -Id $j.mailboxid.Guid -Fields @{testemailconfigurationscheduled=$true}
        Write-Host The Mailbox has been Tested and Enabled. Please wait...
        Start-Sleep 1

        $Newvalue = Get-MailboxLastTestDate -MailboxName $j.name

        #Checking last tested date and time for mailbox
        while($Oldvalue.Equals($Newvalue)){
            Start-Sleep 4
            $Newvalue = Get-MailboxLastTestDate -MailboxName $j.name
            }

        Write-Host The Mailbox is Tested and Enabled.

 #Fetch XML on Entity Mailbox Details
$fetchXml = @"
<fetch>
  <entity name="mailbox" >
    <attribute name="incomingemailstatus" />
    <attribute name="outgoingemailstatus" />
    <attribute name="averagetotalduration" />
    <attribute name="mailboxstatus" />
    <attribute name="name" />
    <attribute name="emailserverprofile" />
    <attribute name="mailboxid" />
    <attribute name="statuscode" />
    <attribute name="emailrouteraccessapproval" />
    <attribute name="isemailaddressapprovedbyo365admin" />
    <attribute name="testemailconfigurationscheduled" />
    <attribute name="testmailboxaccesscompletedon" />
    <filter>
      <condition attribute="name" operator="eq" value="$MailboxName" />
    </filter>
  </entity>
</fetch>
"@


        $FetchResult = Get-CrmRecordsByFetch -conn $trgtCRMOrg -Fetch $fetchXml -AllRow
            $CheckServerProfile = foreach($i in $FetchResult.CrmRecords){
                if(!($i.emailserverprofile).Equals($ServerProfileName)){
                    [System.Windows.MessageBox]::Show("The mailbox " +$MailboxName+ " is not present in " +$ServerProfileName+"",'No Result Found','Ok','warning')
                    exit
                    }
                }    

        Write-Host Mailbox Status is retrieved from $URL

        #Creating Tablubar format to store in CSV File
        $tableEntity = New-Object system.Data.DataTable "MailboxStaus"
        $tblcol1 = New-Object system.Data.DataColumn Date, ([string])
        $tblcol2 = New-Object system.Data.DataColumn Name, ([string])
        $tblcol3 = New-Object system.Data.DataColumn Incoming_Email_Status, ([string])
        $tblcol4 = New-Object system.Data.DataColumn Outgoing_Email_Status, ([string])
        $tblcol5 = New-Object system.Data.DataColumn Status_Code, ([string])
        $tblcol6 = New-Object system.Data.DataColumn Mailbox_Status, ([string])
        $tblcol7 = New-Object system.Data.DataColumn Average_Total_Duration, ([string])
        $tblcol8 = New-Object system.Data.DataColumn Email_Router_Access_Approval, ([string])
        $tblcol9 = New-Object system.Data.DataColumn IsEmailAddressApprovedbyo365Admin, ([string])
        $tblcol10 = New-Object system.Data.DataColumn Test_Emailconfigurationscheduled, ([string])
        $tblcol11 = New-Object system.Data.DataColumn Test_Mailboxaccesscompletedon, ([string])
        $tableEntity.columns.add($tblcol1)
        $tableEntity.columns.add($tblcol2)
        $tableEntity.columns.add($tblcol3)
        $tableEntity.columns.add($tblcol4)
        $tableEntity.columns.add($tblcol5)
        $tableEntity.columns.add($tblcol6)
        $tableEntity.columns.add($tblcol7)
        $tableEntity.columns.add($tblcol8)
        $tableEntity.columns.add($tblcol9)
        $tableEntity.columns.add($tblcol10)
        $tableEntity.columns.add($tblcol11)
        $FetchResult = Get-CrmRecordsByFetch -conn $trgtCRMOrg -Fetch $fetchXml -AllRows
        #$solutionEntity = New-Object System.Collections.Generic.List[Guid]

        $FetchResult.CrmRecords | ForEach-Object{
            $tblrow = $tableEntity.NewRow()
            $tblrow.Date = (Get-Date).ToString('MM-dd-yyyy hh:mm:ss')
            $tblrow.Name = $_.name
            $tblrow.Incoming_Email_Status = $_.incomingemailstatus
            $tblrow.Outgoing_Email_Status = $_.outgoingemailstatus
            $tblrow.Status_Code = $_.statuscode
            $tblrow.Mailbox_Status = $_.mailboxstatus
            $tblrow.Average_Total_Duration = $_.averagetotalduration
            $tblrow.Email_Router_Access_Approval = $_.emailrouteraccessapproval
            $tblrow.IsEmailAddressApprovedbyo365Admin = $_.isemailaddressapprovedbyo365admin
            $tblrow.Test_Emailconfigurationscheduled = $_.testemailconfigurationscheduled
            $tblrow.Test_Mailboxaccesscompletedon = $_.testmailboxaccesscompletedon
            $tableEntity.Rows.Add($tblrow)

            $FetchResult = Get-CrmRecordsByFetch -conn $trgtCRMOrg -Fetch $fetchXml -AllRow
            $result = foreach($i in $FetchResult.CrmRecords){
                $i.name
                $i.mailboxid.Guid
                $i.testemailconfigurationscheduled
                $i.testmailboxaccesscompletedon
                }
            }

        #Exporting Data in CSV File
        $tableEntity | Export-Csv -NoTypeInformation -Path $DataFilepath -Append
        Write-Host The Mailbox Status is exported.
        " " | Add-Content $DataFilepath

        if($tblrow.Name -eq $MailboxName){
            if(($tblrow.Incoming_Email_Status -eq "Failure") -or ($tblrow.Outgoing_Email_Status -eq "Failure") -or ($tblrow.Status_Code -eq "Inactive") -or ($tblrow.Mailbox_Status -eq "Not Run") -or ($tblrow.Mailbox_Status -eq "Failure") -or ($tblrow.Email_Router_Access_Approval -eq "Empty") -or ($tblrow.IsEmailAddressApprovedbyo365Admin -eq "No") -or ($tblrow.Outgoing_Email_Status -eq "Not Run") -or ($tblrow.Incoming_Email_Status -eq "Not Run")){
                Write-Host Something went wrong in mailbox. Please Check your mail for more details.
                Send-EmailToNotifyError -loc $DataFilepath -EmailTo $EmailTo -SMTPServer $SMTPServer -SMTPPort $SMTPPort -EnvName $trgtCRMOrg.ConnectedOrgFriendlyName -MailboxName $MailboxName
                }
            }
        }
    catch{
        Write-Host An Error has occured $_.Exception.Message
        }

<#
.SYNOPSIS
  
This function is used to check Status Mailbox.
  
.DESCRIPTION
  
Author : Yash Gupta(YG).
This function triggered by Get-EmailServerProfile
This function is a parameterised function.
You should pass arguments to the function using Named parametered.
The credentials will be saved in Window's Credential Manager.
  
.OUTPUTS
  
Create CSV file in same folder where script is saved. Send Email to given Email Id.
  
.EXAMPLE
  
Test-Mailbox -MailboxName $MialboxName -URL $URL -EmailTo $EmailTo -ServerProfileName $ServerProfileName -DataFilepath $DataFilepath -SMTPServer $SMTPServer -SMTPPort $SMTPPort
.EXAMPLE
  
Test-Mailbox -MailboxName "Mailbox Name" - URL "http:\\example.dynamics.crm8.com" -EmailTo "someone@domain.com" -ServerProfileName "Server Profile Name" -DataFilePath "C:\Test.EmailServerProfileANDMailbox\Mailbox Status.csv" -SMTPServer "SMTP Server Name" -SMTPPort 25
#>

 }


#This function is used get details of Email Server profile and notify if it is Inactivate.
function Test-EmailServerProfile{
# .ExternalHelp Test.EmailServerProfileANDMailbox.help.xml
    [CmdletBinding(SupportsShouldProcess)]
    PARAM(
        [parameter(Mandatory=$true)]
        [string]$ServerProfileName,
        [parameter(Mandatory=$true)]
        [string]$URL,
        [parameter(Mandatory=$true)]
        [string]$DataFilepath,
        [parameter(Mandatory=$true)]
        [string]$EmailTo,
        [parameter(Mandatory=$true)]
        [string]$SMTPServer,
        [parameter(Mandatory=$true)]
        [int]$SMTPPort
        )
    try{
    #Checking Required Module
    $PackageArray = "CredentialManager","Microsoft.Xrm.Data.Powershell"
    foreach($i in $PackageArray){
        Write-Host Intalling required Modules.
        if(Get-Module -ListAvailable -Name $i){
            }
        else{
            Install-Module -Name $i -Force
            }
        }
    $StoredCredential = Get-StoredCredential -Target PowershellLogin
    If(!$StoredCredential) {
        $psCred = Get-Credential -Message "Enter your Credentials for Dynamics 365 Environment"
        $strcred = New-StoredCredential -Target PowershellLogin -Credentials $psCred -Persist LocalMachine
        $StoredCredential = Get-StoredCredential -Target PowershellLogin
        }
    $trgtUserName = $StoredCredential.UserName
    $trgtPass = $StoredCredential.Password
    $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $trgtUserName, $trgtPass

    #________________________Connecting CRM______________________
    Write-Host Connecting to CRM/CDS...
    $trgtCRMOrg = Connect-CrmOnline -Credential $cred -ServerUrl $URL
    Write-Host Connected to Dynamics 365 $URL

#Fetching Email Server Profile Details
$fetchXml = @"
<fetch>
<entity name="emailserverprofile" >
<attribute name="name" />
<attribute name="statecode" />
<attribute name="statuscode" />
<filter>
<condition attribute="name" operator="eq" value="$ServerProfileName" />
</filter>
</entity>
</fetch>
"@


    $FetchResult = Get-CrmRecordsByFetch -conn $trgtCRMOrg -Fetch $fetchXml -AllRow
    $result = foreach($i in $FetchResult.CrmRecords){
        $i.name
        $i.statecode
        $i.statuscode
        }
    if($i.statecode.Equals("Inactive") -and $i.statuscode.Equals("Inactive")){
        [System.Windows.MessageBox]::Show('Email Server profile is not Active','Not Active','Ok','warning')
        break
        }
    else{
        Write-Host Email Server Profile is Activated.
        $MialboxName = Read-Host "Which Mailbox's status are you looking for?"
        Test-Mailbox -MailboxName $MialboxName -URL $URL -ServerProfileName $ServerProfileName -DataFilepath $DataFilepath -EmailTo $EmailTo -SMTPServer $SMTPServer -SMTPPort $SMTPPort
        }
    }
    catch{
        Write-Host An Error has occured $_.Exception.Message
    }

<#
.SYNOPSIS
  
This function is used to get Status Email Server Profile and linked Mailbox and will notify if anything goes wrong.
  
.DESCRIPTION
  
Author : Yash Gupta(YG).
This function is a parameterised function.
You should pass arguments to the function using Named parametered.
The credentials will be saved in Window's Credential Manager.
  
.OUTPUTS
  
Ask for mailbox name, Create CSV file in same folder where script is saved, Send Email to given Email Id.
  
.EXAMPLE
  
Test-EmailServerProfile -ServerProfileName $ServerProfileName -URL $URL -DataFilepath $DataFilepath -EmailTo $EmailTo -SMTPServer $SMTPServer -SMTPPort $SMTPPort
.EXAMPLE
  
Test-EmailServerProfile -ServerProfileName "Server Profile Name -URL "https:\\example.crm8.dynamics.com" -DataFilepath "C:\Test.EmailServerProfileANDMailbox\Mailbox Status.csv" -EmailTo "someone@domain.com" -SMTPServer "SMTP Server" -SMTPPort 25
#>

}


#This function is used to test incoming and outgoing mail to and from Mailbox ID respectively.
function SendReceiveMail-Mailbox{
# .ExternalHelp Test.EmailServerProfileANDMailbox.help.xml
    [CmdletBinding(SupportsShouldProcess)]
    PARAM(
        [parameter(Mandatory=$true)]
        [string]$MailboxEmailId,
        [parameter(Mandatory=$true)]
        [string]$TestEmailId,
        [parameter(Mandatory=$true)]
        [int]$PortForTestEmailId,
        [parameter(Mandatory=$true)]
        [string]$SMTPServerForTestEmailId,
        [parameter(Mandatory=$true)]
        [int]$PortForMailboxEmailId,
        [parameter(Mandatory=$true)]
        [string]$SMTPServerForMailboxEmailId
    )
    try{
        $ToMailbox = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password for TestEmail ID.", "", "NetBiosUserName")
        Send-MailMessage -From $TestEmailId -Subject "Test Subject to check incoming" -To $MailboxEmailId -Body "Test Body From PowerShell" -Credential $ToMailbox -Port $PortForTestEmailId -SmtpServer $SMTPServerForTestEmailId
        Write-Host Email Send Successfully to $MailboxEmailId from $TestEmailId

        $FromMailbox = $host.ui.PromptForCredential("Need credentials", "Please enter your user name and password for Mailbox ID.", "", "NetBiosUserName")
        Send-MailMessage -From $MailboxEmailId -Subject "Test Subject to check outgoing" -To $TestEmailId -Body "Test Body From PowerShell" -Credential $FromMailbox -Port $PortForMailboxEmailId -SmtpServer $SMTPServerForMailboxEmailId
        Write-Host Email Send Successfully to $TestEmailId from $MailboxEmailId
    }
    catch{
        Write-Host An Error has occured $_.Exception.Message
    }

<#
.SYNOPSIS
This Cmdlet will test the mailbox by sending and receiving the email to and from mailbox respectively.
  
.DESCRIPTION
Author : Yash Gupta(YG).
This function is a parameterised function.
You should pass arguments to the function using Named parametered.
  
.OUTPUTS
Send and receive Email to given Email Id.
  
.EXAMPLE
SendReceiveMail-Mailbox -MailboxEmailId $MailboxEmailId -TestEmailId $TestEmailId -PortForTestEmailId $PortForTestEmailId -SMTPServerForTestEmailId $SMTPServerForTestEmailId -PortForMailboxEmailId $PortForMailboxEmailId -SMTPServerForMailboxEmailId $SMTPServerForMailboxEmailId
 
.EXAMPLE
SendReceiveMail-Mailbox -MailboxEmailId "mailbox@domain.com" -TestEmailId "Someone@domain.com" -PortForTestEmailId 25 -SMTPServerForTestEmailId "smtp.domain.com" -PortForMailboxEmailId 25 -SMTPServerForMailboxEmailId "smtp.domain.com"
#>

}