Zabbix мониторинг доступности SMTP серверов

Проверка

 echo "QUIT" | nc mx.domain.com 25

на некоторых почтовых серверах (Exim) выдает “554 SMTP synchronization error”

Причина в том что Exim не принимает ввод, посланный до готовности, то есть в тот момент когда этого не должно было быть.
Соответственно проверка SMTP сервера через NETCAT – не работает.

Шаблон Zabbix: zabbix_template_smtp_servers.xml

Комментарий:
2016-06-03 – функция nodata() в триггере абсолютно бесполезна, так как ее значение для элемента данных сети в статусе “Не поддерживается” = НЕИЗВЕСТНО, и триггер не срабатывает.

Конфиг zabbix-agent-a:

UserParameter=smtpcheck[*],/etc/zabbix/zabbix-check-smtp.sh $1

Скрипт 1 (устарел): /etc/zabbix/zabbix-check-smtp.sh

#!/bin/sh
# по-умолчанию - ошибка проверки
result=0
if [ $# -lt 1 ]
then {}
else {
# Вычленяем имя сервера из почтового адреса
domain=$1
# Определяем MX домена
mxserver=$( dig $domain MX |\
egrep 'MX[[:space:]]+[0-9]+[[:space:]]+[^[:space:]]+\.' |\
sort -n -k5,5 |\
head -1 | awk '{print $6}' | sed 's/\.$//' )
#
# echo 'mxserver='$mxserver
# нашелся MX
if [ "$mxserver" != "" ]
then {
# Пытаемся провести SMTP диалог
smtpconnect=`/usr/bin/php -f /etc/zabbix/check-smtp-server.php $mxserver 25`
# формируем результат
if [ $smtpconnect = "1" ]
then
{
result=1
}
fi
}
fi # MX сервер для домена найден
}
fi # количество параметров
echo $result

Скрипт 2 : /etc/zabbix/zabbix-check-smtp.sh
Преимущества: проверяет все имеющиеся MX записи, сохраняет доступную MX-запись в /var/cache/zabbix
Не забыть создать и дать права на /var/cache/zabbix!

#!/bin/sh
#
CACHE=/var/cache/zabbix

checksmtp()
{
 echo `/usr/bin/php -f /etc/zabbix/check-smtp-server.php $1 25`
}

# Domain name set
domain=$1
ismx=$CACHE/ismx-$domain.list
goodmx=$CACHE/goodmx-$domain

# if there is NO file with good MX name list
if [ ! -f $goodmx ]
then
# Get all mx-record from DNS server to file
dig $domain MX |\
egrep 'MX[[:space:]]+[0-9]+[[:space:]]+[^[:space:]]+\.' |\
sort -n -k5,5 | awk '{print $6}' | sed 's/\.$//' > $ismx

# check all MX one by one
index=0
while read line; do
    mxserver=$line
    smtpconnect=$(checksmtp $mxserver)
    if [ $smtpconnect = "1" ]
    then
        rm $ismx
        echo $mxserver >> $goodmx
        # EXIT
        echo 1
        exit
    fi
done < $ismx

# If we are here that means THERE ARE NO answer from ALL MX-records
rm $ismx
echo 0
exit

# WE HAVE STORED FILE WITH GOOD MX RECORD
#-----------------------------------------
else
mxserver=$(head -1 $goodmx)
if [ "$mxserver" != "" ]
then
    smtpconnect=$(checksmtp $mxserver)
    if [ $smtpconnect = "1" ]
    then
        echo 1
        exit
    else
        rm $goodmx
        echo 0
        exit
    fi
fi
fi

PHP-скрипт /etc/zabbix/check-smtp-server.php:

Важно: Параметр timeout в функции fsocketopen и stream_set_timeout должен коррелировать со значением параметра TimeOut в конфигурации zabbix-agent-a.

<?php

error_reporting(0);

function server_parse($socket, $response, $line = __LINE__) {
    $server_response ='';

    while (substr($server_response, 3, 1) != ' ') {
        //
        // TimeOut !!!
        stream_set_timeout($socket, 20);

        if (!($server_response = fgets($socket, 256))) {
                   return false;
        }
    }
    if (!(substr($server_response, 0, 3) == $response)) {
        return false;
    }
    return true;
}

// 
// TimeOut = 3 second
// Иначе получаем большое ожидание, и элемент данных не получает значения по таймаут-у.
function checkSMTPServer( $smtp_host, $smtp_port ) {
    if ( !$socket = fsockopen( $smtp_host, $smtp_port, $errno, $errstr, 3) ) {
        return 0;
    }

    if (!server_parse($socket, "220", __LINE__)) {
        return 0;
    }

    fputs($socket, "QUIT\r\n");
    fclose($socket);
    return 1;
}


if ($argc != 3) {
    echo 'Command line: /usr/bin/php check-smtp-server.php mx.mydomain.com 25'."\n";
}
else {
    echo checkSMTPServer( $argv[1], $argv[2])."\n";
}