Скрипт Powershell для тестирования прохождения почты

Для тестирования работоспособности почтовой системы была создана пара почтовых ящиков, один из которых находится во внешней сети, и настроено правило, чтобы письмо, отправленное с внутреннего ящика на внешний, автоматически возвращалось на внутренний ящик. Осталось только сделать скрипт на Powershell, который бы периодически отправлял тестовое письмо, и проверял, вернулось ли оно обратно.

В скрипте использованы найденные в интернете функции получения почты через POP3, а отправка осуществляется через командлет Send-MailMessage. В случае, если отправленное письмо не возвращается обратно, скрипт отправляет письмо на адреса администраторов (заданы в переменной addr_to).

Скрипт выкладывается “как есть”, за исключением того, что имена серверов, доменов, и пользователей изменены на тестовые. Имена почтовых серверов, логин и пароль “зашиты” в теле функции NewPOP3 и в основном скрипте – не забудьте поменять. У меня возникала мысль немного дописать скрипт, чтобы он делал несколько попыток получения письма, но как это обычно бывает, руки не дошли. Скрипт работал в организации примерно год, после чего его функциональность перенесли на Microsoft System Center 2012 Orchestrator. Правило в Orchestrator точно так же тестировало работу почты, и в случае проблемы создавало алерт в SCOM, чего скрипт не делает, но это уже совсем другая история.

function Send ([string]$Msg)
{
    $Encoder=New-Object System.Text.ASCIIEncoding
    [byte[]]$Buffer=(,0)*1024
    $Buffer=$Encoder.GetBytes($Msg)
    $NetStream=$this.GetStream()
    $NetStream.Write($Buffer, 0, $Buffer.Length)
}

function Response ()
{
    $Encoder=New-Object System.Text.ASCIIEncoding
    [byte[]]$Buffer=(,0)*1024
    $NetStream=$this.GetStream()
    [int]$Count=0
    While($true)
    {
        [byte[]]$buff=(,0)*2
        $NotEnd=$NetStream.Read($buff, 0, 1)
        if ($NotEnd)
        {
            if (($buff -eq 10) -and ($Buffer[0] -eq 0)) {continue}
            $Buffer[$Count]=$buff[0]
            $Count++
            if ($buff[0] -eq 10) {break}
        }
        else {break}
    }
    return $Encoder.GetString($Buffer, 0, $Count)
}

function NewMessage ()
{
    $Message=New-Object -Type PSobject
    Add-Member -in $Message NoteProperty Number $([long]0) -Force
    Add-Member -in $Message NoteProperty Size $([long]0) -Force
    Add-Member -in $Message NoteProperty Recieved $([bool]0) -Force
    Add-Member -in $Message NoteProperty Content $([string]::Empty) -Force
    return $Message
}


function NewPOP3 ()
{
    $ConnectP=
    {
        $Server='srv-mail04.test.local'
        $User='mailtest@test.local'
        $Password='P@ssw0rd'

        $Res=''
        $POP3.Connect($Server,110)
        $Res=Response
        if (! $Res.StartsWith('+OK')) {throw $Res}
        Send "USER $User`r`n"
        $Res=Response
        if (! $Res.StartsWith('+OK')) {throw $Res}
        Send "PASS $Password`r`n"
        $Res=Response
        if (! $Res.StartsWith('+OK')) {throw $Res}
    }

    $DisconnectP=
    {
        $Res=''
        Send "QUIT`r`n"
        $Res=Response
        if (! $Res.StartsWith('+OK')) {throw $Res}
    }

 

    $GetList=
    {
        $Res=''
        $List=@()
        Send "LIST`r`n"
        $Res=Response
        if (! $Res.StartsWith('+OK')) {throw "Error"}
        While ($true)
        {
            $Res=Response
            if ($Res -eq ".`r`n") {return $List}
            else
            {
                $Message=NewMessage
                [string[]]$Value=$Res.Split(" ")
                $Message.Number=[int]$Value[0]
                $Message.Size=[int]$Value[1]
                $Message.Recieved=$false
                $List+=$Message
                $Message=$null
                continue
            }
        }
    }

    $Retrieve=
    {
        param ($Msg)
        $Res=''
        $Message=NewMessage
        $Message.Size=$Msg.Size
        $Message.Number=$Msg.Number
        Send "RETR $($Msg.Number)`r`n"
        $Res=Response
        if (! $Res.StartsWith('+OK')) {throw $Res}
        $Message.Recieved=$true
        while ($true)
        {
            $Res=Response
            if ($Res -eq ".`r`n") {break}
            else {$Message.Content+=$Res}
        }
        return $Message
    }

    $Delete=
    {
        param ($Msg)
        $Res=''
        $Message=NewMessage
        $Message.Size=$Msg.Size
        $Message.Number=$Msg.Number
        Send "DELE $($Msg.Number)`r`n"
        $Res=Response
        if (! $Res.StartsWith('+OK')) {throw $Res}
    }

    [PSObject]$TCPClient=New-Object System.Net.Sockets.TcpClient
    Add-Member -in $TCPClient ScriptMethod ConnectP $ConnectP
    Add-Member -in $TCPClient ScriptMethod DisconnectP $DisconnectP
    Add-Member -in $TCPClient ScriptMethod GetList $GetList
    Add-Member -in $TCPClient ScriptMethod Retrieve $Retrieve
    Add-Member -in $TCPClient ScriptMethod Delete $Delete
    return $TCPClient
}

cls

$Result=@()

# интервал ожидания прохождения письма после его отправки
$delay = 15

# кому отправлять письма:
$addr_to = "Admin1@test.local", "Admin2@test.local"

# отправка тестового сообщения
write-host "Отправляем письмо..."
$date = Get-Date
$subject = "Test " + $date
$body = "Тестирование почты " + $date
Send-MailMessage -from mailtest@test.local -to mailtest@internetmail.ru -Subject $subject -Body $body -smtpserver srv-mail01.test.local -encoding ([System.TExt.Encoding]::UTF8)
if($?)
    {
    write-host "Письмо отправлено!"
    # подождать...
    write-host "Ждём 15 секунд..."
    sleep($delay)
    write-host "Получаем почту..."
    # получить список писем
    $POP3=NewPOP3
    trap {$_;$POP3.Close();exit} $POP3.ConnectP()
    trap {$_;$POP3.close();exit} $MessageList=$POP3.GetList()
    if ($MessageList.Count -eq 0)
        {
        # если в ящике 0 сообщений - почта не работает
        Write-Host "В ящике нет писем. Почта не работает!"
        $body = "Почта не работает`n" + $date + "`n`nСообщение, отправленное на адрес mailtest@internetmail.ru, не вернулось на адрес mailtest@test.local.`n`n-- `nЭто тест. Меня видно?"
        Send-MailMessage -from mailtest@test.local -to $addr_to -Subject "Тестирование почты" -Body $body -smtpserver srv-mail01.test.local -encoding ([System.TExt.Encoding]::UTF8)
        }
    else
        {
        Write-Host "Почта работает"
        # удаляем письма
        Write-Host "Удаляем письма"
        foreach ($Msg in $MessageList)
            {
            # trap {$_;$POP3.close();exit} $Result+=($POP3.Retrieve($Msg))
            trap {$_;$POP3.close();exit} $Result+=($POP3.Delete($Msg))
           
            }
        }
    $POP3.DisconnectP()
    $POP3.Close()
    }
else
    {
    write-host "Ошибка отправки письма!"
    $body = "Сбой тестирования почты`n" + $date + "`n`nНе удалось отправить сообщение на адрес mailtest@internet.ru.`n`n-- `nЭто тест. Меня видно?"
    Send-MailMessage -from mailtest@test.local -to $addr_to -Subject "Тестирование почты" -Body $body -smtpserver srv-mail01.test.local -encoding ([System.TExt.Encoding]::UTF8)
    }

Добавить комментарий