使用 Powershell 在 windows 服务器中配置 Smtp 虚拟服务器-(中继,连接)

Configure Smtp Virtual Server in windows Server using Powershell-(Relay,Connection)

使用 powershell 我必须启用 SMTP 和

我找到了以下用于上述操作的代码

$GetSMTP = Get-CimInstance -Namespace "root\MicrosoftIISv2" -Class "IISSMTPServerSetting" -Filter "Name ='SmtpSvc/1'"
$RelayIps =  @(10,92,32,83,127,0,0,1)
$GetSMTP.RelayIpList = $RelayIps
Set-CimInstance -InputObject $GetSMTP

$GetSMTP
$GetSMTP = Get-CimInstance -Namespace "root\MicrosoftIISv2" -Class "IIsIPSecuritySetting" -Filter "Name ='SmtpSvc/1'"

$NewConnectionIps = @(
                     "10.92.32.80, 10.92.32.81";
                     "10.92.32.83,127.0.0.1";
                      )
$GetSMTP.ipgrant += $NewConnectionIps
Set-CimInstance -InputObject $GetSMTP

$GetSMTP

以上 powershell 代码执行成功,并在添加时列出。

但是当我连接到 smtp 服务器时,抛出以下错误

我找到了解决上述问题的方法,要删除 "C:\inetpub\mailroot" 中的文件夹以及我可以启动默认 Smtp 虚拟服务器的文件夹,但在单击 smtp 虚拟服务器时再次遇到问题属性

Loading Feature Installation Modules

Import-Module ServerManager 

Installing Features

Add-WindowsFeature SMTP-Server,Web-Mgmt-Console,WEB-WMI

Adding Relay , connection IPs and Authentication Basic for SMTP

$Networkip =@()
$Networks = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName    localhost | ? {$_.IPEnabled}
foreach($Network in $Networks)  {  $Networkip = $Network.IpAddress[0]  }

Adding Relay and Authentication Basic for SMTP

$ipblock= @(24,0,0,128,
32,0,0,128,
60,0,0,128,
68,0,0,128,
1,0,0,0,
76,0,0,0,
0,0,0,0,
0,0,0,0,
1,0,0,0,
0,0,0,0,
2,0,0,0,
1,0,0,0,
4,0,0,0,
0,0,0,0,
76,0,0,128,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
255,255,255,255)

$ipList = @()
$octet = @()
$connectionips=$arg[0]       
$ipList = "127.0.0.1"
$octet += $ipList.Split(".")
$octet += $Networkip.Split(".")

$ipblock[36] +=2 
$ipblock[44] +=2;
$smtpserversetting = get-wmiobject -namespace root\MicrosoftIISv2 -computername localhost -Query "Select * from IIsSmtpServerSetting"
$ipblock += $octet
$smtpserversetting.AuthBasic=1
$smtpserversetting.RelayIpList = $ipblock
$smtpserversetting.put()

Adding Connection for SMTP

$connectionips="10.10.10.10"      

$checkArray =$connectionips.split(",") 
if($checkArray -notcontains $Networkip)
{
 $connectionips += ","+$Networkip
}

$connectionipbuild=@()
$ipArray=$connectionips.split(",")
foreach ($ip in $ipArray)
{   
  $connectionipbuild +=$ip+",255.255.255.255;"     
}

$iisObject = new-object System.DirectoryServices.DirectoryEntry("IIS://localhost/SmtpSvc/1")
$ipSec = $iisObject.Properties["IPSecurity"].Value

# We need to pass values as one element object arrays
[Object[]] $grantByDefault = @()
$grantByDefault += , $false            # <<< We're setting it to false

$ipSec.GetType().InvokeMember("GrantByDefault", $bindingFlags, $null, $ipSec, $grantByDefault);

$iisObject.Properties["IPSecurity"].Value = $ipSec
$iisObject.CommitChanges()

$iisObject = new-object System.DirectoryServices.DirectoryEntry("IIS://localhost/SmtpSvc/1")
$ipSec = $iisObject.Properties["IPSecurity"].Value
$bindingFlags = [Reflection.BindingFlags] "Public, Instance, GetProperty"
$isGrantByDefault = $ipSec.GetType().InvokeMember("GrantByDefault", $bindingFlags, $null, $ipSec, $null);

# to set an iplist we need to get it first
if($isGrantByDefault)
{
    $ipList = $ipSec.GetType().InvokeMember("IPDeny", $bindingFlags, $null, $ipSec, $null);
}
else
{
    $ipList = $ipSec.GetType().InvokeMember("IPGrant", $bindingFlags, $null, $ipSec, $null);
}

# Add a single computer to the list:
$ipList = $ipList + $connectionipbuild

# This is important, we need to pass an object array of one element containing our ipList array
[Object[]] $ipArray = @()
$ipArray += , $ipList

# Now update
$bindingFlags = [Reflection.BindingFlags] "Public, Instance, SetProperty"
if($isGrantByDefault)
{
    $ipList = $ipSec.GetType().InvokeMember("IPDeny", $bindingFlags, $null, $ipSec, $ipArray);
}
else
{
    $ipList = $ipSec.GetType().InvokeMember("IPGrant", $bindingFlags, $null, $ipSec, $ipArray);
}

$iisObject.Properties["IPSecurity"].Value = $ipSec
$iisObject.CommitChanges()

除了 PonVimal 的 回答(已接受):

此解决方案使用 Indented.NetworkTools

中的 Get-NetworkAddress 函数

如果您想为一组计算机而不是单个地址指定中继,您可以按以下方式使用System.DirectoryServices(感谢this answer):

$IpRelayList = @("192.168.1.0, 255.255.0.0", 
                "127.3.4.0, 255.255.255.192")

#adding relays
$iisObject = new-object System.DirectoryServices.DirectoryEntry("IIS://localhost/smtpsvc/1")
$relays = $iisObject.Properties["RelayIpList"].Value
$bindingFlags = [Reflection.BindingFlags] "Public, Instance, GetProperty"
$ipList = $relays.GetType().InvokeMember("IPGrant", $bindingFlags, $null, $relays, $null);

#if relay list is empty we are retrieving host subnets and adding to relay
$Networkip =@()
if($IpRelayList.Count -eq 0)
{
    $Networks = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName localhost | ? {$_.IPEnabled}
    foreach($Network in $Networks)  
    {   
        $line = Get-NetworkAddress $Network.IpAddress[0] $Network.IpSubnet[0]
        $line = $line + ", " + $Network.IpSubnet[0]
        $Networkip += $line
    }
}

$ipList = $Networkip + $IpRelayList

# This is important, we need to pass an object array of one element containing our ipList array
[Object[]] $ipArray = @()
$ipArray += , $ipList

# Now update
$bindingFlags = [Reflection.BindingFlags] "Public, Instance, SetProperty"
$ipList = $relays.GetType().InvokeMember("IPGrant", $bindingFlags, $null, $relays, $ipArray);

$iisObject.Properties["RelayIpList"].Value = $relays
$iisObject.CommitChanges()

除了PonVimal的回答(采纳):

我还希望 SMTPSVC 服务是自动的,并想出了一个幂等脚本来确保该服务不仅被安装而且设置为自动并启动,这样任何后续的机器重启都不需要我手动启动服务。

# ----- Converting service: "Simple Mail Transfer Protocol" to be automatic from manual ------
$ServiceName= "SMTPSVC"

    If (Get-Service $ServiceName -ErrorAction SilentlyContinue) {
        If ((Get-Service $ServiceName).StartType -ne "Automatic") {
            If ((Get-Service $ServiceName).Status -eq 'Running') {
                Stop-Service $ServiceName
                "Stopping $ServiceName"
            } Else {
                        "ServiceName found, and it is stopped."
                    }
            Set-Service -Name $ServiceName -StartupType "Automatic"
            Do{
            "Starting service: $ServiceName"
            sc.exe start "$ServiceName"
            start-sleep -s 5
            $ServiceStatus = (get-service -name $ServiceName)
            } 
            Until ($ServiceStatus.Status -eq "running")
            "Service Started: $ServiceName"
        }

        If ((Get-Service $ServiceName).Status -eq 'Running') {
            "`n$ServiceName configured as automatic and running`n"
        } Else {
            Do{
            "Starting service: $ServiceName"
            sc.exe start "$ServiceName"
            start-sleep -s 5
              $ServiceStatus = (get-service -name $ServiceName)
            } 
            Until ($ServiceStatus.Status -eq "running")
            "Service Started: $ServiceName"
          }
        } Else {
        "$ServiceName not found"
    }

# Test to check if the service is configured correctly and is running
If (Get-Service $ServiceName) {

    If ((Get-Service $ServiceName).StartType -ne "Automatic") {
        throw "$ServiceName is not configured as automatic"

    }
    If ((Get-Service $ServiceName).Status -ne 'Running') {
        throw "$ServiceName is not running"

    }
    "`n$ServiceName configured as automatic and running`n"
}

这实际上是可能的,而且比人们想象的要复杂。这个神奇的中继 IP 列表对象包含一些集合长度 hard-coded。

这是我在发现这个奇怪之处后使用的脚本的一部分。

param(
    [Parameter(ValueFromRemainingArguments=$true)][object[]]$AllowedIPs
)

$SMTPServerWmi = Get-WmiObject IISSmtpServerSetting -namespace "ROOT\MicrosoftIISv2" | Where-Object { $_.name -like "SmtpSVC/1" }
$SMTPServerWmi.RelayIpList = @(24,0,0,128,
32,0,0,128,
60,0,0,128,
68,0,0,128,
1,0,0,0,
76,0,0,0,
0,0,0,0,
0,0,0,0,
1,0,0,0,
$AllowedIPs.Count,0,0,0,
2,0,0,0,
($AllowedIPs.Count + 1),0,0,0,
4,0,0,0,
0,0,0,0,
76,0,0,128,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
255,255,255,255) + $AllowedIPs.ForEach({ $_.Split(".")})

$SMTPServerWmi.Put()

如果这些值不正确,UI 可能会显示您的 IP 和大量随机垃圾、崩溃或损坏,因此您无法使用它从列表中删除项目UI.