none
Смена смартхоста в коннекторе RRS feed

  • Общие обсуждения

  • Задача была такая... Есть несколько серверов Exchange, два смартхоста на *nix, через которых приходит нешняя почта и уходит внутренняя.
    Со входящей почтой проблем нет, оба смартхоста прописваются в DNS, первым и вторым MX-ом. А вот с исходящей почтой...

    В exchange организации есть два коннектора, через которые и уходит почта во вне. В одном прописан server1, во втором server2. У первого cost 10,у второго 20. Вроде бы все хорошо, не так ли? В любом случае отказа первого вся почта начинает ходить через второй. А вот как бы ни так! Если, к примеру, на первый идет слишком большое число коннектов или забита очередь на отправку-получение, то соединение виснет то на отправке helo, то на rcpt to... Но Exchange этого не понимает и перекидывает очередь на отправку на другой коннектор и почта стоит, пока не разгрузится смартхост.

    Я сделал вот что:

    1. Написал скрипт-эмуляцию соединения с smtp смартхоста:
    test_smtp_connect_and_send.tcl
    Код:
     
    Code Snippet
    #
        #   Скрипт для проверки отправки почты через SMTP
        #   <Путь к интерпретатору TCLwExpect>tcl.exe test_smtp_connect_and_send.tcl %1 %2 %3 %4 %5 %6
        #
        #    %1  <полное имя сервера или IP-адрес>
        #    %2  <таймаут>
        #    %3  <путь к лог-файлу>
        #    %4  <адрес отправителя>
        #    %5  <адрес получателя>
        #    %6  <Имя или IP-адрес замены смартхоста>
        #
        #

        if { $argc != 6 } {
        puts "This Script Need 6 Agruments...Target timeout logfile mailfrom rcptto NEWsmarthost."
        exit
        } else {
        # Указываем цель
        set target       [lindex $argv 0]
        # Указываем общее значение таймаута
        set timeout      [lindex $argv 1]
        # Указываем путь и имя файла
        log_file         [lindex $argv 2]
        # Указываем Отправителя
        set mailfrom     [lindex $argv 3]
        # Указываем Получателя
        set rcptto       [lindex $argv 4]
        # Указываем имя смартхоста, на который меняем сбойный
        set newsmarthost [lindex $argv 5]
        }
       
        #   Писать ли отчет на экране?
        log_user 1
        #   Ловим текущую дату и пишем ее в переменную
        catch {exec date} date_results

        send_log "------------------- "
        send_log $date_results
        send_log "-------------------- \n"
        #   Открываем сессию на указанный сервер
        spawn telnet $target 25
        #   Ожидаем ответа от сервера
        expect {
            -re "220" {
                send_log "Подключились. Посылаем helo\n"
                send -- "helo tst\n"
                }
            timeout {
                send_log "------------------- "
                send_log $date_results
                send_log "-------------------- \n"           
                send_log "Таймаут при подключении к серверу $target !\n "
                send_log "\n\n"
                exec writeeventlog.bat "error" "не отвечает сервер $target"
                exec change_smarthost.bat "$smarthost"
                exit
                }
        }
        expect {
            -re "250" {
                send_log "helo прошел. Посылаем отправителя.\n"
                send -- "mail from: $mailfrom \n"
                }
            timeout {
                send_log "helo не прошел! Ответ сервера: "
                send_log $expect_out(0,string)
                send_log "\n\n"
                exec writeeventlog.bat "error" "Не отвечает сервер $target HELO не прошел."
                exit
                }
        }
        expect {
            -re "250" {
                send_log "Отправитель прошел. Указываем получателя.\n"
                send -- "rcpt to: $rcptto \n"
            }
            timeout {
                send_log "---Таймаут при определении отправителя! Ответ сервера:\n "
                send_log $expect_out(0,string)
                send_log "\n\n"
                exit
                exec writeeventlog.bat "error" "Таймаут при определении отправителя! Сервер $target"
                }
        }
        expect {
            -re "250" {
                send_log "Получатель прошел. Отправляем данные.\n"
                send -- "data\n"
            }
            timeout {
                send_log "---Таймаут при попытке определения получателя! Ответ сервера:\n "
                send_log $expect_out(0,string)
                send_log "\n\n"
                exec writeeventlog.bat "error" "Таймаут при определении получателя! Сервер $target"
                exit
                }
        }
            expect {
            -re "354" {
                send_log "Проверка прошла успешно. Закрываюсь...\n"
                send_log "---------------------------------------\n"
                exec writeeventlog.bat "information" "Проверка прошла успешно. Сервер $target"
                exit
                }
            } 
           

     

    2. Написал скрипт, который бы писал о всех действиях в EventLog:
    write_to_eventlog.vbs

    Код:

    Code Snippet
    Sub WriteEvent (Error_Type, strEventLog)

       Set WshShell = WScript.CreateObject("WScript.Shell")
       
       Select Case Error_Type
             Case "information"
                WshShell.LogEvent 4, strEvent
             Case "warning"
                WshShell.LogEvent 2, strEvent
             Case "error"
                WshShell.LogEvent 1, strEvent
       End Select                     
    End Sub

     

    3. Написал скрипт переписывания смартхоста в первом коннекторе
    change_connector.vbs
    Код:
    Code Snippet
    Option Explicit
    On Error Resume Next

    Dim GCName, ConnectorName, ExchOrganization, ConfNamingContext
    Dim objRoutingGroup, NewSmartHost, NewSH, ExistSH, args

    GCName = "GlobalCatalogServerName" 'Имя или ip-адрес сервера глобального каталога
    ConnectorName = "CONNECTORName" 'Имя коннектора
    ExchOrganization = "ExchangeOrganizationName" 'Имя Exchange организации
    ConfNamingContext = "CN=Configuration, DC=WIN2000, DC=test" 'домен

    Set args = WScript.Arguments

    If args.Length = 0 Then

       Call WriteEvent ("error", "Не указаны необходимые аргументы для смены SmartHost у коннектора $ConnectorName !")
       WScript.Quit
       
    End If

    NewSmartHost = args.Item(0)

    Set objRoutingGroup = GetObject("LDAP://"&; GCName &" /CN="& ConnectorName &",CN=Connections,CN=First Routing Group,CN=Routing Groups," & _
    "CN=First Administrative Group,CN­ministrative Groups,CN="& ExchOrganization &",CN=Microsoft Exchange,CN=Services," & _
    ConfNamingContext)
    objRoutingGroup.GetInfo

    If Err.Number <> 0 Then

       Call WriteEvent ("error", "Ошибка подключения к объекту SMTP-коннектора $ConnectorName в AD! Код ошибки: " & Err.Number)
       WScript.Quit
       
    End If

    WScript.Echo Err.Number

    ExistSH = objRoutingGroup.msExchSmtpSmartHost

    If NewSmartHost = ExistSH Then

          Call WriteEvent ("warning", "Смена хоста не была произведена. " & VbCrLf & "Причина: указываемый хост уже установлен" & VbCrLf & _
          "Указываемый хост: " & NewSmartHost & VbCrLf & "Заменяемый хост: " & ExistSH)
          
       Else

          objRoutingGroup.msExchSmtpSmartHost = NewSmartHost
          objRoutingGroup.SetInfo
          
          If Err.Number <> 0 Then

             Call WriteEvent ("error", "Ошибка подключения к объекту SMTP-коннектора $ConnectorName в AD! Код ошибки: " & Err.Number)
             WScript.Quit
       
          End If
          
          Call WriteEvent ("warning", "Была произведена смена хоста . " & VbCrLf & "Причина: таймаут при попытке отправить тестовое сообщение" & VbCrLf & _
          "Указываемый хост: " & NewSmartHost & VbCrLf & "Заменяемый хост: " & ExistSH)

    End If      

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Sub WriteEvent (Error_Type, strEventLog)

       Dim WshShell

       Set WshShell = WScript.CreateObject("WScript.Shell")
       
       Select Case Error_Type
             Case "information"
                WshShell.LogEvent 4, strEventLog
             Case "warning"
                WshShell.LogEvent 2, strEventLog
             Case "error"
                WshShell.LogEvent 1, strEventLog
       End Select                     
    End Sub
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

     

    4. Так как язык TCL для windows может поддерживать только командные bat-файлы, то создаем и их тоже:
    change_smarthost.bat
    Код:
    Code Snippet
    cscript.exe change_smarthost.vbs %1

     

    write_to_eventlog
    Код:
    Code Snippet
    cscript write_to_eventlog.vbs %1 %2

     

    Подвесил cmd-файл на одном из серверов:

    Код:
    Code Snippet
    .\tcl\bin\tclsh80.exe test_smtp_connect_and_send.tcl <smarthost address> <TIMEOUT> <PATH\LOGFILE.LOG> <SENDERADDRESS> <RECIPIENTADDRESS>

     


    И все! После зависания пишется в лог и переписывается имя смархоста, после этого вся почта пойдет туда куда надо)

    Есть ли у вас предложения?

    Первый скрипт написан на TCL&Expect. Ссылка на дистрибутив (установки не требуется)

    Маны на него

    • Перемещено Tina_Tian 19 марта 2012 г. 7:17 forum merge (От:Exchange Server 2003/2000/5.5)