PowerShell SMTPSERVER help

I have many power shell scripts on my servers that report to me status

I have Exchange 2016 CU10 DAG setup 2 NODES

My scripts all point to NODE 1 but when I take down NODE 1 for maintenance No email is received. thru NODE 2 I changed the script to point to NODE 2 and it works great.

How can I automatically switch from NODE 1 to NODE 2?

Here is a sample script I use.

$Server = hostname
$Subject = “$Server Delete VSS Report”
$Body = “Open attachment for Delete VSS Report”
$From = “no-reply@mynet.com
$To = “systems-alert@mynet.com
$LogFolder = “c:\util\logs”
$LogFile = “vss.txt”

remove-item -path $LogFolder$LogFile -Force

vssadmin list shadows >>$LogFolder$LogFile
vssadmin delete shadows /all /quiet >>$LogFolder$LogFile
vssadmin list shadows >>$LogFolder$LogFile

$PSEmailServer = “SERV021-N1.MYNET.COM
Send-MailMessage -From $From -To $To -Subject $Subject -Body $Body -smtpserver $PSEmailServer -attachment “$LogFolder$LogFile”

SERV021-N2.MYNET.COM IS NODE 2

Thank you

Tom

 

 

You could detect the availability of the two servers and make a decision which to use for Hostname

$Mailservers = @("HOST1","HOST2")
if (Test-Connection -ComputerName $Mailservers[0] -Count 1 -Quiet) {
    # first Server is UP
    $Nailserver = $Mailservers[0]
}
elseif (Test-Connection -ComputerName $Mailservers[1] -Count 1 -Quiet) {
    # second server is UP
    $Mailserver = $Mailservers[1]
 } else {
     Write-Error "No Mailservers Available"
 }

Schlauge,

Thanks for the fast reply.

That’s a good start.

 

I should have mentioned that both server are up and running. When I meant it was in Maint Mode it is applying upgrades to Exchange.

I need a check that will detect the Exchange Server is in Maint mode.

Thoughts?

 

How do you determine the state where you would consider the Exchange server in MaintMode? Are you running another script, externally, tp place the Exchange server into Maintenance. That should point you in the right direction.

I’m not an Exchange guy, but I found this with a quick search.
Get-ServerComponentState
or
Exchange Maintenance Mode

Schlauge

the output of the Get-servercomponetstate is

 
[PS] C:\Windows\system32>get-servercomponentstate -Identity SERV021-N1
 

 
Server Component State
 


 
SERV021-N1.mynet.com ServerWideOffline Active
 
SERV021-N1.mynet.com HubTransport Active
 
SERV021-N1.mynet.com FrontendTransport Active
 
SERV021-N1.mynet.com Monitoring Active
 
SERV021-N1.mynet.com RecoveryActionsEnabled Active
 
SERV021-N1.mynet.com AutoDiscoverProxy Active
 
SERV021-N1.mynet.com ActiveSyncProxy Active
 
SERV021-N1.mynet.com EcpProxy Active
 
SERV021-N1.mynet.com EwsProxy Active
 
SERV021-N1.mynet.com ImapProxy Active
 
SERV021-N1.mynet.com OabProxy Active
 
SERV021-N1.mynet.com OwaProxy Active
 
SERV021-N1.mynet.com PopProxy Active
 
SERV021-N1.mynet.com PushNotificationsProxy Active
 
SERV021-N1.mynet.com RpsProxy Active
 
SERV021-N1.mynet.com RwsProxy Active
 
SERV021-N1.mynet.com RpcProxy Active
 
SERV021-N1.mynet.com UMCallRouter Active
 
SERV021-N1.mynet.com XropProxy Active
 
SERV021-N1.mynet.com HttpProxyAvailabilityGroup Active
 
SERV021-N1.mynet.com ForwardSyncDaemon Inactive
 
SERV021-N1.mynet.com ProvisioningRps Inactive
 
SERV021-N1.mynet.com MapiProxy Active
 
SERV021-N1.mynet.com EdgeTransport Active
 
SERV021-N1.mynet.com HighAvailability Active
 
SERV021-N1.mynet.com SharedCache Active
 
SERV021-N1.mynet.com MailboxDeliveryProxy Active
 
SERV021-N1.mynet.com RoutingUpdates Active
 
SERV021-N1.mynet.com RestProxy Active
 
SERV021-N1.mynet.com DefaultProxy Active
 
SERV021-N1.mynet.com Lsass Active
 
SERV021-N1.mynet.com RoutingService Active
 
SERV021-N1.mynet.com E4EProxy Active
 
SERV021-N1.mynet.com CafeLAMv2 Active
 
SERV021-N1.mynet.com LogExportProvider Active
Is there a way to check the HubTransport Status Active vs Inactive?

Also this would need to be run remotely since all servers do not have exchange powershell commands available

They all can remote into the exchange server using New-PSSEssion

Thoughts

 

Schlauge

How about this command

 

Test-NetConnection -ComputerName SERV021-N1 -port 25

ComputerName : SERV021-N1
RemoteAddress : 10.2.2.17
RemotePort : 25
InterfaceAlias : Local Area Connection
SourceAddress : 10.2.2.69
TcpTestSucceeded : True

You can try PSRemoting to get the state of the HubTrasnport component.
The overall logic is the same:

<pre class="brush:powershell"
$servers = @("SERV021-N1","SERV021-N2")

Some work to get status of Server

maybe invoke-command or somethignelse

I dont know what this code should be, this needs to get the status of the Hubtransport from each Exchange server

$ExchHubTransportStatus = Invoke-Command -ComputerName $servers -ScriptBlock {get-servercomponentstate -Component HubTransport }

if ( $ExchHubTransportStatus[0].state -eq "Active") {
# first Server is UP
$Mailserver = $ExchHubTransportStatus[0].Server
}
elseif ($ExchHubTransportStatus[0].state -eq "Active") {
# second server is UP
$Mailserver = $ExchHubTransportStatus[1].Server
} else {
Write-Error "No Mailservers Available"
}

 

Schlauge

Your code below looks good can we use this

Test-NetConnection -ComputerName SERV021-N1 -port 25

Output is in my last posting above

This will test if port 25 is available
$Mailservers = @(“HOST1”,“HOST2”)

if (Test-Connection -ComputerName $Mailservers[0] -Count 1 -Quiet) {

first Server is UP

$Nailserver = $Mailservers[0]

}

elseif (Test-Connection -ComputerName $Mailservers[1] -Count 1 -Quiet) {

second server is UP

$Mailserver = $Mailservers[1]

} else {

Write-Error “No Mailservers Available”

}
 

 

TcpTestSucceeded : False when port is not available

I would do like below.

Create a function to send mail, then

$Mailservers = @("HOST1","HOST2")
$Mailserver = ''
$Mailservers | ForEach-Object -Process {
   if (Test-Connection -ComputerName $_ -Count 1 -Quiet) {
     $Mailserver = $_
   }
}
if($Null -ne $Mailserver){
   # Call send mail function here
}
else{
   # Throw here
}

#Or 

$Mailserver = Test-Connection -ComputerName $Mailservers -Count 1 -ErrorAction SilentlyContinue
if($Null -ne $Mailserver){
   # Call send mail function here
   $ActiveServer = ($Mailserver|Get-Random)
}
else{
   # Throw here using $Error
}

btwn,
It would be great if you update the post by formatting the code using code posting tags , this makes other to easily understand your code, below link will help you.

Guys

 

[PRE]Invoke-Command -ComputerName $Mailservers[0] -FilePath c:\Util\get-exchangestatus.ps1 [/PRE]

I created the script get-exchangestatus.ps1 on my exchange servers in the folder c:\util

but when I run the command above it returns command not found.

So I placed the script on my local c drive in the same folder it ran but had this error

[PRE]Active Directory operation failed on . The supplied credential for ‘MYNET\myaccount’ is invalid.

 
+ CategoryInfo : NotSpecified: (:slight_smile: , ADInvalidCredentialException
 
+ FullyQualifiedErrorId : [Server=SERV021-N1,RequestId=2b810f62-fd8c-4b97-91cb-69958d5d7ba0,TimeStamp=9/30/2018 1:44:28 PM] [FailureCategory=Cmdlet-ADInvalidCredentialException] 3A548CBE
 
+ PSComputerName : SERV021-N1.mynet.com
[/PRE]

So how can I run the script on the exchange server?

I have many servers that need to run this script

I thought the invoke-command would work

 

Thoughts?

 

 

 

Tom,

Start with Enter-PSSession from a Powershell prompt

[PRE]
Enter-PSSEssion -ComputerName SERV021-N1
[/PRE]

If you can connect to connect to the remote server, then run the Get-ServerComponentState

[PRE]
Get-ServerComponentState -Component HubTransport
[/PRE]

IF this works, then you can expand that to the previous script I provided. It looks like my last, got garbled somehow…

[PRE]
$Mailservers = @(“SERV021-N1”,“SERV021-N2”)
$MailSvrStatus = Invoke-Command -ComputerName $mailServers -ScriptBlock {
Enter-PSSEssion -ComputerName SERV021-N1

if ( {
# first Server is UP
$Nailserver = $Mailservers[0]
}
elseif (Test-Connection -ComputerName $Mailservers[1] -Count 1 -Quiet) {
# second server is UP
$Mailserver = $Mailservers[1]
} else {
Write-Error “No Mailservers Available”
}
[/PRE]

You are passing credentials, please show us the script you are using and note the
“To format code, use the Text…” above the text box for formatting the code.
Backticks or [pre] cannot be used to format code

Tom,

Break this down into little chunks…
…Can you get the Mail Server’s Maint Status from the server running the script…

Try starting with Enter-PSSession from a PowerShell prompt

Enter-PSSEssion -ComputerName SERV021-N1

If you can connect to connect to the remote server, then run the Get-ServerComponentState from within the session

Get-ServerComponentState -Component HubTransport

IF all this works, then you can expand that to the previous script I provided. It looks like my last, got garbled somehow…

$Mailservers = @("SERV021-N1","SERV021-N2")
$mailServerStatus = Invoke-Command -ComputerName $mailServers -ScriptBlock { Get-ServerComponentState -Component HubTransport }

if ( $mailServerStatus[0].State -eq "Active" ) {
# first Server is UP
$Nailserver = $Mailservers[0].Server
}
elseif ($mailServerStatus[1].State -eq "Active") {
# second server is UP
$Mailserver = $Mailservers[1].Server
} else {
Write-Error "No Mailservers Available"
}

if you can’t get a PSSession to get the data you are looking for… then you’ll need some other method to get the state of Maintenance Mode.

I hope this helps…

Get-ServerComponentState -Component HubTransport

The term ‘Get-ServerComponentState’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
+ CategoryInfo : ObjectNotFound: (Get-ServerComponentState:String) , CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

In the scriptblock can I load the exchange powershell module?
The command is this how do I wrap that in the scriptb block?
Add-PSSnapin microsoft.exchange.management.powershell.SnapIn;

Thank

Perhaps a better way to tell if the Exchange server is ready, is to utilize the Test-ServiceHealth cmdlet. That is provided you are running the script from the Exchange management shell where this cmdlet is available.

It will check if all required services are running on said Exchange server. And if they are running, you will be OK to send mail through it.

Simply edit to your original sample script, replace the following line:

 

$PSEmailServer = "SERV021-N1.MYNET.COM"

 

with an if statement that checks if services are running, then sets your PSEmailServer variable with the server name:

 

 if (Test-ServiceHealth -Server SERV021-N1.MYNET.COM | ? {$_.RequiredServicesRunning -eq $False}) 
	{$PSEmailServer = "SERV021-N2.MYNET.COM"} 
	else {$PSEmailServer = "SERV021-N1.MYNET.COM"}

I Like Cheese

Nice command but I still need the exchange powershell modules loaded.

I am trying this

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://$MailServers[0]/PowerShell/ -Authentication Kerberos -Credential $cred
Import-PSSession $Session -DisableNameChecking
$mailServerStatus = Get-ServerComponentState -Identity $EMailservers[0] -Component HubTransport