LoginSignup
1
5

More than 5 years have passed since last update.

Outlook向け Zabbixメール通知拡張

Last updated at Posted at 2017-09-14

メール通知拡張

目的

  • 大前提 「Outlook」を利用する(会社指定だから仕方ないね)
  • Zabbixからのメール通知の異常発生、復旧をツリー化したい
  • 通知メールが異常発生なのか復旧なのかひと目で分かるように
    デザインを取り込みたい
  • メーリングリストを使って通知したい
  • メール優先度で障害レベルが知りたい

実装

https://github.com/130cmWolf/plugins/tree/master/notification/sendmessage-smtp-php
思いつきで対応していたので比較的適当な実装になってます
もちろん勝手に改造していただいてよいです。

ソース解説

解説はいいから使い方を教えろって方は→の目次からドゾ

比較的よく使われていそうなZabbixメール送信拡張用のプラグインスクリプトの
https://github.com/zabbix-jp/plugins
からsendmessage-smtp-phpを利用しています

とは言え最終的にはほぼすべて書き直しに近い実装になってしまったが…

UTF-8を利用したほうが実装が楽だったのでiso-2022-jpやPHPMailer_JPクラスは削除しています。

phpmailer の更新

まあ、サラッと追加。

composer require phpmailer/phpmailer

記載時のバージョンは 5.2.25 でした
$ cat vendor/phpmailer/phpmailer/VERSION
5.2.25

vendorを読み込んでおきます。

sendmessage_smtp_php.sh
require 'vendor/autoload.php';

Markdown対応

Zabbix内でのメール書式をMarkdownで書いたほうが楽かもしれないと思ったので、
Markdownプラグインも乗せています。

composer require michelf/php-markdown
sendmessage_smtp_php.sh
use Michelf\MarkdownExtra;


// HTMLメール対応
$MAIL_MESSAGE = <<<EOD
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" />
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Language" content="ja" />
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    <meta name="viewport" content="initial-scale=1.0,width=device-width" />
    <title>$MAIL_SUBJECT</title>
    <style type="text/css">
h1,h2 {
  font-size: 110%
}
blockquote {
  margin-left: 0.5em;
  padding-left: 0.5em;
  border-left: 1px solid #CCCCCC;
}
body {
  font-size: 90%;
}
pre{
  font-size: 90%
  display: block;
  padding: 0.5em;
  width: 70%;
  background-color: #DDDDDD;
  border: 1px dotted #666666;
}
code{
font-size: 90%
}
  </style>
  </head>
EOD;
// Markdownフォーマットの展開
$MAIL_MESSAGE .= "<body>" . MarkdownExtra::defaultTransform($argv[3]) . "</body>";
$MAIL_MESSAGE .= "</html>";

SMTP認証の改良

そのままでも問題無いと思いますが、
ポート等の変数を分解しています。

sendmessage_smtp_php.sh
$MAIL_SMTP_HOST = 'smtp.example.com';
$MAIL_SMTP_PORT = 25;
$MAIL_SMTP_SEC  = "ssl";

$mailer->Host = $MAIL_SMTP_HOST;
$mailer->Port = $MAIL_SMTP_PORT;
$mailer->SMTPAuth = true;
$mailer->SMTPSecure = $MAIL_SMTP_SEC;
$mailer->Username = $MAIL_SMTP_USER;
$mailer->Password = $MAIL_SMTP_PASS;

優先度対応

特に難しいことはしていません。

sendmessage_smtp_php.sh
// 優先度設定
$PRIORITY = 3;
switch ($m[3]) {
    case "0":
        // 分類無し
        $PRIORITY = 3;
        break;
    case "1":
        // 情報
        $PRIORITY = 3;
        break;
    case "2":
        // 警告
        $PRIORITY = 3;
        break;
    case "3":
        // 障害
        $PRIORITY = 1;
        break;
    case "4":
        // 重度障害
        $PRIORITY = 1;
        break;
    case "5":
        // 致命的な障害
        $PRIORITY = 1;
        break;
}


$mailer->Priority = $PRIORITY;

メールツリー化用リプライ設定

ツリー化するためのリプライ設定を追加します。
管理ファイルの持ち方等は ZABBIXの通知メールをスレッド化してみる を参考にしています

sendmessage_smtp_php.sh
    $mailer->addCustomHeader('In-Reply-To', '<APPLI.' . $id . '.' . $rnd . '@' . gethostname() . '>');
    $mailer->addCustomHeader('References', '<APPLI.' . $id . '.' . $rnd . '@' . gethostname() . '>');

Outlook用ツリー化リプライ設定、メーリングリスト対応

こいつが曲者

getNewThreadIndex()でメール新規発行用のThread-Indexを生成して、
管理ファイルへ保存しています。

リプライ用にgetNextThreadIndex($parent)に対しツリー親のThread-Indexを渡すとツリー子用のThread-Indexを発行します。

Thread-Indexについての解説は Outlook Thread-Index Value Analysis を参考に。

子用のThread-Indexの算出があってるかどうかわからないが、
動いたからいいかなと思っている。

多分孫メール用のThread-Indexは正しく生成できないと思われるが、Zabbixで動く分には問題ないためこの実装ですすめる。

sendmessage_smtp_php.sh
function GUID()
{
    if (function_exists('com_create_guid') === true)
    {
        return trim(com_create_guid(), '{}');
    }

    return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
}
function getNewThreadIndex()
{
    // Outlook独自ヘッダー Thread-Index 生成
    $offset = ((new DateTime())->getTimeStamp() - (new DateTime("1601-01-01T00:00:00.000Z"))->getTimeStamp());
    $hex = hex2bin(substr(sprintf("%016X",$offset *10 *1000 *1000), 0, 12) . str_replace ('-', '', GUID()));
    return base64_encode($hex);
}
function getNextThreadIndex($parent)
{
    // Outlook独自ヘッダー Thread-Index リプライ生成
    $parenthex = bin2hex(base64_decode($parent));

    $parentdate = new DateTime("1601-01-01T00:00:00.000Z");
    $parentdate->modify("+". sprintf("%d",hexdec(substr($parenthex, 0, 12) ."0000")/10 /1000/1000). " seconds" );

    $c_time_offset  = ((new DateTime())->getTimeStamp() - $parentdate->getTimeStamp()) *10 *1000 *1000;
    $time_diff  = sprintf("%064s",decbin($c_time_offset)) ."\n";
    $binary = substr($time_diff, 23, 31);
    return base64_encode(hex2bin($parenthex . sprintf("%010X", intval($binary,2))));
}



    // 初期ヘッダ作成
    $mailer->addCustomHeader('Thread-Topic', $thr);
    $mailer->addCustomHeader('Thread-Index', $thi);


    $mailer->addCustomHeader('Thread-Topic', $thr);
    $mailer->addCustomHeader('Thread-Index', getNextThreadIndex($thi)); // Thread-Indexリプライ設定

使い方

サーバー内

Zabbix用スクリプトの配置

/usr/lib/zabbix/alertscripts/sendmessage_smtp_php/sendmessage_smtp_php.sh

phpmailerとphp-markdownを取得

cd /usr/lib/zabbix/alertscripts/sendmessage_smtp_php/
chmod +x sendmessage_smtp_php.sh
composer require phpmailer/phpmailer
composer require michelf/php-markdown

Zabbix 設定

メディアタイプ

「管理>メディアタイプ」から「メディアタイプの作成」

mediatype.png

一般的な設定で作成

ユーザー設定

ユーザーに対応するメディアタイプにメール設定を追加

アクション設定の変更

件名

[Zabbix Alert:{EVENT.ID}] {HOST.NAME} 障害発生  ###{EVENT.ID}  {TRIGGER.NSEVERITY}

「###」をキーとしてその後ろにイベントIDと障害レベルをスクリプトに通知しています

メッセージ

<font color="Red">システム障害発生</font>
======

* 環境  
{HOST.NAME1} / {HOST.IP}
* 障害発生時刻  
{DATE} {TIME}

[障害情報](http://zabbix.server/zabbix/tr_events.php?triggerid={TRIGGER.ID}&eventid={EVENT.ID})

-----

* このメールはシステムより自動配信されています。  
* 監視停止再開メールはスレッド化されて配信されます。

-----

等、Markdownで自由に記載します。

実行内容も作成したメディアタイプに対して送信します。

復旧メール設定

件名

[Zabbix Alert:{EVENT.ID}] {HOST.NAME} 障害発生  ###{EVENT.ID}  {TRIGGER.NSEVERITY}

「###」をキーとしてその後ろにイベントIDと障害レベルをスクリプトに通知しています
注:障害メールと同じ件名にしないとOutlookの仕様では同じツリーとみなされずばらばらになってしまいます。
タイトル先頭に 「re:」「復旧:」 は同じツリー内メールとしてみなされたため(Outlook2010)付けるのはありだと思う。

メッセージ

<font color="Blue">システム復旧</font>
======

* 環境  
{HOST.NAME1} / {HOST.IP}
* 復旧時刻  
{DATE} {TIME}

[障害情報](http://zabbix.server/zabbix/tr_events.php?triggerid={TRIGGER.ID}&eventid={EVENT.ID})

-----

* このメールはシステムより自動配信されています。  
* 監視停止再開メールはスレッド化されて配信されます。

-----

等、Markdownで自由に記載します。

実行内容も作成したメディアタイプに対して送信します。

参考

http://pocketstudio.jp/log3/2013/06/07/zabbix-email-alerts-threadin/
ツリー化の参考情報

https://www.solutionary.com/resource-center/blog/2014/04/thread-index-value-analysis/
唯一のthreadindex解説だった

追加

https://github.com/130cmWolf/SampleSource/blob/master/Thread-Index/getThreadIndex.php
Thread-Index周りのサンプルコードを作成しました。
親、子、孫…関係のThread-Indexが生成できます。

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5